Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `tidy3d.plugins.design.DesignSpace.run(..., fn_post=...)` now accepts a `priority` keyword to propagate vGPU queue priority to all automatically batched simulations.
- Introduced `BroadbandPulse` for exciting simulations across a wide frequency spectrum.
- Added `interp_spec` in `ModeSpec` to allow downsampling and interpolation of waveguide modes in frequency.
- Added warning if port mesh refinement is incompatible with the `GridSpec` in the `TerminalComponentModeler`.

### Breaking Changes
- Edge singularity correction at PEC and lossy metal edges defaults to `True`.
Expand Down
3 changes: 3 additions & 0 deletions tests/test_plugins/smatrix/terminal_component_modeler_def.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,10 @@ def make_coaxial_component_modeler(
def make_port(center, direction, type, name) -> Union[CoaxialLumpedPort, WavePort]:
if type is CoaxialLumpedPort:
port_cells = None
enable_snapping_points = False
if port_refinement:
port_cells = 21
enable_snapping_points = True
port = CoaxialLumpedPort(
center=center,
outer_diameter=2 * Router,
Expand All @@ -278,6 +280,7 @@ def make_port(center, direction, type, name) -> Union[CoaxialLumpedPort, WavePor
name="coax" + name,
num_grid_cells=port_cells,
impedance=reference_impedance,
enable_snapping_points=enable_snapping_points,
)
else:
mean_radius = (Router + Rinner) / 2
Expand Down
4 changes: 4 additions & 0 deletions tests/test_plugins/smatrix/test_component_modeler_autograd.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,17 @@ def build_terminal_modeler(scale: float) -> TerminalComponentModeler:
voltage_axis=1,
name="lp1",
impedance=50.0,
num_grid_cells=None,
enable_snapping_points=False,
)
p2 = RectLumpedPort(
center=(0.0, 0.0, 1.5),
size=port_size,
voltage_axis=1,
name="lp2",
impedance=50.0,
num_grid_cells=None,
enable_snapping_points=False,
)

freqs = [2.0e14]
Expand Down
47 changes: 37 additions & 10 deletions tests/test_plugins/smatrix/test_terminal_component_modeler.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
from tidy3d.plugins.smatrix.ports.base_lumped import AbstractLumpedPort
from tidy3d.plugins.smatrix.utils import s_to_z, validate_square_matrix

from ...utils import run_emulated
from ...utils import AssertLogLevel, run_emulated
from .terminal_component_modeler_def import (
make_basic_filter_terminals,
make_coaxial_component_modeler,
Expand Down Expand Up @@ -521,14 +521,16 @@ def test_ab_to_s_component_modeler():
assert np.isclose(S_matrix, b_matrix).all()


def test_port_snapping(tmp_path):
def test_port_snapping():
"""Make sure that the snapping behavior of the load resistor is mirrored
by all other components in the modeler simulations with rectangular ports.
"""
y_z_grid = td.UniformGrid(dl=0.1 * 1e3)
x_grid = td.UniformGrid(dl=11 * 1e3)
grid_spec = td.GridSpec(grid_x=x_grid, grid_y=y_z_grid, grid_z=y_z_grid)
modeler = make_component_modeler(planar_pec=True, port_refinement=False, grid_spec=grid_spec)
modeler = make_component_modeler(
planar_pec=True, port_refinement=False, port_snapping=False, grid_spec=grid_spec
)
check_lumped_port_components_snapped_correctly(modeler=modeler)


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


def test_coarse_grid_at_port(monkeypatch, tmp_path):
def test_coarse_grid_at_port(monkeypatch):
modeler = make_component_modeler(planar_pec=True, port_refinement=False, port_snapping=False)
# Without port refinement the grid is much too coarse for these port sizes
with pytest.raises(SetupError):
Expand Down Expand Up @@ -823,8 +825,7 @@ def test_make_coaxial_component_modeler_with_wave_ports(tmp_path):
xy_grid = td.UniformGrid(dl=0.1 * 1e3)
grid_spec = td.GridSpec(grid_x=xy_grid, grid_y=xy_grid, grid_z=z_grid)
_ = make_coaxial_component_modeler(
port_types=(WavePort, WavePort),
grid_spec=grid_spec,
port_types=(WavePort, WavePort), grid_spec=grid_spec, port_refinement=False
)


Expand All @@ -844,6 +845,7 @@ def test_run_coaxial_component_modeler_with_wave_ports(
grid_spec=grid_spec,
use_voltage=voltage_enabled,
use_current=current_enabled,
port_refinement=False,
)
return

Expand All @@ -852,6 +854,7 @@ def test_run_coaxial_component_modeler_with_wave_ports(
grid_spec=grid_spec,
use_voltage=voltage_enabled,
use_current=current_enabled,
port_refinement=False,
)
s_matrix = get_terminal_port_data_array(monkeypatch, modeler)

Expand Down Expand Up @@ -895,7 +898,9 @@ def test_run_mixed_component_modeler_with_wave_ports(monkeypatch, tmp_path):
xy_grid = td.UniformGrid(dl=0.1 * 1e3)
grid_spec = td.GridSpec(grid_x=xy_grid, grid_y=xy_grid, grid_z=z_grid)
modeler = make_coaxial_component_modeler(
port_types=(CoaxialLumpedPort, WavePort), grid_spec=grid_spec
port_types=(CoaxialLumpedPort, WavePort),
grid_spec=grid_spec,
port_refinement=False,
)
s_matrix = get_terminal_port_data_array(monkeypatch, modeler)

Expand Down Expand Up @@ -1363,7 +1368,9 @@ def test_run_only_and_element_mappings(monkeypatch, tmp_path):
xy_grid = td.UniformGrid(dl=0.1 * 1e3)
grid_spec = td.GridSpec(grid_x=xy_grid, grid_y=xy_grid, grid_z=z_grid)
modeler = make_coaxial_component_modeler(
port_types=(CoaxialLumpedPort, CoaxialLumpedPort), grid_spec=grid_spec
port_types=(CoaxialLumpedPort, CoaxialLumpedPort),
grid_spec=grid_spec,
port_refinement=False,
)
port0_idx = modeler.network_index(modeler.ports[0])
port1_idx = modeler.network_index(modeler.ports[1])
Expand Down Expand Up @@ -1677,7 +1684,11 @@ def test_S_parameter_deembedding(monkeypatch, tmp_path):
z_grid = td.UniformGrid(dl=1 * 1e3)
xy_grid = td.UniformGrid(dl=0.1 * 1e3)
grid_spec = td.GridSpec(grid_x=xy_grid, grid_y=xy_grid, grid_z=z_grid)
modeler = make_coaxial_component_modeler(port_types=(WavePort, WavePort), grid_spec=grid_spec)
modeler = make_coaxial_component_modeler(
port_types=(WavePort, WavePort),
grid_spec=grid_spec,
port_refinement=False,
)

# Make sure the smatrix and impedance calculations work for reduced simulations
modeler_data = run_component_modeler(monkeypatch, modeler)
Expand Down Expand Up @@ -1977,7 +1988,11 @@ def test_validate_run_only_with_wave_ports():
z_grid = td.UniformGrid(dl=1 * 1e3)
xy_grid = td.UniformGrid(dl=0.1 * 1e3)
grid_spec = td.GridSpec(grid_x=xy_grid, grid_y=xy_grid, grid_z=z_grid)
modeler = make_coaxial_component_modeler(port_types=(WavePort, WavePort), grid_spec=grid_spec)
modeler = make_coaxial_component_modeler(
port_types=(WavePort, WavePort),
grid_spec=grid_spec,
port_refinement=False,
)

port0_idx = modeler.network_index(modeler.ports[0], 0)
port1_idx = modeler.network_index(modeler.ports[1], 0)
Expand Down Expand Up @@ -2212,6 +2227,7 @@ def test_wave_port_mode_index_with_modeler():
mode_spec=mode_spec,
direction="+",
mode_selection=(0, 2), # Only modes 0 and 2
num_grid_cells=None,
)

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

modeler = TerminalComponentModeler(
Expand Down Expand Up @@ -2306,3 +2324,12 @@ def test_get_task_name():
# Test with wave port (no mode_index) - should work
task_name = TerminalComponentModeler.get_task_name(port=wave_port)
assert task_name == "wave@1"


def test_validate_port_refinement_with_uniform_grid():
"""Test that port refinement options raise error with uniform grid."""
uniform_grid = td.GridSpec.uniform(dl=0.5 * mm)
with AssertLogLevel("WARNING", contains_str="mesh refinement options enabled"):
make_coaxial_component_modeler(
port_types=(CoaxialLumpedPort, WavePort), grid_spec=uniform_grid
)
25 changes: 25 additions & 0 deletions tidy3d/plugins/smatrix/component_modelers/terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,31 @@ def _validate_3d_simulation(cls, val):
)
return val

@pd.validator("ports")
@skip_if_fields_missing(["simulation"])
def _validate_port_refinement_usage(cls, val, values):
"""Warn if port refinement options are enabled, but the supplied simulation
does not contain a grid type that will make use of them."""

sim: Simulation = values.get("simulation")
# If grid spec is using AutoGrid
# then set up is acceptable
if sim.grid_spec.auto_grid_used:
return val

for port in val:
if port._is_using_mesh_refinement:
log.warning(
f"A port with name '{port.name}' has mesh refinement options enabled, but the "
"'Simulation' passed to the 'TerminalComponentModeler' was setup with a 'GridSpec' which "
"does not support mesh refinement. For accurate simulations, please setup the "
"'Simulation' to use an 'AutoGrid'. To suppress this warning, please explicitly disable "
"mesh refinement options in the port, which are by default enabled. For example, set "
"the 'enable_snapping_points=False' and 'num_grid_cells=None' for lumped ports."
)

return val

@pd.validator("radiation_monitors")
@skip_if_fields_missing(["freqs"])
def _validate_radiation_monitors(cls, val, values):
Expand Down
8 changes: 8 additions & 0 deletions tidy3d/plugins/smatrix/ports/base_lumped.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,11 @@ def to_monitors(
@abstractmethod
def _check_grid_size(self, yee_grid: YeeGrid) -> None:
"""Raises :class:`SetupError` if the grid is too coarse at port locations."""

@property
def _is_using_mesh_refinement(self) -> bool:
"""Check if this lumped port is using any mesh refinement options.

Returns ``True`` if snapping points are enabled or custom grid cell count is specified.
"""
return self.enable_snapping_points or self.num_grid_cells is not None
8 changes: 8 additions & 0 deletions tidy3d/plugins/smatrix/ports/wave.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,3 +365,11 @@ def _validate_mode_index(cls, val, values):
f"'mode_spec.num_modes' ({num_modes}). Valid range is 0 to {num_modes - 1}."
)
return val

@property
def _is_using_mesh_refinement(self) -> bool:
"""Check if this wave port is using mesh refinement options.

Returns ``True`` if a custom grid cell count is specified.
"""
return self.num_grid_cells is not None