Skip to content

Commit 5ce8b70

Browse files
port absorbers
1 parent b780155 commit 5ce8b70

File tree

12 files changed

+894
-355
lines changed

12 files changed

+894
-355
lines changed

tests/test_components/test_absorbers.py

Lines changed: 463 additions & 0 deletions
Large diffs are not rendered by default.

tests/test_components/test_boundaries.py

Lines changed: 0 additions & 271 deletions
Original file line numberDiff line numberDiff line change
@@ -214,274 +214,3 @@ def test_num_layers_validator_warning(absorber_type, num_layers):
214214
_ = absorber_type(num_layers=num_layers)
215215
with AssertLogLevel("WARNING"):
216216
_ = absorber_type(num_layers=num_layers - 1)
217-
218-
219-
def test_abc_boundary():
220-
# check basic instance
221-
_ = td.ABCBoundary()
222-
223-
# check enforced perm (and conductivity)
224-
_ = td.ABCBoundary(permittivity=2)
225-
_ = td.ABCBoundary(permittivity=2, conductivity=0.1)
226-
227-
with pytest.raises(pydantic.ValidationError):
228-
_ = td.ABCBoundary(permittivity=0)
229-
230-
with pytest.raises(pydantic.ValidationError):
231-
_ = td.ABCBoundary(permittivity=2, conductivity=-0.1)
232-
233-
with pytest.raises(pydantic.ValidationError):
234-
_ = td.ABCBoundary(permittivity=None, conductivity=-0.1)
235-
236-
# test mode abc
237-
wvl_um = 1
238-
freq0 = td.C_0 / wvl_um
239-
mode_abc = td.ModeABCBoundary(
240-
plane=td.Box(size=(1, 1, 0)),
241-
mode_spec=td.ModeSpec(num_modes=2),
242-
mode_index=1,
243-
frequency=freq0,
244-
)
245-
246-
with pytest.raises(pydantic.ValidationError):
247-
_ = td.ModeABCBoundary(
248-
plane=td.Box(size=(1, 1, 0)),
249-
mode_spec=td.ModeSpec(num_modes=2),
250-
mode_index=1,
251-
frequency=-1,
252-
)
253-
254-
with pytest.raises(pydantic.ValidationError):
255-
_ = td.ModeABCBoundary(
256-
plane=td.Box(size=(1, 1, 0)),
257-
mode_spec=td.ModeSpec(num_modes=2),
258-
mode_index=-1,
259-
frequency=freq0,
260-
)
261-
262-
with pytest.raises(pydantic.ValidationError):
263-
_ = td.ModeABCBoundary(
264-
plane=td.Box(size=(1, 1, 1)),
265-
mode_spec=td.ModeSpec(num_modes=2),
266-
mode_index=0,
267-
frequency=freq0,
268-
)
269-
270-
# from mode source
271-
mode_source = td.ModeSource(
272-
size=(1, 1, 0),
273-
source_time=td.GaussianPulse(freq0=freq0, fwidth=0.2 * freq0),
274-
mode_spec=td.ModeSpec(num_modes=2),
275-
mode_index=1,
276-
direction="+",
277-
)
278-
mode_abc_from_source = td.ModeABCBoundary.from_source(mode_source)
279-
assert mode_abc == mode_abc_from_source
280-
281-
# from mode monitor
282-
mode_monitor = td.ModeMonitor(
283-
size=(1, 1, 0), mode_spec=td.ModeSpec(num_modes=2), freqs=[freq0], name="mnt"
284-
)
285-
mode_abc_from_monitor = td.ModeABCBoundary.from_monitor(
286-
mode_monitor, mode_index=1, frequency=freq0
287-
)
288-
assert mode_abc == mode_abc_from_monitor
289-
290-
# in Boundary
291-
_ = td.Boundary(
292-
minus=td.ABCBoundary(permittivity=3), plus=td.ModeABCBoundary(plane=td.Box(size=(1, 1, 0)))
293-
)
294-
_ = td.Boundary.abc(permittivity=3, conductivity=1e-5)
295-
abc_boundary = td.Boundary.mode_abc(
296-
plane=td.Box(size=(1, 1, 0)),
297-
mode_spec=td.ModeSpec(num_modes=2),
298-
mode_index=1,
299-
frequency=freq0,
300-
)
301-
abc_boundary_from_source = td.Boundary.mode_abc_from_source(mode_source)
302-
abc_boundary_from_monitor = td.Boundary.mode_abc_from_monitor(
303-
mode_monitor, mode_index=1, frequency=freq0
304-
)
305-
assert abc_boundary == abc_boundary_from_source
306-
assert abc_boundary == abc_boundary_from_monitor
307-
308-
with pytest.raises(pydantic.ValidationError):
309-
_ = td.Boundary(minus=td.Periodic(), plus=td.ABCBoundary())
310-
311-
with pytest.raises(pydantic.ValidationError):
312-
_ = td.Boundary(minus=td.Periodic(), plus=td.ModeABCBoundary(plane=td.Box(size=(1, 1, 0))))
313-
314-
# in Simulation
315-
_ = td.Simulation(
316-
center=[0, 0, 0],
317-
size=[1, 1, 1],
318-
grid_spec=td.GridSpec.auto(
319-
min_steps_per_wvl=10,
320-
wavelength=wvl_um,
321-
),
322-
sources=[],
323-
run_time=1e-20,
324-
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary()),
325-
)
326-
327-
# validate ABC medium is not anisotorpic
328-
with pytest.raises(pydantic.ValidationError):
329-
_ = td.Simulation(
330-
center=[0, 0, 0],
331-
size=[1, 1, 1],
332-
grid_spec=td.GridSpec.auto(
333-
min_steps_per_wvl=10,
334-
wavelength=wvl_um,
335-
),
336-
sources=[],
337-
medium=td.AnisotropicMedium(xx=td.Medium(), yy=td.Medium(), zz=td.Medium()),
338-
run_time=1e-20,
339-
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary()),
340-
)
341-
342-
# validate homogeneous medium when permittivity=None, that is, automatic detection
343-
box_crossing_boundary = td.Structure(
344-
geometry=td.Box(size=(0.3, 0.2, td.inf)),
345-
medium=td.Medium(permittivity=2),
346-
)
347-
# ok if ABC boundary is not crossed
348-
_ = td.Simulation(
349-
center=[0, 0, 0],
350-
size=[1, 1, 1],
351-
grid_spec=td.GridSpec.auto(
352-
min_steps_per_wvl=10,
353-
wavelength=wvl_um,
354-
),
355-
sources=[],
356-
structures=[box_crossing_boundary],
357-
run_time=1e-20,
358-
boundary_spec=td.BoundarySpec(
359-
x=td.Boundary.abc(),
360-
y=td.Boundary.abc(),
361-
z=td.Boundary.pml(),
362-
),
363-
)
364-
# or if we override manually
365-
_ = td.Simulation(
366-
center=[0, 0, 0],
367-
size=[1, 1, 1],
368-
grid_spec=td.GridSpec.auto(
369-
min_steps_per_wvl=10,
370-
wavelength=wvl_um,
371-
),
372-
sources=[],
373-
structures=[box_crossing_boundary],
374-
run_time=1e-20,
375-
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary(permittivity=2)),
376-
)
377-
# not ok if ABC boudary is crossed
378-
with pytest.raises(pydantic.ValidationError):
379-
_ = td.Simulation(
380-
center=[0, 0, 0],
381-
size=[1, 1, 1],
382-
grid_spec=td.GridSpec.auto(
383-
min_steps_per_wvl=10,
384-
wavelength=wvl_um,
385-
),
386-
sources=[],
387-
structures=[box_crossing_boundary],
388-
run_time=1e-20,
389-
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary()),
390-
)
391-
# edge case when a structure exactly coincides with simulation domain
392-
_ = td.Simulation(
393-
center=[0, 0, 0],
394-
size=[1, 1, 1],
395-
grid_spec=td.GridSpec.auto(
396-
min_steps_per_wvl=10,
397-
wavelength=wvl_um,
398-
),
399-
sources=[],
400-
structures=[box_crossing_boundary.updated_copy(geometry=td.Box(size=(1, 1, 1)))],
401-
run_time=1e-20,
402-
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary()),
403-
)
404-
405-
# warning for possibly non-uniform custom medium
406-
with AssertLogLevel(
407-
"WARNING", contains_str="Nonuniform custom medium detected on an 'ABCBoundary'"
408-
):
409-
_ = td.Simulation(
410-
center=[0, 0, 0],
411-
size=[1, 1, 1],
412-
grid_spec=td.GridSpec.auto(
413-
min_steps_per_wvl=10,
414-
wavelength=wvl_um,
415-
),
416-
sources=[],
417-
medium=td.CustomMedium(
418-
permittivity=td.SpatialDataArray([[[2, 3]]], coords=dict(x=[0], y=[0], z=[0, 1]))
419-
),
420-
run_time=1e-20,
421-
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary()),
422-
)
423-
424-
# disallow ABC boundaries in zero dimensions
425-
with pytest.raises(pydantic.ValidationError):
426-
_ = td.Simulation(
427-
center=[0, 0, 0],
428-
size=[1, 1, 0],
429-
grid_spec=td.GridSpec.auto(
430-
min_steps_per_wvl=10,
431-
wavelength=wvl_um,
432-
),
433-
sources=[],
434-
structures=[box_crossing_boundary],
435-
run_time=1e-20,
436-
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary()),
437-
)
438-
439-
# need to define frequence for ModeABCBoundary
440-
# manually
441-
_ = td.Simulation(
442-
center=[0, 0, 0],
443-
size=[1, 1, 1],
444-
grid_spec=td.GridSpec.auto(
445-
min_steps_per_wvl=10,
446-
wavelength=wvl_um,
447-
),
448-
sources=[],
449-
run_time=1e-20,
450-
boundary_spec=td.BoundarySpec.all_sides(
451-
td.ModeABCBoundary(plane=td.Box(size=(1, 1, 0)), frequency=freq0)
452-
),
453-
)
454-
# or at least one source
455-
_ = td.Simulation(
456-
center=[0, 0, 0],
457-
size=[1, 1, 1],
458-
grid_spec=td.GridSpec.auto(
459-
min_steps_per_wvl=10,
460-
wavelength=wvl_um,
461-
),
462-
sources=[mode_source],
463-
run_time=1e-20,
464-
boundary_spec=td.BoundarySpec.all_sides(td.ModeABCBoundary(plane=td.Box(size=(1, 1, 0)))),
465-
)
466-
# multiple sources with different central freqs is still ok, but show warning
467-
with AssertLogLevel(
468-
"WARNING", contains_str="The central frequency of the first source will be used"
469-
):
470-
_ = td.Simulation(
471-
center=[0, 0, 0],
472-
size=[1, 1, 1],
473-
grid_spec=td.GridSpec.auto(
474-
min_steps_per_wvl=10,
475-
wavelength=wvl_um,
476-
),
477-
sources=[
478-
mode_source,
479-
mode_source.updated_copy(
480-
source_time=td.GaussianPulse(freq0=2 * freq0, fwidth=0.2 * freq0)
481-
),
482-
],
483-
run_time=1e-20,
484-
boundary_spec=td.BoundarySpec.all_sides(
485-
td.ModeABCBoundary(plane=td.Box(size=(1, 1, 0)))
486-
),
487-
)

tidy3d/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
PMCBoundary,
121121
PMLParams,
122122
PMLTypes,
123+
PortAbsorber,
123124
StablePML,
124125
)
125126

@@ -635,6 +636,7 @@ def set_logging_level(level: str) -> None:
635636
"PolarizedAveraging",
636637
"PoleResidue",
637638
"PolySlab",
639+
"PortAbsorber",
638640
"Q_e",
639641
"QuasiUniformGrid",
640642
"RLCNetwork",

0 commit comments

Comments
 (0)