Skip to content

Commit bad66c6

Browse files
committed
fix(rf): add warning if port mesh refinement is incompatible with GridSpec
1 parent f3b119b commit bad66c6

File tree

7 files changed

+86
-10
lines changed

7 files changed

+86
-10
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3636
- `tidy3d.plugins.design.DesignSpace.run(..., fn_post=...)` now accepts a `priority` keyword to propagate vGPU queue priority to all automatically batched simulations.
3737
- Introduced `BroadbandPulse` for exciting simulations across a wide frequency spectrum.
3838
- Added `interp_spec` in `ModeSpec` to allow downsampling and interpolation of waveguide modes in frequency.
39+
- Added warning if port mesh refinement is incompatible with the `GridSpec` in the `TerminalComponentModeler`.
3940

4041
### Breaking Changes
4142
- Edge singularity correction at PEC and lossy metal edges defaults to `True`.

tests/test_plugins/smatrix/terminal_component_modeler_def.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,10 @@ def make_coaxial_component_modeler(
267267
def make_port(center, direction, type, name) -> Union[CoaxialLumpedPort, WavePort]:
268268
if type is CoaxialLumpedPort:
269269
port_cells = None
270+
enable_snapping_points = False
270271
if port_refinement:
271272
port_cells = 21
273+
enable_snapping_points = True
272274
port = CoaxialLumpedPort(
273275
center=center,
274276
outer_diameter=2 * Router,
@@ -278,6 +280,7 @@ def make_port(center, direction, type, name) -> Union[CoaxialLumpedPort, WavePor
278280
name="coax" + name,
279281
num_grid_cells=port_cells,
280282
impedance=reference_impedance,
283+
enable_snapping_points=enable_snapping_points,
281284
)
282285
else:
283286
mean_radius = (Router + Rinner) / 2

tests/test_plugins/smatrix/test_component_modeler_autograd.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,13 +197,17 @@ def build_terminal_modeler(scale: float) -> TerminalComponentModeler:
197197
voltage_axis=1,
198198
name="lp1",
199199
impedance=50.0,
200+
num_grid_cells=None,
201+
enable_snapping_points=False,
200202
)
201203
p2 = RectLumpedPort(
202204
center=(0.0, 0.0, 1.5),
203205
size=port_size,
204206
voltage_axis=1,
205207
name="lp2",
206208
impedance=50.0,
209+
num_grid_cells=None,
210+
enable_snapping_points=False,
207211
)
208212

209213
freqs = [2.0e14]

tests/test_plugins/smatrix/test_terminal_component_modeler.py

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from tidy3d.plugins.smatrix.ports.base_lumped import AbstractLumpedPort
3030
from tidy3d.plugins.smatrix.utils import s_to_z, validate_square_matrix
3131

32-
from ...utils import run_emulated
32+
from ...utils import AssertLogLevel, run_emulated
3333
from .terminal_component_modeler_def import (
3434
make_basic_filter_terminals,
3535
make_coaxial_component_modeler,
@@ -521,14 +521,16 @@ def test_ab_to_s_component_modeler():
521521
assert np.isclose(S_matrix, b_matrix).all()
522522

523523

524-
def test_port_snapping(tmp_path):
524+
def test_port_snapping():
525525
"""Make sure that the snapping behavior of the load resistor is mirrored
526526
by all other components in the modeler simulations with rectangular ports.
527527
"""
528528
y_z_grid = td.UniformGrid(dl=0.1 * 1e3)
529529
x_grid = td.UniformGrid(dl=11 * 1e3)
530530
grid_spec = td.GridSpec(grid_x=x_grid, grid_y=y_z_grid, grid_z=y_z_grid)
531-
modeler = make_component_modeler(planar_pec=True, port_refinement=False, grid_spec=grid_spec)
531+
modeler = make_component_modeler(
532+
planar_pec=True, port_refinement=False, port_snapping=False, grid_spec=grid_spec
533+
)
532534
check_lumped_port_components_snapped_correctly(modeler=modeler)
533535

534536

@@ -548,7 +550,7 @@ def test_coaxial_port_source_size(axis):
548550
assert np.isclose(source.size[axis], 0)
549551

550552

551-
def test_coarse_grid_at_port(monkeypatch, tmp_path):
553+
def test_coarse_grid_at_port(monkeypatch):
552554
modeler = make_component_modeler(planar_pec=True, port_refinement=False, port_snapping=False)
553555
# Without port refinement the grid is much too coarse for these port sizes
554556
with pytest.raises(SetupError):
@@ -823,8 +825,7 @@ def test_make_coaxial_component_modeler_with_wave_ports(tmp_path):
823825
xy_grid = td.UniformGrid(dl=0.1 * 1e3)
824826
grid_spec = td.GridSpec(grid_x=xy_grid, grid_y=xy_grid, grid_z=z_grid)
825827
_ = make_coaxial_component_modeler(
826-
port_types=(WavePort, WavePort),
827-
grid_spec=grid_spec,
828+
port_types=(WavePort, WavePort), grid_spec=grid_spec, port_refinement=False
828829
)
829830

830831

@@ -844,6 +845,7 @@ def test_run_coaxial_component_modeler_with_wave_ports(
844845
grid_spec=grid_spec,
845846
use_voltage=voltage_enabled,
846847
use_current=current_enabled,
848+
port_refinement=False,
847849
)
848850
return
849851

@@ -852,6 +854,7 @@ def test_run_coaxial_component_modeler_with_wave_ports(
852854
grid_spec=grid_spec,
853855
use_voltage=voltage_enabled,
854856
use_current=current_enabled,
857+
port_refinement=False,
855858
)
856859
s_matrix = get_terminal_port_data_array(monkeypatch, modeler)
857860

@@ -895,7 +898,9 @@ def test_run_mixed_component_modeler_with_wave_ports(monkeypatch, tmp_path):
895898
xy_grid = td.UniformGrid(dl=0.1 * 1e3)
896899
grid_spec = td.GridSpec(grid_x=xy_grid, grid_y=xy_grid, grid_z=z_grid)
897900
modeler = make_coaxial_component_modeler(
898-
port_types=(CoaxialLumpedPort, WavePort), grid_spec=grid_spec
901+
port_types=(CoaxialLumpedPort, WavePort),
902+
grid_spec=grid_spec,
903+
port_refinement=False,
899904
)
900905
s_matrix = get_terminal_port_data_array(monkeypatch, modeler)
901906

@@ -1363,7 +1368,9 @@ def test_run_only_and_element_mappings(monkeypatch, tmp_path):
13631368
xy_grid = td.UniformGrid(dl=0.1 * 1e3)
13641369
grid_spec = td.GridSpec(grid_x=xy_grid, grid_y=xy_grid, grid_z=z_grid)
13651370
modeler = make_coaxial_component_modeler(
1366-
port_types=(CoaxialLumpedPort, CoaxialLumpedPort), grid_spec=grid_spec
1371+
port_types=(CoaxialLumpedPort, CoaxialLumpedPort),
1372+
grid_spec=grid_spec,
1373+
port_refinement=False,
13671374
)
13681375
port0_idx = modeler.network_index(modeler.ports[0])
13691376
port1_idx = modeler.network_index(modeler.ports[1])
@@ -1677,7 +1684,11 @@ def test_S_parameter_deembedding(monkeypatch, tmp_path):
16771684
z_grid = td.UniformGrid(dl=1 * 1e3)
16781685
xy_grid = td.UniformGrid(dl=0.1 * 1e3)
16791686
grid_spec = td.GridSpec(grid_x=xy_grid, grid_y=xy_grid, grid_z=z_grid)
1680-
modeler = make_coaxial_component_modeler(port_types=(WavePort, WavePort), grid_spec=grid_spec)
1687+
modeler = make_coaxial_component_modeler(
1688+
port_types=(WavePort, WavePort),
1689+
grid_spec=grid_spec,
1690+
port_refinement=False,
1691+
)
16811692

16821693
# Make sure the smatrix and impedance calculations work for reduced simulations
16831694
modeler_data = run_component_modeler(monkeypatch, modeler)
@@ -1977,7 +1988,11 @@ def test_validate_run_only_with_wave_ports():
19771988
z_grid = td.UniformGrid(dl=1 * 1e3)
19781989
xy_grid = td.UniformGrid(dl=0.1 * 1e3)
19791990
grid_spec = td.GridSpec(grid_x=xy_grid, grid_y=xy_grid, grid_z=z_grid)
1980-
modeler = make_coaxial_component_modeler(port_types=(WavePort, WavePort), grid_spec=grid_spec)
1991+
modeler = make_coaxial_component_modeler(
1992+
port_types=(WavePort, WavePort),
1993+
grid_spec=grid_spec,
1994+
port_refinement=False,
1995+
)
19811996

19821997
port0_idx = modeler.network_index(modeler.ports[0], 0)
19831998
port1_idx = modeler.network_index(modeler.ports[1], 0)
@@ -2212,6 +2227,7 @@ def test_wave_port_mode_index_with_modeler():
22122227
mode_spec=mode_spec,
22132228
direction="+",
22142229
mode_selection=(0, 2), # Only modes 0 and 2
2230+
num_grid_cells=None,
22152231
)
22162232

22172233
# Verify the port has only the selected modes
@@ -2232,6 +2248,8 @@ def test_wave_port_mode_index_with_modeler():
22322248
size=(1, 1, 0),
22332249
voltage_axis=0, # x-direction since port is in x-y plane
22342250
name="lumped_port",
2251+
num_grid_cells=None,
2252+
enable_snapping_points=False,
22352253
)
22362254

