Skip to content

Commit 9fd5ed4

Browse files
clean up
1 parent 37a3e60 commit 9fd5ed4

File tree

5 files changed

+83
-18
lines changed

5 files changed

+83
-18
lines changed

tests/test_components/test_absorbers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ def test_abc_boundaries_broadband():
557557
_ = td.BroadbandModeABCFitterParam(frequency_sampling_points=0)
558558
# test frequency sampling points <= 21
559559
with pytest.raises(pydantic.ValidationError):
560-
_ = td.BroadbandModeABCFitterParam(frequency_sampling_points=22)
560+
_ = td.BroadbandModeABCFitterParam(frequency_sampling_points=102)
561561

562562
# test basic instance
563563
fmin = 100e12

tests/test_plugins/smatrix/test_terminal_component_modeler.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import xarray as xr
99

1010
import tidy3d as td
11+
from tidy3d.components.boundary import BroadbandModeABCSpec
1112
from tidy3d.components.data.data_array import FreqDataArray
1213
from tidy3d.exceptions import SetupError, Tidy3dError, Tidy3dKeyError
1314
from tidy3d.plugins.microwave import (
@@ -1296,3 +1297,45 @@ def check_S_matrix(S_computed, S_expected, tol=1e-12):
12961297
# Check power wave S matrix
12971298
S_computed = modeler._internal_construct_smatrix(batch_data, s_param_def="power").values
12981299
check_S_matrix(S_computed, S_power)
1300+
1301+
1302+
def test_wave_port_to_absorber(tmp_path):
1303+
"""Test that wave port absorber can be specified as a boolean, ABCBoundary, or ModeABCBoundary."""
1304+
1305+
# test automatic absorber
1306+
modeler = make_coaxial_component_modeler(
1307+
path_dir=str(tmp_path), port_types=(WavePort, WavePort)
1308+
)
1309+
sim = list(modeler.sim_dict.values())[0]
1310+
1311+
absorber = sim.internal_absorbers[0]
1312+
1313+
assert absorber.boundary_spec.mode_spec == modeler.ports[0].mode_spec
1314+
assert absorber.boundary_spec.mode_index == modeler.ports[0].mode_index
1315+
assert absorber.boundary_spec.plane == modeler.ports[0].geometry
1316+
assert absorber.boundary_spec.freq_spec == BroadbandModeABCSpec(
1317+
frequency_range=(np.min(modeler.freqs), np.max(modeler.freqs))
1318+
)
1319+
1320+
# test to_absorber()
1321+
absorber = modeler.ports[0].to_absorber(freq_spec=1e9)
1322+
assert absorber.boundary_spec.freq_spec == 1e9
1323+
1324+
absorber = modeler.ports[0].to_absorber(
1325+
freq_spec=BroadbandModeABCSpec(frequency_range=(1e9, 2e9))
1326+
)
1327+
assert absorber.boundary_spec.freq_spec == BroadbandModeABCSpec(frequency_range=(1e9, 2e9))
1328+
1329+
# test no automatic absorber
1330+
modeler = modeler.updated_copy(ports=[modeler.ports[0].updated_copy(absorber=False)])
1331+
sim = list(modeler.sim_dict.values())[0]
1332+
assert len(sim.internal_absorbers) == 0
1333+
1334+
# test custom boundary spec
1335+
custom_boundary_spec = td.ModeABCBoundary(plane=td.Box(size=(0.1, 0.1, 0)), freq_spec=1e9)
1336+
modeler = modeler.updated_copy(
1337+
ports=[modeler.ports[0].updated_copy(absorber=custom_boundary_spec)]
1338+
)
1339+
sim = list(modeler.sim_dict.values())[0]
1340+
absorber = sim.internal_absorbers[0]
1341+
assert absorber.boundary_spec == custom_boundary_spec

tidy3d/components/boundary.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def _warn_num_layers(cls, val):
5959
DEFAULT_BROADBAND_MODE_ABC_NUM_FREQS = 15
6060
DEFAULT_BROADBAND_MODE_ABC_NUM_POLES = 5
6161
MAX_BROADBAND_MODE_ABC_NUM_POLES = 10
62-
MAX_BROADBAND_MODE_ABC_NUM_FREQS = 21
62+
MAX_BROADBAND_MODE_ABC_NUM_FREQS = 101
6363

6464

6565
class BoundaryEdge(ABC, Tidy3dBaseModel):
@@ -175,7 +175,7 @@ class BroadbandModeABCSpec(Tidy3dBaseModel):
175175
176176
Example
177177
-------
178-
>>> broadband_mode_abc_spec = BroadbandModeABCSpec(frequency_range=(fmin=100e12, fmax=120e12), fit_param=BroadbandModeABCFitterParam())
178+
>>> broadband_mode_abc_spec = BroadbandModeABCSpec(frequency_range=(100e12, 120e12), fit_param=BroadbandModeABCFitterParam())
179179
"""
180180

181181
frequency_range: FreqBound = pd.Field(
@@ -273,13 +273,19 @@ def is_plane(cls, val):
273273
return val
274274

275275
@classmethod
276-
def from_source(cls, source: ModeSource) -> ModeABCBoundary:
276+
def from_source(
277+
cls,
278+
source: ModeSource,
279+
freq_spec: Optional[Union[pd.PositiveFloat, BroadbandModeABCSpec]] = None,
280+
) -> ModeABCBoundary:
277281
"""Instantiate from a ``ModeSource``.
278282
279283
Parameters
280284
----------
281285
source : :class:`ModeSource`
282286
Mode source.
287+
freq_spec : Optional[Union[pd.PositiveFloat, BroadbandModeABCSpec]] = None
288+
Specifies the frequency at which field is absorbed. If ``None``, then the central frequency of the source is used. If ``BroadbandModeABCSpec``, then the field is absorbed over the specified frequency range.
283289
284290
Returns
285291
-------
@@ -294,11 +300,14 @@ def from_source(cls, source: ModeSource) -> ModeABCBoundary:
294300
>>> abc_boundary = ModeABCBoundary.from_source(source=source)
295301
"""
296302

303+
if freq_spec is None:
304+
freq_spec = source.source_time.freq0
305+
297306
return cls(
298307
plane=source.bounding_box,
299308
mode_spec=source.mode_spec,
300309
mode_index=source.mode_index,
301-
freq_spec=source.source_time.freq0,
310+
freq_spec=freq_spec,
302311
)
303312

304313
@classmethod
@@ -1137,13 +1146,19 @@ def mode_abc(
11371146
return cls(plus=plus, minus=minus)
11381147

11391148
@classmethod
1140-
def mode_abc_from_source(cls, source: ModeSource):
1149+
def mode_abc_from_source(
1150+
cls,
1151+
source: ModeSource,
1152+
freq_spec: Optional[Union[pd.PositiveFloat, BroadbandModeABCSpec]] = None,
1153+
):
11411154
"""One-way wave equation mode ABC boundary specification on both sides along a dimension constructed from a mode source.
11421155
11431156
Parameters
11441157
----------
11451158
source : :class:`ModeSource`
11461159
Mode source.
1160+
freq_spec : Optional[Union[pd.PositiveFloat, BroadbandModeABCSpec]] = None
1161+
Specifies the frequency at which field is absorbed. If ``None``, then the central frequency of the source is used. If ``BroadbandModeABCSpec``, then the field is absorbed over the specified frequency range.
11471162
11481163
Example
11491164
-------
@@ -1152,8 +1167,8 @@ def mode_abc_from_source(cls, source: ModeSource):
11521167
>>> source = ModeSource(size=(1, 1, 0), source_time=pulse, direction='+')
11531168
>>> abc = Boundary.mode_abc_from_source(source=source)
11541169
"""
1155-
plus = ModeABCBoundary.from_source(source=source)
1156-
minus = ModeABCBoundary.from_source(source=source)
1170+
plus = ModeABCBoundary.from_source(source=source, freq_spec=freq_spec)
1171+
minus = ModeABCBoundary.from_source(source=source, freq_spec=freq_spec)
11571172
return cls(plus=plus, minus=minus)
11581173

11591174
@classmethod

tidy3d/plugins/smatrix/component_modelers/terminal.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,9 @@ def base_sim(self) -> Simulation:
255255
] + self._shift_value_signed(wave_port)
256256
port_absorber = wave_port.to_absorber(
257257
snap_center=mode_src_pos,
258-
freq_spec=BroadbandModeABCSpec(frequency_range=(self.freqs, self.freqs)),
258+
freq_spec=BroadbandModeABCSpec(
259+
frequency_range=(np.min(self.freqs), np.max(self.freqs))
260+
),
259261
)
260262
new_absorbers.append(port_absorber)
261263

tidy3d/plugins/smatrix/ports/wave.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import pydantic.v1 as pd
99

1010
from tidy3d.components.base import cached_property, skip_if_fields_missing
11-
from tidy3d.components.boundary import InternalAbsorber, ModeABCBoundary
11+
from tidy3d.components.boundary import ABCBoundary, InternalAbsorber, ModeABCBoundary
1212
from tidy3d.components.data.data_array import FreqDataArray, FreqModeDataArray
1313
from tidy3d.components.data.monitor_data import ModeData
1414
from tidy3d.components.data.sim_data import SimulationData
@@ -91,10 +91,11 @@ class WavePort(AbstractTerminalPort, Box):
9191
description="Add a thin frame around the source during FDTD run for an improved injection.",
9292
)
9393

94-
absorber: bool = pd.Field(
94+
absorber: Union[bool, ABCBoundary, ModeABCBoundary] = pd.Field(
9595
True,
9696
title="Absorber.",
97-
description="Place a mode absorber in the port.",
97+
description="Place a mode absorber in the port. If ``True``, an automatically generated mode absorber is placed in the port. "
98+
"If ``ABCBoundary`` or ``ModeABCBoundary``, a mode absorber is placed in the port with the specified boundary conditions.",
9899
)
99100

100101
def _mode_voltage_coefficients(self, mode_data: ModeData) -> FreqModeDataArray:
@@ -199,15 +200,19 @@ def to_absorber(
199200
center = list(self.center)
200201
if snap_center:
201202
center[self.injection_axis] = snap_center
203+
if isinstance(self.absorber, (ABCBoundary, ModeABCBoundary)):
204+
boundary_spec = self.absorber
205+
else:
206+
boundary_spec = ModeABCBoundary(
207+
mode_spec=self.mode_spec,
208+
mode_index=self.mode_index,
209+
plane=self.geometry,
210+
freq_spec=freq_spec,
211+
)
202212
return InternalAbsorber(
203213
center=center,
204214
size=self.size,
205-
boundary_spec=ModeABCBoundary(
206-
mode_spec=self.mode_spec,
207-
mode_index=self.mode_index,
208-
plane=self.bounding_box,
209-
frequency=freq_spec,
210-
),
215+
boundary_spec=boundary_spec,
211216
direction="-"
212217
if self.direction == "+"
213218
else "+", # absorb in the opposite direction of source

0 commit comments

Comments
 (0)