Skip to content

Commit 2b6d21b

Browse files
feat(meshing): cache merged_geos in gap refinement
feat(meshing): gap refinement only insert snapping points
1 parent 7b879bd commit 2b6d21b

File tree

7 files changed

+723
-214
lines changed

7 files changed

+723
-214
lines changed

tests/test_components/test_layerrefinement.py

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -104,19 +104,19 @@ def test_layerrefinement():
104104
assert layer.size[axis] == 1
105105
assert layer.size[(axis + 1) % 3] == td.inf
106106
assert layer.size[(axis + 2) % 3] == td.inf
107-
assert not layer._is_inplane_bounded
107+
assert not layer._is_inplane_bounded(layer)
108108

109109
layer = LayerRefinementSpec.from_bounds(axis=axis, rmin=(0, 0, 0), rmax=(1, 2, 3))
110110
layer = LayerRefinementSpec.from_bounds(rmin=(0, 0, 0), rmax=(1, 2, 3))
111111
assert layer.axis == 0
112112
assert np.isclose(layer.length_axis, 1)
113113
assert np.isclose(layer.center_axis, 0.5)
114-
assert layer._is_inplane_bounded
114+
assert layer._is_inplane_bounded(layer)
115115

116116
# from structures
117117
structures = [td.Structure(geometry=td.Box(size=(td.inf, 2, 3)), medium=td.Medium())]
118118
layer = LayerRefinementSpec.from_structures(structures)
119-
assert layer._is_inplane_bounded
119+
assert layer._is_inplane_bounded(layer)
120120
assert layer.axis == 1
121121

122122
with pytest.raises(pydantic.ValidationError):
@@ -138,11 +138,11 @@ def test_layerrefinement():
138138
def test_layerrefinement_inplane_inside():
139139
# inplane inside
140140
layer = LayerRefinementSpec.from_layer_bounds(axis=2, bounds=(0, 1))
141-
assert not layer._is_inplane_bounded
142-
assert layer._inplane_inside([3e3, 4e4])
141+
assert not layer._is_inplane_bounded(layer)
142+
assert layer._inplane_inside(layer, [3e3, 4e4])
143143
layer = LayerRefinementSpec(axis=1, size=(1, 0, 1))
144-
assert layer._inplane_inside([0, 0])
145-
assert not layer._inplane_inside([2, 0])
144+
assert layer._inplane_inside(layer, [0, 0])
145+
assert not layer._inplane_inside(layer, [2, 0])
146146

147147

148148
def test_layerrefinement_snapping_points():
@@ -263,7 +263,11 @@ def count_grids_within_layer(sim_t):
263263
assert (
264264
len(
265265
sim2.grid_spec.all_override_structures(
266-
list(sim2.structures), 1.0, sim2.size, lumped_elements
266+
list(sim2.structures),
267+
1.0,
268+
lumped_elements,
269+
sim2._internal_layerrefinement_boundary_types,
270+
sim2.bounds,
267271
)
268272
)
269273
== 1
@@ -281,7 +285,11 @@ def count_grids_within_layer(sim_t):
281285
assert (
282286
len(
283287
sim2.grid_spec.all_override_structures(
284-
list(sim2.structures), 1.0, sim2.size, lumped_elements
288+
list(sim2.structures),
289+
1.0,
290+
lumped_elements,
291+
sim2._internal_layerrefinement_boundary_types,
292+
sim2.bounds,
285293
)
286294
)
287295
== 2
@@ -425,7 +433,11 @@ def test_dl_min_from_smallest_feature():
425433
),
426434
medium=td.PECMedium(),
427435
)
428-
436+
boundary_types = [[None] * 2] * 3
437+
sim_bounds = [
438+
[-td.inf] * 3,
439+
[td.inf] * 3,
440+
]
429441
# check expected dl_min
430442
layer_spec = td.LayerRefinementSpec(
431443
axis=2,
@@ -434,15 +446,15 @@ def test_dl_min_from_smallest_feature():
434446
convex_resolution=10,
435447
),
436448
)
437-
dl_min = layer_spec._dl_min_from_smallest_feature([structure])
449+
dl_min = layer_spec._dl_min_from_smallest_feature([structure], sim_bounds, boundary_types)
438450
assert np.allclose(0.3 / 10, dl_min)
439451