22372255
modeler = TerminalComponentModeler(
@@ -2306,3 +2324,12 @@ def test_get_task_name():
23062324
# Test with wave port (no mode_index) - should work
23072325
task_name = TerminalComponentModeler.get_task_name(port=wave_port)
23082326
assert task_name == "wave@1"
2327+
2328+
2329+
def test_validate_port_refinement_with_uniform_grid():
2330+
"""Test that port refinement options raise error with uniform grid."""
2331+
uniform_grid = td.GridSpec.uniform(dl=0.5 * mm)
2332+
with AssertLogLevel("WARNING", contains_str="mesh refinement options enabled"):
2333+
make_coaxial_component_modeler(
2334+
port_types=(CoaxialLumpedPort, WavePort), grid_spec=uniform_grid
2335+
)

tidy3d/plugins/smatrix/component_modelers/terminal.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,31 @@ def _validate_3d_simulation(cls, val):
742742
)
743743
return val
744744

745+
@pd.validator("ports")
746+
@skip_if_fields_missing(["simulation"])
747+
def _validate_port_refinement_usage(cls, val, values):
748+
"""Warn if port refinement options are enabled, but the supplied simulation
749+
does not contain a grid type that will make use of them."""
750+
751+
sim: Simulation = values.get("simulation")
752+
# If grid spec is using AutoGrid
753+
# then set up is acceptable
754+
if sim.grid_spec.auto_grid_used:
755+
return val
756+
757+
for port in val:
758+
if port._is_using_mesh_refinement:
759+
log.warning(
760+
f"A port with name '{port.name}' has mesh refinement options enabled, but the "
761+
"'Simulation' passed to the 'TerminalComponentModeler' was setup with a 'GridSpec' which "
762+
"does not support mesh refinement. For accurate simulations, please setup the "
763+
"'Simulation' to use an 'AutoGrid'. To suppress this warning, please explicitly disable "
764+
"mesh refinement options in the port, which are by default enabled. For example, set "
765+
"the 'enable_snapping_points=False' and 'num_grid_cells=None' for lumped ports."
766+
)
767+
768+
return val
769+
745770
@pd.validator("radiation_monitors")
746771
@skip_if_fields_missing(["freqs"])
747772
def _validate_radiation_monitors(cls, val, values):

tidy3d/plugins/smatrix/ports/base_lumped.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,11 @@ def to_monitors(
9494
@abstractmethod
9595
def _check_grid_size(self, yee_grid: YeeGrid) -> None:
9696
"""Raises :class:`SetupError` if the grid is too coarse at port locations."""
97+
98+
@property
99+
def _is_using_mesh_refinement(self) -> bool:
100+
"""Check if this lumped port is using any mesh refinement options.
101+
102+
Returns ``True`` if snapping points are enabled or custom grid cell count is specified.
103+
"""
104+
return self.enable_snapping_points or self.num_grid_cells is not None

tidy3d/plugins/smatrix/ports/wave.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,3 +365,11 @@ def _validate_mode_index(cls, val, values):
365365
f"'mode_spec.num_modes' ({num_modes}). Valid range is 0 to {num_modes - 1}."
366366
)
367367
return val
368+
369+
@property
370+
def _is_using_mesh_refinement(self) -> bool:
371+
"""Check if this wave port is using mesh refinement options.
372+
373+
Returns ``True`` if a custom grid cell count is specified.
374+
"""
375+
return self.num_grid_cells is not None

0 commit comments

Comments
 (0)