Skip to content

Commit 826ee5f

Browse files
small reorg
1 parent 876fdf5 commit 826ee5f

File tree

3 files changed

+256
-279
lines changed

3 files changed

+256
-279
lines changed

tests/test_components/test_boundaries.py

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,259 @@ def test_boundaryspec_classmethods():
185185
assert all(
186186
isinstance(boundary, PML) for boundary_dim in boundaries for boundary in boundary_dim
187187
)
188+
189+
190+
def test_abc_boundary():
191+
# check basic instance
192+
_ = td.ABCBoundary()
193+
194+
# check enforced perm (and conductivity)
195+
_ = td.ABCBoundary(permittivity=2)
196+
_ = td.ABCBoundary(permittivity=2, conductivity=0.1)
197+
198+
with pytest.raises(pydantic.ValidationError):
199+
_ = td.ABCBoundary(permittivity=0)
200+
201+
with pytest.raises(pydantic.ValidationError):
202+
_ = td.ABCBoundary(permittivity=2, conductivity=-0.1)
203+
204+
with pytest.raises(pydantic.ValidationError):
205+
_ = td.ABCBoundary(permittivity=None, conductivity=-0.1)
206+
207+
# test abc mode spec
208+
wvl_um = 1
209+
freq0 = td.C_0 / wvl_um
210+
abc_mode_spec = td.ABCModeSpec(
211+
size=(1, 1, 0),
212+
mode_spec=td.ModeSpec(num_modes=2),
213+
mode_index=1,
214+
frequency=freq0,
215+
)
216+
217+
with pytest.raises(pydantic.ValidationError):
218+
_ = td.ABCModeSpec(
219+
size=(1, 1, 0),
220+
mode_spec=td.ModeSpec(num_modes=2),
221+
mode_index=1,
222+
frequency=-1,
223+
)
224+
225+
with pytest.raises(pydantic.ValidationError):
226+
_ = td.ABCModeSpec(
227+
size=(1, 1, 0),
228+
mode_spec=td.ModeSpec(num_modes=2),
229+
mode_index=-1,
230+
frequency=freq0,
231+
)
232+
233+
with pytest.raises(pydantic.ValidationError):
234+
_ = td.ABCModeSpec(
235+
size=(1, 1, 1),
236+
mode_spec=td.ModeSpec(num_modes=2),
237+
mode_index=0,
238+
frequency=freq0,
239+
)
240+
241+
# from mode source
242+
mode_source = td.ModeSource(
243+
size=(1, 1, 0),
244+
source_time=td.GaussianPulse(freq0=freq0, fwidth=0.2 * freq0),
245+
mode_spec=td.ModeSpec(num_modes=2),
246+
mode_index=1,
247+
direction="+",
248+
)
249+
250+
abc_mode_spec_from_source = td.ABCModeSpec.from_source(mode_source)
251+
252+
assert abc_mode_spec == abc_mode_spec_from_source
253+
254+
_ = td.ABCBoundary(permittivity=abc_mode_spec)
255+
256+
with pytest.raises(pydantic.ValidationError):
257+
_ = td.ABCBoundary(permittivity=abc_mode_spec, conductivity=0.1)
258+
259+
# in Boundary
260+
_ = td.Boundary(
261+
minus=td.ABCBoundary(permittivity=3), plus=td.ABCBoundary(permittivity=abc_mode_spec)
262+
)
263+
_ = td.Boundary.abc(permittivity=3, conductivity=1e-5)
264+
265+
with pytest.raises(pydantic.ValidationError):
266+
_ = td.Boundary(minus=td.Periodic(), plus=td.ABCBoundary(permittivity=abc_mode_spec))
267+
268+
# in Simulation
269+
_ = td.Simulation(
270+
center=[0, 0, 0],
271+
size=[1, 1, 1],
272+
grid_spec=td.GridSpec.auto(
273+
min_steps_per_wvl=10,
274+
wavelength=wvl_um,
275+
),
276+
sources=[],
277+
run_time=1e-20,
278+
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary()),
279+
)
280+
281+
# validate ABC medium is not anisotorpic
282+
with pytest.raises(pydantic.ValidationError):
283+
_ = td.Simulation(
284+
center=[0, 0, 0],
285+
size=[1, 1, 1],
286+
grid_spec=td.GridSpec.auto(
287+
min_steps_per_wvl=10,
288+
wavelength=wvl_um,
289+
),
290+
sources=[],
291+
medium=td.AnisotropicMedium(xx=td.Medium(), yy=td.Medium(), zz=td.Medium()),
292+
run_time=1e-20,
293+
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary()),
294+
)
295+
296+
# validate homogeneous medium when permittivity=None, that is, automatic detection
297+
box_crossing_boundary = td.Structure(
298+
geometry=td.Box(size=(0.3, 0.2, td.inf)),
299+
medium=td.Medium(permittivity=2),
300+
)
301+
# ok if ABC boundary is not crossed
302+
_ = td.Simulation(
303+
center=[0, 0, 0],
304+
size=[1, 1, 1],
305+
grid_spec=td.GridSpec.auto(
306+
min_steps_per_wvl=10,
307+
wavelength=wvl_um,
308+
),
309+
sources=[],
310+
structures=[box_crossing_boundary],
311+
run_time=1e-20,
312+
boundary_spec=td.BoundarySpec(
313+
x=td.Boundary.abc(),
314+
y=td.Boundary.abc(),
315+
z=td.Boundary.pml(),
316+
),
317+
)
318+
# or if we override manually
319+
_ = td.Simulation(
320+
center=[0, 0, 0],
321+
size=[1, 1, 1],
322+
grid_spec=td.GridSpec.auto(
323+
min_steps_per_wvl=10,
324+
wavelength=wvl_um,
325+
),
326+
sources=[],
327+
structures=[box_crossing_boundary],
328+
run_time=1e-20,
329+
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary(permittivity=2)),
330+
)
331+
# not ok if ABC boudary is crossed
332+
with pytest.raises(pydantic.ValidationError):
333+
_ = td.Simulation(
334+
center=[0, 0, 0],
335+
size=[1, 1, 1],
336+
grid_spec=td.GridSpec.auto(
337+
min_steps_per_wvl=10,
338+
wavelength=wvl_um,
339+
),
340+
sources=[],
341+
structures=[box_crossing_boundary],
342+
run_time=1e-20,
343+
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary()),
344+
)
345+
# edge case when a structure exactly coincides with simulation domain
346+
_ = td.Simulation(
347+
center=[0, 0, 0],
348+
size=[1, 1, 1],
349+
grid_spec=td.GridSpec.auto(
350+
min_steps_per_wvl=10,
351+
wavelength=wvl_um,
352+
),
353+
sources=[],
354+
structures=[box_crossing_boundary.updated_copy(geometry=td.Box(size=(1, 1, 1)))],
355+
run_time=1e-20,
356+
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary()),
357+
)
358+
359+
# warning for possibly non-uniform custom medium
360+
with AssertLogLevel(
361+
"WARNING", contains_str="Nonuniform custom medium detected on an 'ABCBoundary'"
362+
):
363+
_ = td.Simulation(
364+
center=[0, 0, 0],
365+
size=[1, 1, 1],
366+
grid_spec=td.GridSpec.auto(
367+
min_steps_per_wvl=10,
368+
wavelength=wvl_um,
369+
),
370+
sources=[],
371+
medium=td.CustomMedium(
372+
permittivity=td.SpatialDataArray([[[2, 3]]], coords=dict(x=[0], y=[0], z=[0, 1]))
373+
),
374+
run_time=1e-20,
375+
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary()),
376+
)
377+
378+
# disallow ABC boundaries in zero dimensions
379+
with pytest.raises(pydantic.ValidationError):
380+
_ = td.Simulation(
381+
center=[0, 0, 0],
382+
size=[1, 1, 0],
383+
grid_spec=td.GridSpec.auto(
384+
min_steps_per_wvl=10,
385+
wavelength=wvl_um,
386+
),
387+
sources=[],
388+
structures=[box_crossing_boundary],
389+
run_time=1e-20,
390+
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary()),
391+
)
392+
393+
# need to define frequence for ABCModeSpec
394+
# manually
395+
_ = td.Simulation(
396+
center=[0, 0, 0],
397+
size=[1, 1, 1],
398+
grid_spec=td.GridSpec.auto(
399+
min_steps_per_wvl=10,
400+
wavelength=wvl_um,
401+
),
402+
sources=[],
403+
run_time=1e-20,
404+
boundary_spec=td.BoundarySpec.all_sides(
405+
td.ABCBoundary(permittivity=td.ABCModeSpec(size=(1, 1, 0), frequency=freq0))
406+
),
407+
)
408+
# or at least one source
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=[mode_source],
417+
run_time=1e-20,
418+
boundary_spec=td.BoundarySpec.all_sides(
419+
td.ABCBoundary(permittivity=td.ABCModeSpec(size=(1, 1, 0)))
420+
),
421+
)
422+
# multiple sources with different central freqs is still ok, but show warning
423+
with AssertLogLevel(
424+
"WARNING", contains_str="The central frequency of the first source will be used"
425+
):
426+
_ = td.Simulation(
427+
center=[0, 0, 0],
428+
size=[1, 1, 1],
429+
grid_spec=td.GridSpec.auto(
430+
min_steps_per_wvl=10,
431+
wavelength=wvl_um,
432+
),
433+
sources=[
434+
mode_source,
435+
mode_source.updated_copy(
436+
source_time=td.GaussianPulse(freq0=2 * freq0, fwidth=0.2 * freq0)
437+
),
438+
],
439+
run_time=1e-20,
440+
boundary_spec=td.BoundarySpec.all_sides(
441+
td.ABCBoundary(permittivity=td.ABCModeSpec(size=(1, 1, 0)))
442+
),
443+
)

0 commit comments

Comments
 (0)