440452
layer_spec = td.LayerRefinementSpec(
441453
axis=2,
442454
size=(td.inf, td.inf, 2),
443455
corner_finder=td.CornerFinderSpec(mixed_resolution=10),
444456
)
445-
dl_min = layer_spec._dl_min_from_smallest_feature([structure])
457+
dl_min = layer_spec._dl_min_from_smallest_feature([structure], sim_bounds, boundary_types)
446458
assert np.allclose(0.2 / 10, dl_min)
447459

448460
layer_spec = td.LayerRefinementSpec(
@@ -452,7 +464,7 @@ def test_dl_min_from_smallest_feature():
452464
concave_resolution=10,
453465
),
454466
)
455-
dl_min = layer_spec._dl_min_from_smallest_feature([structure])
467+
dl_min = layer_spec._dl_min_from_smallest_feature([structure], sim_bounds, boundary_types)
456468
assert np.allclose(0.1 / 10, dl_min)
457469

458470
# check grid is generated succesfully
@@ -517,7 +529,8 @@ def test_gap_meshing():
517529
layer_refinement_specs=[
518530
td.LayerRefinementSpec(
519531
axis=2,
520-
corner_finder=None,
532+
corner_snapping=False,
533+
corner_refinement=None,
521534
gap_meshing_iters=num_iters,
522535
size=[td.inf, td.inf, 2],
523536
center=[0, 0, 1],
@@ -583,7 +596,8 @@ def test_gap_meshing():
583596
td.LayerRefinementSpec(
584597
axis=1,
585598
size=(td.inf, 0.2, td.inf),
586-
corner_finder=None,
599+
corner_snapping=False,
600+
corner_refinement=None,
587601
gap_meshing_iters=1,
588602
dl_min_from_gap_width=True,
589603
)
@@ -626,7 +640,8 @@ def test_gap_meshing():
626640
td.LayerRefinementSpec(
627641
axis=1,
628642
size=(td.inf, 0.2, td.inf),
629-
corner_finder=None,
643+
corner_snapping=False,
644+
corner_refinement=None,
630645
gap_meshing_iters=2,
631646
dl_min_from_gap_width=True,
632647
interior_disjoint_geometries=False,
@@ -658,7 +673,8 @@ def test_gap_meshing():
658673
td.LayerRefinementSpec(
659674
axis=1,
660675
size=(td.inf, 0.2, td.inf),
661-
corner_finder=None,
676+
corner_snapping=False,
677+
corner_refinement=None,
662678
gap_meshing_iters=1,
663679
dl_min_from_gap_width=True,
664680
)
@@ -697,7 +713,8 @@ def test_gap_meshing():
697713
axis=1,
698714
size=(0.5, 0.2, 0.5),
699715
center=(0.5, 0, -0.5),
700-
corner_finder=None,
716+
corner_snapping=False,
717+
corner_refinement=None,
701718
gap_meshing_iters=1,
702719
dl_min_from_gap_width=True,
703720
)
@@ -731,7 +748,8 @@ def test_gap_meshing():
731748
axis=1,
732749
size=(0.05, 0.2, 0.05),
733750
center=(0.05, 0, 0.05),
734-
corner_finder=None,
751+
corner_snapping=False,
752+
corner_refinement=None,
735753
gap_meshing_iters=2,
736754
dl_min_from_gap_width=True,
737755
)
@@ -765,7 +783,8 @@ def test_gap_meshing():
765783
axis=1,
766784
size=(0.01, 0.2, 0.01),
767785
center=(10.0, 0, 10.0),
768-
corner_finder=None,
786+
corner_snapping=False,
787+
corner_refinement=None,
769788
gap_meshing_iters=1,
770789
dl_min_from_gap_width=True,
771790
)
@@ -804,7 +823,8 @@ def test_gap_meshing():
804823
td.LayerRefinementSpec(
805824
axis=1,
806825
size=(td.inf, 0.2, td.inf),
807-
corner_finder=None,
826+
corner_snapping=False,
827+
corner_refinement=None,
808828
gap_meshing_iters=1,
809829
dl_min_from_gap_width=True,
810830
)
@@ -842,7 +862,8 @@ def test_gap_meshing():
842862
td.LayerRefinementSpec(
843863
axis=0,
844864
size=(0.2, td.inf, td.inf),
845-
corner_finder=None,
865+
corner_snapping=False,
866+
corner_refinement=None,
846867
gap_meshing_iters=1,
847868
dl_min_from_gap_width=True,
848869
)

