Skip to content

Commit 935ddd4

Browse files
a stricter check for missing frequency
1 parent cfeed7f commit 935ddd4

File tree

4 files changed

+104
-18
lines changed

4 files changed

+104
-18
lines changed

tests/test_components/test_absorbers.py

Lines changed: 74 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ def test_abc_boundaries_simulations():
298298
min_steps_per_wvl=10,
299299
wavelength=wvl_um,
300300
),
301-
sources=[],
301+
sources=[mode_source],
302302
run_time=1e-20,
303303
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary()),
304304
)
@@ -313,7 +313,7 @@ def test_abc_boundaries_simulations():
313313
min_steps_per_wvl=10,
314314
wavelength=wvl_um,
315315
),
316-
sources=[],
316+
sources=[mode_source],
317317
medium=td.AnisotropicMedium(xx=td.Medium(), yy=td.Medium(), zz=td.Medium()),
318318
run_time=1e-20,
319319
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary()),
@@ -332,7 +332,7 @@ def test_abc_boundaries_simulations():
332332
min_steps_per_wvl=10,
333333
wavelength=wvl_um,
334334
),
335-
sources=[],
335+
sources=[mode_source],
336336
structures=[box_crossing_boundary],
337337
run_time=1e-20,
338338
boundary_spec=td.BoundarySpec(
@@ -349,7 +349,7 @@ def test_abc_boundaries_simulations():
349349
min_steps_per_wvl=10,
350350
wavelength=wvl_um,
351351
),
352-
sources=[],
352+
sources=[mode_source],
353353
structures=[box_crossing_boundary],
354354
run_time=1e-20,
355355
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary(permittivity=2)),
@@ -363,7 +363,7 @@ def test_abc_boundaries_simulations():
363363
min_steps_per_wvl=10,
364364
wavelength=wvl_um,
365365
),
366-
sources=[],
366+
sources=[mode_source],
367367
structures=[box_crossing_boundary],
368368
run_time=1e-20,
369369
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary()),
@@ -376,7 +376,7 @@ def test_abc_boundaries_simulations():
376376
min_steps_per_wvl=10,
377377
wavelength=wvl_um,
378378
),
379-
sources=[],
379+
sources=[mode_source],
380380
structures=[box_crossing_boundary.updated_copy(geometry=td.Box(size=(1, 1, 1)))],
381381
run_time=1e-20,
382382
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary()),
@@ -393,7 +393,7 @@ def test_abc_boundaries_simulations():
393393
min_steps_per_wvl=10,
394394
wavelength=wvl_um,
395395
),
396-
sources=[],
396+
sources=[mode_source],
397397
medium=td.CustomMedium(
398398
permittivity=td.SpatialDataArray(
399399
[[[2, 3]]], coords={"x": [0], "y": [0], "z": [0, 1]}
@@ -412,7 +412,7 @@ def test_abc_boundaries_simulations():
412412
min_steps_per_wvl=10,
413413
wavelength=wvl_um,
414414
),
415-
sources=[],
415+
sources=[mode_source],
416416
structures=[box_crossing_boundary],
417417
run_time=1e-20,
418418
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary()),
@@ -467,3 +467,69 @@ def test_abc_boundaries_simulations():
467467
td.ModeABCBoundary(plane=td.Box(size=(1, 1, 0)))
468468
),
469469
)
470+
# error if no frequency
471+
with pytest.raises(pydantic.ValidationError):
472+
_ = td.Simulation(
473+
center=[0, 0, 0],
474+
size=[1, 1, 1],
475+
grid_spec=td.GridSpec.auto(
476+
min_steps_per_wvl=10,
477+
wavelength=wvl_um,
478+
),
479+
sources=[],
480+
run_time=1e-20,
481+
boundary_spec=td.BoundarySpec.all_sides(
482+
td.ModeABCBoundary(plane=td.Box(size=(1, 1, 0)))
483+
),
484+
)
485+
# error if no frequency for automatic abc from interesected mediums
486+
with pytest.raises(pydantic.ValidationError):
487+
_ = td.Simulation(
488+
center=[0, 0, 0],
489+
size=[1, 1, 1],
490+
grid_spec=td.GridSpec.auto(
491+
min_steps_per_wvl=10,
492+
wavelength=wvl_um,
493+
),
494+
sources=[],
495+
run_time=1e-20,
496+
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary()),
497+
)
498+
# ok if abc with permittivity only
499+
_ = td.Simulation(
500+
center=[0, 0, 0],
501+
size=[1, 1, 1],
502+
grid_spec=td.GridSpec.auto(
503+
min_steps_per_wvl=10,
504+
wavelength=wvl_um,
505+
),
506+
sources=[],
507+
run_time=1e-20,
508+
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary(permittivity=2)),
509+
)
510+
_ = td.Simulation(
511+
center=[0, 0, 0],
512+
size=[1, 1, 1],
513+
grid_spec=td.GridSpec.auto(
514+
min_steps_per_wvl=10,
515+
wavelength=wvl_um,
516+
),
517+
sources=[],
518+
run_time=1e-20,
519+
boundary_spec=td.BoundarySpec.all_sides(td.ABCBoundary(permittivity=2, conductivity=0)),
520+
)
521+
# not ok if non-zerp conductivity
522+
with pytest.raises(pydantic.ValidationError):
523+
_ = td.Simulation(
524+
center=[0, 0, 0],
525+
size=[1, 1, 1],
526+
grid_spec=td.GridSpec.auto(
527+
min_steps_per_wvl=10,
528+
wavelength=wvl_um,
529+
),
530+
sources=[],
531+
run_time=1e-20,
532+
boundary_spec=td.BoundarySpec.all_sides(
533+
td.ABCBoundary(permittivity=2, conductivity=1e-5)
534+
),
535+
)

