Skip to content

Commit 73046e6

Browse files
authored
fix contains check for lumped element, which was too strict (#2511)
1 parent 74f402e commit 73046e6

File tree

4 files changed

+39
-8
lines changed

4 files changed

+39
-8
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2020
### Fixed
2121
- Fixed bug in broadband adjoint source creation when forward simulation had a pulse amplitude greater than 1 or a nonzero pulse phase.
2222
- Fixed shaping of `CustomMedium` gradients when permittivity data includes a frequency dimension with multiple entries.
23+
- Bug in contains check for `LumpedElement`, which should allow the case of a `LumpedElement` touching the simulation boundaries.
2324
- Bug when generating a grid with snapping points near the simulation boundaries.
2425

2526
### Changed

tests/test_components/test_simulation.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1604,6 +1604,25 @@ def test_warn_lumped_elements_outside_sim_bounds():
16041604
)
16051605
assert len(sim_good.volumetric_structures) == 1
16061606

1607+
# Lumped element is touching the boundary along one of its nonzero dims
1608+
resistor_in = td.LumpedResistor(
1609+
size=(0.5, 1, 0),
1610+
center=(0, 0.5, 0),
1611+
voltage_axis=1,
1612+
resistance=50,
1613+
name="resistor_touching",
1614+
)
1615+
with AssertLogLevel("INFO"):
1616+
sim_good = td.Simulation(
1617+
size=sim_size,
1618+
center=sim_center,
1619+
sources=[src],
1620+
run_time=1e-12,
1621+
lumped_elements=[resistor_in],
1622+
boundary_spec=td.BoundarySpec.all_sides(boundary=td.Periodic()),
1623+
)
1624+
assert len(sim_good.volumetric_structures) == 1
1625+
16071626
# Lumped element outside - should emit warning and not be added
16081627
resistor_out = td.LumpedResistor(
16091628
size=(0.5, 1, 0),
@@ -1616,16 +1635,16 @@ def test_warn_lumped_elements_outside_sim_bounds():
16161635
sim_bad = sim_good.updated_copy(lumped_elements=[resistor_out])
16171636
assert len(sim_bad.volumetric_structures) == 0
16181637

1619-
# Lumped element extends to boundary and is not strictly inside simulation
1638+
# Lumped element is flush against boundary along its zero size dimension
16201639
resistor_edge = td.LumpedResistor(
16211640
size=(0.5, 1, 0),
1622-
center=(0, 0.5, 0),
1641+
center=(0, 0.5, 1),
16231642
voltage_axis=1,
16241643
resistance=50,
16251644
name="resistor_edge",
16261645
)
16271646
with AssertLogLevel("WARNING"):
1628-
_ = sim_good.updated_copy(lumped_elements=[resistor_edge])
1647+
sim_bad = sim_good.updated_copy(lumped_elements=[resistor_edge])
16291648
assert len(sim_bad.volumetric_structures) == 0
16301649

16311650

tidy3d/components/simulation.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,8 +1613,9 @@ def snap_to_grid(geom: Geometry, axis: Axis) -> Geometry:
16131613

16141614
# Convert lumped elements into structures
16151615
lumped_structures = []
1616-
strict_ineq = 3 * [True]
16171616
for lumped_element in self.lumped_elements:
1617+
strict_ineq = 3 * [False]
1618+
strict_ineq[lumped_element.normal_axis] = True
16181619
if self.geometry.contains(lumped_element.geometry, strict_inequality=strict_ineq):
16191620
lumped_structures += lumped_element.to_structures(self.grid)
16201621

@@ -2660,7 +2661,7 @@ def _validate_auto_grid_wavelength(cls, val, values):
26602661

26612662
_sources_in_bounds = assert_objects_in_sim_bounds("sources", strict_inequality=True)
26622663
_lumped_elements_in_bounds = assert_objects_contained_in_sim_bounds(
2663-
"lumped_elements", error=False, strict_inequality=True
2664+
"lumped_elements", error=False, strict_inequality=False, strict_for_zero_size_dim=True
26642665
)
26652666
_mode_sources_symmetries = validate_mode_objects_symmetry("sources")
26662667
_mode_monitors_symmetries = validate_mode_objects_symmetry("monitors")

tidy3d/components/validators.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,10 @@ def objects_in_sim_bounds(cls, val, values):
214214

215215

216216
def assert_objects_contained_in_sim_bounds(
217-
field_name: str, error: bool = True, strict_inequality: bool = False
217+
field_name: str,
218+
error: bool = True,
219+
strict_inequality: bool = False,
220+
strict_for_zero_size_dim: bool = False,
218221
):
219222
"""Makes sure all objects in field are completely inside the simulation bounds."""
220223

@@ -228,10 +231,17 @@ def objects_contained_in_sim_bounds(cls, val, values):
228231

229232
# Do a strict check, unless simulation is 0D along a dimension
230233
strict_ineq = [size != 0 and strict_inequality for size in sim_size]
231-
232234
with log as consolidated_logger:
233235
for position_index, geometric_object in enumerate(val):
234-
if not sim_box.contains(geometric_object.geometry, strict_inequality=strict_ineq):
236+
geo_strict_ineq = list(strict_ineq)
237+
# Optionally ensure that zero size dimensions are strictly contained
238+
if strict_for_zero_size_dim:
239+
zero_dims = geometric_object.geometry.zero_dims
240+
for zero_dim in zero_dims:
241+
geo_strict_ineq[zero_dim] = True
242+
if not sim_box.contains(
243+
geometric_object.geometry, strict_inequality=geo_strict_ineq
244+
):
235245
message = (
236246
f"'simulation.{field_name}[{position_index}]' "
237247
"is not completely inside the simulation domain."

0 commit comments

Comments
 (0)