tidy3d/components/geometry/base.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
from tidy3d.components.autograd.derivative_utils import DerivativeInfo
3232
from tidy3d.components.base import Tidy3dBaseModel, cached_property
3333
from tidy3d.components.geometry.bound_ops import bounds_intersection, bounds_union
34+
from tidy3d.components.geometry.float_utils import increment_float
3435
from tidy3d.components.transformation import ReflectionFromPlane, RotationAroundAxis
3536
from tidy3d.components.types import (
3637
ArrayFloat2D,
@@ -2173,6 +2174,11 @@ def intersections_with(self, other: Shapely) -> list[Shapely]:
21732174
shapely_box = Geometry.evaluate_inf_shape(shapely_box)
21742175
return [Geometry.evaluate_inf_shape(shape) & shapely_box for shape in shapes_plane]
21752176

2177+
def slightly_enlarged_copy(self) -> Box:
2178+
"""Box size slightly enlarged around machine precision."""
2179+
size = [increment_float(orig_length, 1) for orig_length in self.size]
2180+
return self.updated_copy(size=size)
2181+
21762182
def padded_copy(
21772183
self,
21782184
x: Optional[tuple[pydantic.NonNegativeFloat, pydantic.NonNegativeFloat]] = None,
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""Utilities for float manipulation."""
2+
3+
from __future__ import annotations
4+
5+
import numpy as np
6+
7+
from tidy3d.constants import inf
8+
9+
10+
def increment_float(val: float, sign: int) -> float:
11+
"""Applies a small positive or negative shift as though `val` is a 32bit float
12+
using numpy.nextafter, but additionally handles some corner cases.
13+
"""
14+
# Infinity is left unchanged
15+
if val == inf or val == -inf:
16+
return val
17+
18+
if sign >= 0:
19+
sign = 1
20+
else:
21+
sign = -1
22+
23+
# Avoid small increments within subnormal values
24+
if np.abs(val) <= np.finfo(np.float32).tiny:
25+
return val + sign * np.finfo(np.float32).tiny
26+
27+
# Numpy seems to skip over the increment from -0.0 and +0.0
28+
# which is different from c++
29+
val_inc = np.nextafter(val, sign * inf, dtype=np.float32)
30+
31+
return np.float32(val_inc)

tidy3d/components/geometry/utils_2d.py

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,13 @@
88
import shapely
99

1010
from tidy3d.components.geometry.base import Box, ClipOperation, Geometry, GeometryGroup
11+
from tidy3d.components.geometry.float_utils import increment_float
1112
from tidy3d.components.geometry.polyslab import _MIN_POLYGON_AREA, PolySlab
1213
from tidy3d.components.grid.grid import Grid
1314
from tidy3d.components.scene import Scene
1415
from tidy3d.components.structure import Structure
1516
from tidy3d.components.types import Axis, Shapely
16-
from tidy3d.constants import fp_eps, inf
17-
18-
19-
def increment_float(val: float, sign: int) -> float:
20-
"""Applies a small positive or negative shift as though `val` is a 32bit float
21-
using numpy.nextafter, but additionally handles some corner cases.
22-
"""
23-
# Infinity is left unchanged
24-
if val == inf or val == -inf:
25-
return val
26-
27-
if sign >= 0:
28-
sign = 1
29-
else:
30-
sign = -1
31-
32-
# Avoid small increments within subnormal values
33-
if np.abs(val) <= np.finfo(np.float32).tiny:
34-
return val + sign * np.finfo(np.float32).tiny
35-
36-
# Numpy seems to skip over the increment from -0.0 and +0.0
37-
# which is different from c++
38-
val_inc = np.nextafter(val, sign * inf, dtype=np.float32)
39-
40-
return np.float32(val_inc)
17+
from tidy3d.constants import fp_eps
4118

4219

4320
def snap_coordinate_to_grid(grid: Grid, center: float, axis: Axis) -> float:

0 commit comments

Comments
 (0)