tidy3d/components/simulation.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3101,21 +3101,34 @@ def check_fixed_angle_components(cls, values):
31013101
@skip_if_fields_missing(["sources", "boundary_spec", "internal_absorbers"], root=True)
31023102
def _validate_frequency_mode_abc(cls, values):
31033103
"""Warn if ModeABCBoundary expects a frequency from a source, but there are multiple sources with different central frequencies."""
3104+
3105+
def boundary_needs_freq(boundary):
3106+
return (isinstance(boundary, ModeABCBoundary) and boundary.frequency is None) or (
3107+
isinstance(boundary, ABCBoundary)
3108+
and (
3109+
(boundary.conductivity is not None and boundary.conductivity != 0)
3110+
or (boundary.permittivity is None and boundary.conductivity is None)
3111+
)
3112+
)
3113+
3114+
# check domain boundaries
31043115
boundaries = values["boundary_spec"].to_list
3105-
need_wavelength = any(
3106-
isinstance(edge, ModeABCBoundary) and edge.frequency is None
3107-
for edge in np.ravel(boundaries)
3108-
)
3116+
need_wavelength = any(boundary_needs_freq(edge) for edge in np.ravel(boundaries))
31093117

3118+
# check dinternal absorbers
31103119
need_wavelength = need_wavelength or any(
3111-
isinstance(port_abc.boundary_spec, ModeABCBoundary)
3112-
and port_abc.boundary_spec.frequency is None
3113-
for port_abc in values["internal_absorbers"]
3120+
boundary_needs_freq(abc.boundary_spec) for abc in values["internal_absorbers"]
31143121
)
31153122

31163123
if need_wavelength:
31173124
sources = values.get("sources")
31183125

3126+
if len(sources) == 0:
3127+
raise SetupError(
3128+
"At least one 'ModeABCBoundary'/'ABCBoundary' needs specification of frequency at which the absorbed mode must be evaluated. "
3129+
"Add at least one source or use parameter 'frequency' for 'ModeABCBoundary'.",
3130+
)
3131+
31193132
freq0s = [source.source_time.freq0 for source in sources]
31203133
if not all(math.isclose(freq0, freq0s[0]) for freq0 in freq0s):
31213134
log.warning(

tidy3d/plugins/smatrix/component_modelers/terminal.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,9 @@ def base_sim(self) -> Simulation:
252252
mode_src_pos = wave_port.center[
253253
wave_port.injection_axis
254254
] + self._shift_value_signed(wave_port)
255-
port_absorber = wave_port.to_absorber(snap_center=mode_src_pos)
255+
port_absorber = wave_port.to_absorber(
256+
snap_center=mode_src_pos, frequency=0.5 * (min(self.freqs) + max(self.freqs))
257+
)
256258
new_absorbers.append(port_absorber)
257259

258260
update_dict = {

tidy3d/plugins/smatrix/ports/wave.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,9 @@ def to_mode_solver(self, simulation: Simulation, freqs: FreqArray) -> ModeSolver
192192
)
193193
return mode_solver
194194

195-
def to_absorber(self, snap_center: Optional[float] = None) -> InternalAbsorber:
195+
def to_absorber(
196+
self, snap_center: Optional[float] = None, frequency: Optional[pd.NonNegativeFloat] = None
197+
) -> InternalAbsorber:
196198
"""Create an internal absorber from the wave port."""
197199
center = list(self.center)
198200
if snap_center:
@@ -201,7 +203,10 @@ def to_absorber(self, snap_center: Optional[float] = None) -> InternalAbsorber:
201203
center=center,
202204
size=self.size,
203205
boundary_spec=ModeABCBoundary(
204-
mode_spec=self.mode_spec, mode_index=self.mode_index, plane=self.bounding_box
206+
mode_spec=self.mode_spec,
207+
mode_index=self.mode_index,
208+
plane=self.bounding_box,
209+
frequency=frequency,
205210
),
206211
direction="-"
207212
if self.direction == "+"

0 commit comments

Comments
 (0)