Skip to content

Commit 3f087b5

Browse files
committed
Validate that bend radius is not smaller than half the mode plane size
1 parent e7bc235 commit 3f087b5

File tree

6 files changed

+98
-2
lines changed

6 files changed

+98
-2
lines changed

tests/test_components/test_monitor.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,24 @@ def test_monitor_num_modes(log_capture, num_modes, log_level):
296296
assert_log_level(log_capture, log_level)
297297

298298

299+
def test_mode_bend_radius():
300+
"""Test that small bend radius fails."""
301+
302+
with pytest.raises(ValueError):
303+
mnt = td.ModeMonitor(
304+
size=(5, 0, 1),
305+
freqs=np.linspace(1e14, 2e14, 100),
306+
name="test",
307+
mode_spec=td.ModeSpec(num_modes=1, bend_radius=1, bend_axis=1),
308+
)
309+
_ = td.Simulation(
310+
size=(2, 2, 2),
311+
run_time=1e-12,
312+
monitors=[mnt],
313+
grid_spec=td.GridSpec.uniform(dl=0.1),
314+
)
315+
316+
299317
def test_diffraction_validators():
300318
# ensure error if boundaries are not periodic
301319
boundary_spec = td.BoundarySpec(

tests/test_components/test_source.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,22 @@ def test_dir_vector():
4646
assert DirectionalSource._dir_vector.fget(S) is None
4747

4848

49+
def test_mode_bend_radius():
50+
"""Test that small bend radius fails."""
51+
52+
with pytest.raises(ValueError):
53+
src = td.ModeSource(
54+
size=(1, 0, 5),
55+
source_time=ST,
56+
mode_spec=td.ModeSpec(num_modes=1, bend_radius=1, bend_axis=0),
57+
)
58+
_ = td.Simulation(
59+
size=(2, 2, 2),
60+
run_time=1e-12,
61+
sources=[src],
62+
)
63+
64+
4965
def test_UniformCurrentSource():
5066
g = td.GaussianPulse(freq0=1e12, fwidth=0.1e12)
5167

tests/test_plugins/test_mode_solver.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,3 +1034,14 @@ def test_modes_eme_sim(mock_remote_api, local):
10341034
_ = msweb.run(solver.to_fdtd_mode_solver())
10351035

10361036
_ = solver.reduced_simulation_copy
1037+
1038+
1039+
def test_mode_bend_radius():
1040+
"""Test that small bend radius fails."""
1041+
1042+
with pytest.raises(ValueError):
1043+
ms = ModeSolver(
1044+
plane=PLANE,
1045+
freqs=np.linspace(1e14, 2e14, 100),
1046+
mode_spec=td.ModeSpec(num_modes=1, bend_radius=1, bend_axis=0),
1047+
)

tidy3d/components/simulation.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,11 @@
8585
from .structure import MeshOverrideStructure, Structure
8686
from .subpixel_spec import SubpixelSpec
8787
from .types import TYPE_TAG_STR, Ax, Axis, FreqBound, InterpMethod, Literal, Symmetry, annotate_type
88-
from .validators import assert_objects_in_sim_bounds, validate_mode_objects_symmetry
88+
from .validators import (
89+
assert_objects_in_sim_bounds,
90+
validate_mode_objects_symmetry,
91+
validate_mode_plane_radius,
92+
)
8993
from .viz import (
9094
PlotParams,
9195
add_ax_if_none,
@@ -3245,6 +3249,24 @@ def _post_init_validators(self) -> None:
32453249
self._validate_tfsf_nonuniform_grid()
32463250
self._validate_nonlinear_specs()
32473251
self._validate_custom_source_time()
3252+
self._validate_mode_object_bends()
3253+
3254+
def _validate_mode_object_bends(self) -> None:
3255+
"""Error if any mode sources or monitors with bends have a radius that is too small."""
3256+
for imnt, monitor in enumerate(self.monitors):
3257+
if isinstance(monitor, AbstractModeMonitor):
3258+
validate_mode_plane_radius(
3259+
mode_spec=monitor.mode_spec,
3260+
plane=monitor.geometry,
3261+
msg_prefix=f"Monitor at 'monitors[{imnt}]' ",
3262+
)
3263+
for isrc, source in enumerate(self.sources):
3264+
if isinstance(source, ModeSource):
3265+
validate_mode_plane_radius(
3266+
mode_spec=source.mode_spec,
3267+
plane=source.geometry,
3268+
msg_prefix=f"Source at 'sources[{isrc}]' ",
3269+
)
32483270

32493271
def _validate_custom_source_time(self):
32503272
"""Warn if all simulation times are outside CustomSourceTime definition range."""

tidy3d/components/validators.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from .base import DATA_ARRAY_MAP, skip_if_fields_missing
99
from .data.dataset import Dataset, FieldDataset
1010
from .geometry.base import Box
11+
from .mode import ModeSpec
1112
from .types import Tuple
1213

1314
""" Explanation of pydantic validators:
@@ -396,3 +397,21 @@ def freqs_not_empty(cls, val):
396397
return val
397398

398399
return freqs_not_empty
400+
401+
402+
def validate_mode_plane_radius(mode_spec: ModeSpec, plane: Box, msg_prefix: str = ""):
403+
"""Validate that the radius of a mode spec with a bend is not smaller than half the size of
404+
the plane along the radial direction."""
405+
406+
if not mode_spec.bend_radius:
407+
return
408+
409+
# radial axis is the plane axis that is not the bend axis
410+
_, plane_axs = plane.pop_axis([0, 1, 2], plane.size.index(0.0))
411+
radial_ax = plane_axs[(mode_spec.bend_axis + 1) % 2]
412+
413+
if np.abs(mode_spec.bend_radius) < plane.size[radial_ax] / 2:
414+
raise ValueError(
415+
f"{msg_prefix} bend radius is smaller than half the mode plane size "
416+
"along the radial axis, which can produce wrong results."
417+
)

tidy3d/plugins/mode/mode_solver.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@
4646
PlotScale,
4747
Symmetry,
4848
)
49-
from ...components.validators import validate_freqs_min, validate_freqs_not_empty
49+
from ...components.validators import (
50+
validate_freqs_min,
51+
validate_freqs_not_empty,
52+
validate_mode_plane_radius,
53+
)
5054
from ...components.viz import make_ax, plot_params_pml
5155
from ...constants import C_0
5256
from ...exceptions import SetupError, ValidationError
@@ -173,6 +177,11 @@ def plane_in_sim_bounds(cls, val, values):
173177
raise SetupError("'ModeSolver.plane' must intersect 'ModeSolver.simulation'.")
174178
return val
175179

180+
def _post_init_validators(self) -> None:
181+
validate_mode_plane_radius(
182+
mode_spec=self.mode_spec, plane=self.plane, msg_prefix="Mode solver"
183+
)
184+
176185
@cached_property
177186
def normal_axis(self) -> Axis:
178187
"""Axis normal to the mode plane."""
@@ -1511,6 +1520,7 @@ def _validate_modes_size(self):
15111520
)
15121521

15131522
def validate_pre_upload(self, source_required: bool = True):
1523+
"""Validate the fully initialized mode solver is ok for upload to our servers."""
15141524
self._validate_modes_size()
15151525

15161526
@cached_property

0 commit comments

Comments
 (0)