Skip to content

Commit a50bd5b

Browse files
caseyflexyaugenst-flex
authored andcommitted
Fix bug in EME simulations with bends
1 parent ed876dd commit a50bd5b

File tree

7 files changed

+64
-30
lines changed

7 files changed

+64
-30
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2222
- Fixed shaping of `CustomMedium` gradients when permittivity data includes a frequency dimension with multiple entries.
2323
- Bug in contains check for `LumpedElement`, which should allow the case of a `LumpedElement` touching the simulation boundaries.
2424
- Bug when generating a grid with snapping points near the simulation boundaries.
25+
- Solver error for EME simulations with bends, introduced when support for 2D EME simulations was added.
2526

2627
### Changed
2728
- Relaxed bounds checking of path integrals during `WavePort` validation.

tests/test_components/test_monitor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ def test_mode_bend_radius():
309309
size=(5, 0, 1),
310310
freqs=np.linspace(1e14, 2e14, 100),
311311
name="test",
312-
mode_spec=td.ModeSpec(num_modes=1, bend_radius=1, bend_axis=1),
312+
mode_spec=td.ModeSpec(num_modes=1, bend_radius=1, bend_axis=2),
313313
)
314314
_ = td.Simulation(
315315
size=(2, 2, 2),

tests/test_plugins/test_mode_solver.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1131,13 +1131,29 @@ def test_modes_eme_sim(mock_remote_api, local):
11311131

11321132
def test_mode_small_bend_radius_fail():
11331133
"""Test that small bend radius fails."""
1134-
1134+
simulation = td.Simulation(
1135+
size=SIM_SIZE,
1136+
grid_spec=td.GridSpec(wavelength=1.0),
1137+
structures=[WAVEGUIDE],
1138+
run_time=1e-12,
1139+
symmetry=(1, 0, -1),
1140+
boundary_spec=td.BoundarySpec.all_sides(boundary=td.Periodic()),
1141+
sources=[SRC],
1142+
)
11351143
with pytest.raises(ValueError):
11361144
ms = ModeSolver(
11371145
plane=PLANE,
11381146
freqs=np.linspace(1e14, 2e14, 100),
11391147
mode_spec=td.ModeSpec(num_modes=1, bend_radius=1, bend_axis=0),
1148+
simulation=simulation,
11401149
)
1150+
# should work for infinite mode plane
1151+
ms = ModeSolver(
1152+
plane=td.Box(center=(0, 0, 0), size=(td.inf, 0, td.inf)),
1153+
freqs=np.linspace(1e14, 2e14, 100),
1154+
mode_spec=td.ModeSpec(num_modes=1, bend_radius=10000, bend_axis=0),
1155+
simulation=simulation,
1156+
)
11411157

11421158

11431159
def make_high_order_mode_solver(sign, dim=3):

tidy3d/components/mode/mode_solver.py

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@
5656
from tidy3d.components.validators import (
5757
validate_freqs_min,
5858
validate_freqs_not_empty,
59-
validate_mode_plane_radius,
6059
)
6160
from tidy3d.components.viz import make_ax, plot_params_pml
6261
from tidy3d.constants import C_0
@@ -211,8 +210,11 @@ def plane_in_sim_bounds(cls, val, values):
211210
return val
212211

213212
def _post_init_validators(self) -> None:
214-
validate_mode_plane_radius(
215-
mode_spec=self.mode_spec, plane=self.plane, msg_prefix="Mode solver"
213+
self._validate_mode_plane_radius(
214+
mode_spec=self.mode_spec,
215+
plane=self.plane,
216+
sim_geom=self.simulation.geometry,
217+
msg_prefix="Mode solver",
216218
)
217219
self._warn_thick_pml(simulation=self.simulation, plane=self.plane, mode_spec=self.mode_spec)
218220

@@ -239,6 +241,35 @@ def _warn_thick_pml(
239241
"or smaller 'num_pml'."
240242
)
241243

244+
@staticmethod
245+
def _mode_plane(plane: Box, sim_geom: Box) -> Box:
246+
"""Intersect the mode plane with the sim geometry to get the effective
247+
mode plane."""
248+
mode_plane_bnds = plane.bounds_intersection(plane.bounds, sim_geom.bounds)
249+
return Box.from_bounds(*mode_plane_bnds)
250+
251+
@classmethod
252+
def _validate_mode_plane_radius(
253+
cls, mode_spec: ModeSpec, plane: Box, sim_geom: Box, msg_prefix: str = ""
254+
):
255+
"""Validate that the radius of a mode spec with a bend is not smaller than half the size of
256+
the plane along the radial direction."""
257+
258+
if not mode_spec.bend_radius:
259+
return
260+
261+
mode_plane = cls._mode_plane(plane=plane, sim_geom=sim_geom)
262+
263+
# radial axis is the plane axis that is not the bend axis
264+
_, plane_axs = mode_plane.pop_axis([0, 1, 2], mode_plane.size.index(0.0))
265+
radial_ax = plane_axs[(mode_spec.bend_axis + 1) % 2]
266+
267+
if np.abs(mode_spec.bend_radius) < mode_plane.size[radial_ax] / 2:
268+
raise ValueError(
269+
f"{msg_prefix} bend radius is smaller than half the mode plane size "
270+
"along the radial axis, which can produce wrong results."
271+
)
272+
242273
@cached_property
243274
def normal_axis(self) -> Axis:
244275
"""Axis normal to the mode plane."""

tidy3d/components/mode/simulation.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
)
2222
from tidy3d.components.source.field import ModeSource
2323
from tidy3d.components.types import TYPE_TAG_STR, Ax, Direction, EMField, FreqArray
24-
from tidy3d.components.validators import validate_mode_plane_radius
2524
from tidy3d.constants import C_0
2625
from tidy3d.exceptions import SetupError, ValidationError
2726
from tidy3d.log import log
@@ -228,8 +227,11 @@ def boundaries_for_zero_dims(cls, val, values):
228227

229228
def _post_init_validators(self) -> None:
230229
"""Call validators taking `self` that get run after init."""
231-
validate_mode_plane_radius(
232-
mode_spec=self.mode_spec, plane=self.plane, msg_prefix="'ModeSimulation'"
230+
ModeSolver._validate_mode_plane_radius(
231+
mode_spec=self.mode_spec,
232+
plane=self.plane,
233+
sim_geom=self.geometry,
234+
msg_prefix="'ModeSimulation'",
233235
)
234236
_ = self._mode_solver
235237
_ = self.grid

tidy3d/components/simulation.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@
118118
assert_objects_contained_in_sim_bounds,
119119
assert_objects_in_sim_bounds,
120120
validate_mode_objects_symmetry,
121-
validate_mode_plane_radius,
122121
)
123122
from .viz import (
124123
PlotParams,
@@ -3729,18 +3728,22 @@ def _warn_mode_object_pml(self) -> None:
37293728

37303729
def _validate_mode_object_bends(self) -> None:
37313730
"""Error if any mode sources or monitors with bends have a radius that is too small."""
3731+
from .mode.mode_solver import ModeSolver
3732+
37323733
for imnt, monitor in enumerate(self.monitors):
37333734
if isinstance(monitor, AbstractModeMonitor):
3734-
validate_mode_plane_radius(
3735+
ModeSolver._validate_mode_plane_radius(
37353736
mode_spec=monitor.mode_spec,
37363737
plane=monitor.geometry,
3738+
sim_geom=self.geometry,
37373739
msg_prefix=f"Monitor at 'monitors[{imnt}]' ",
37383740
)
37393741
for isrc, source in enumerate(self.sources):
37403742
if isinstance(source, ModeSource):
3741-
validate_mode_plane_radius(
3743+
ModeSolver._validate_mode_plane_radius(
37423744
mode_spec=source.mode_spec,
37433745
plane=source.geometry,
3746+
sim_geom=self.geometry,
37443747
msg_prefix=f"Source at 'sources[{isrc}]' ",
37453748
)
37463749

tidy3d/components/validators.py

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
from .base import DATA_ARRAY_MAP, skip_if_fields_missing
1616
from .data.dataset import Dataset, FieldDataset
1717
from .geometry.base import Box
18-
from .mode_spec import ModeSpec
1918

2019
""" Explanation of pydantic validators:
2120
@@ -464,24 +463,6 @@ def freqs_not_empty(cls, val):
464463
return freqs_not_empty
465464

466465

467-
def validate_mode_plane_radius(mode_spec: ModeSpec, plane: Box, msg_prefix: str = ""):
468-
"""Validate that the radius of a mode spec with a bend is not smaller than half the size of
469-
the plane along the radial direction."""
470-
471-
if not mode_spec.bend_radius:
472-
return
473-
474-
# radial axis is the plane axis that is not the bend axis
475-
_, plane_axs = plane.pop_axis([0, 1, 2], plane.size.index(0.0))
476-
radial_ax = plane_axs[(mode_spec.bend_axis + 1) % 2]
477-
478-
if np.abs(mode_spec.bend_radius) < plane.size[radial_ax] / 2:
479-
raise ValueError(
480-
f"{msg_prefix} bend radius is smaller than half the mode plane size "
481-
"along the radial axis, which can produce wrong results."
482-
)
483-
484-
485466
def _warn_unsupported_traced_argument(name: str):
486467
@pydantic.validator(name, always=True, allow_reuse=True)
487468
def _warn_traced_arg(cls, val, values):

0 commit comments

Comments
 (0)