Skip to content

Commit b73cff8

Browse files
formatting
1 parent 479a026 commit b73cff8

File tree

4 files changed

+108
-50
lines changed

4 files changed

+108
-50
lines changed

tests/test_components/test_grid_spec.py

-32
Original file line numberDiff line numberDiff line change
@@ -515,35 +515,3 @@ def test_domain_mismatch():
515515
boundary_spec=td.BoundarySpec.pml(),
516516
)
517517
z = sim.grid.boundaries.z
518-
519-
def test_dl_min_from_smallest_feature():
520-
521-
structure = td.Structure(
522-
geometry=td.PolySlab(vertices=[[0, 0], [2, 0], [2, 1], [1, 1], [1, 1.1], [2, 1.1], [2, 2], [1, 2], [1, 2.2], [0.7, 2.2], [0.7, 2], [0, 2]], slab_bounds=[-1, 1], axis=2),
523-
medium=td.PECMedium(),
524-
)
525-
526-
# check expected dl_min
527-
layer_spec = td.LayerRefinementSpec(axis=2, size=(td.inf, td.inf, 2), corner_finder=td.CornerFinderSpec(dl_min_spec=td.SmallestFeatureSpec(convex_resolution=10, concave_resolution=0, mixed_resolution=0)))
528-
dl_min = layer_spec._dl_min_from_smallest_feature([structure])
529-
assert(np.allclose(0.3 / 10, dl_min))
530-
531-
layer_spec = td.LayerRefinementSpec(axis=2, size=(td.inf, td.inf, 2), corner_finder=td.CornerFinderSpec(dl_min_spec=td.SmallestFeatureSpec(convex_resolution=0, concave_resolution=0, mixed_resolution=10)))
532-
dl_min = layer_spec._dl_min_from_smallest_feature([structure])
533-
assert(np.allclose(0.2 / 10, dl_min))
534-
535-
layer_spec = td.LayerRefinementSpec(axis=2, size=(td.inf, td.inf, 2), corner_finder=td.CornerFinderSpec(dl_min_spec=td.SmallestFeatureSpec(convex_resolution=0, concave_resolution=10, mixed_resolution=0)))
536-
dl_min = layer_spec._dl_min_from_smallest_feature([structure])
537-
assert(np.allclose(0.1 / 10, dl_min))
538-
539-
540-
# check grid is generated succesfully
541-
sim = td.Simulation(
542-
size=(5, 5, 5),
543-
structures=[structure],
544-
grid_spec=td.GridSpec.auto(layer_refinement_specs=[layer_spec], wavelength=100 * td.C_0),
545-
run_time=1e-20,
546-
)
547-
548-
_ = sim.grid
549-

tests/test_components/test_layerrefinement.py

+71
Original file line numberDiff line numberDiff line change
@@ -339,3 +339,74 @@ def count_grids_within_gap(sim_t):
339339
layer = layer.updated_copy(refinement_inside_sim_only=False)
340340
sim = sim.updated_copy(grid_spec=td.GridSpec.auto(wavelength=1, layer_refinement_specs=[layer]))
341341
assert count_grids_within_gap(sim) > 2
342+
343+
344+
def test_dl_min_from_smallest_feature():
345+
structure = td.Structure(
346+
geometry=td.PolySlab(
347+
vertices=[
348+
[0, 0],
349+
[2, 0],
350+
[2, 1],
351+
[1, 1],
352+
[1, 1.1],
353+
[2, 1.1],
354+
[2, 2],
355+
[1, 2],
356+
[1, 2.2],
357+
[0.7, 2.2],
358+
[0.7, 2],
359+
[0, 2],
360+
],
361+
slab_bounds=[-1, 1],
362+
axis=2,
363+
),
364+
medium=td.PECMedium(),
365+
)
366+
367+
# check expected dl_min
368+
layer_spec = td.LayerRefinementSpec(
369+
axis=2,
370+
size=(td.inf, td.inf, 2),
371+
corner_finder=td.CornerFinderSpec(
372+
dl_min_spec=td.SmallestFeatureSpec(
373+
convex_resolution=10, concave_resolution=0, mixed_resolution=0
374+
)
375+
),
376+
)
377+
dl_min = layer_spec._dl_min_from_smallest_feature([structure])
378+
assert np.allclose(0.3 / 10, dl_min)
379+
380+
layer_spec = td.LayerRefinementSpec(
381+
axis=2,
382+
size=(td.inf, td.inf, 2),
383+
corner_finder=td.CornerFinderSpec(
384+
dl_min_spec=td.SmallestFeatureSpec(
385+
convex_resolution=0, concave_resolution=0, mixed_resolution=10
386+
)
387+
),
388+
)
389+
dl_min = layer_spec._dl_min_from_smallest_feature([structure])
390+
assert np.allclose(0.2 / 10, dl_min)
391+
392+
layer_spec = td.LayerRefinementSpec(
393+
axis=2,
394+
size=(td.inf, td.inf, 2),
395+
corner_finder=td.CornerFinderSpec(
396+
dl_min_spec=td.SmallestFeatureSpec(
397+
convex_resolution=0, concave_resolution=10, mixed_resolution=0
398+
)
399+
),
400+
)
401+
dl_min = layer_spec._dl_min_from_smallest_feature([structure])
402+
assert np.allclose(0.1 / 10, dl_min)
403+
404+
# check grid is generated succesfully
405+
sim = td.Simulation(
406+
size=(5, 5, 5),
407+
structures=[structure],
408+
grid_spec=td.GridSpec.auto(layer_refinement_specs=[layer_spec], wavelength=100 * td.C_0),
409+
run_time=1e-20,
410+
)
411+
412+
_ = sim.grid

tidy3d/components/grid/corner_finder.py

+23-10
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,14 @@
1111
from ..geometry.utils import merging_geometries_on_plane
1212
from ..medium import PEC, LossyMetalMedium
1313
from ..structure import Structure
14-
from ..types import ArrayFloat2D, ArrayFloat1D, Axis
14+
from ..types import ArrayFloat1D, ArrayFloat2D, Axis
1515

1616
CORNER_ANGLE_THRESOLD = 0.1 * np.pi
1717

18-
18+
1919
class SmallestFeatureSpec(Tidy3dBaseModel):
2020
"""Specification for automatic detection of smallest geometric features in layered structures."""
2121

22-
2322
concave_resolution: pd.NonNegativeInt = pd.Field(
2423
2,
2524
title="Concave Region Resolution.",
@@ -42,7 +41,10 @@ class SmallestFeatureSpec(Tidy3dBaseModel):
4241

4342
@cached_property
4443
def _no_restriction(self):
45-
return not any((self.concave_resolution != 0, self.convex_resolution != 0, self.mixed_resolution != 0))
44+
return not any(
45+
(self.concave_resolution != 0, self.convex_resolution != 0, self.mixed_resolution != 0)
46+
)
47+
4648

4749
class CornerFinderSpec(Tidy3dBaseModel):
4850
"""Specification for corner detection on a 2D plane."""
@@ -136,16 +138,19 @@ def _corners_and_convexity(
136138
poly = poly.normalize().buffer(0)
137139
if self.distance_threshold is not None:
138140
poly = poly.simplify(self.distance_threshold, preserve_topology=True)
139-
corners_xy, corners_convexity = self._filter_collinear_vertices(list(poly.exterior.coords))
141+
corners_xy, corners_convexity = self._filter_collinear_vertices(
142+
list(poly.exterior.coords)
143+
)
140144
corner_list.append(corners_xy)
141145
convexity_list.append(corners_convexity)
142146
# in case the polygon has holes
143147
for poly_inner in poly.interiors:
144-
corners_xy, corners_convexity = self._filter_collinear_vertices(list(poly_inner.coords))
148+
corners_xy, corners_convexity = self._filter_collinear_vertices(
149+
list(poly_inner.coords)
150+
)
145151
corner_list.append(corners_xy)
146152
convexity_list.append(corners_convexity)
147153

148-
149154
if ravel and len(corner_list) > 0:
150155
corner_list = np.concatenate(corner_list)
151156
convexity_list = np.concatenate(convexity_list)
@@ -177,10 +182,14 @@ def corners(
177182
Corner coordinates.
178183
"""
179184

180-
corner_list, _ = self._corners_and_covexity(normal_axis=normal_axis, coord=coord, structure_list=structure_list, ravel=True)
185+
corner_list, _ = self._corners_and_convexity(
186+
normal_axis=normal_axis, coord=coord, structure_list=structure_list, ravel=True
187+
)
181188
return corner_list
182189

183-
def _filter_collinear_vertices(self, vertices: ArrayFloat2D) -> Tuple[ArrayFloat2D, ArrayFloat1D]:
190+
def _filter_collinear_vertices(
191+
self, vertices: ArrayFloat2D
192+
) -> Tuple[ArrayFloat2D, ArrayFloat1D]:
184193
"""Filter collinear vertices of a polygon, and return corners locations and their convexity.
185194
186195
Parameters
@@ -213,7 +222,11 @@ def normalize(v):
213222
inner_product = np.where(inner_product < -1, -1, inner_product)
214223
angle = np.arccos(inner_product)
215224
num_vs = len(vs_orig)
216-
cross_product = np.cross(np.hstack([unit_next, np.zeros((num_vs, 1))]), np.hstack([unit_previous, np.zeros((num_vs, 1))]), axis=-1)
225+
cross_product = np.cross(
226+
np.hstack([unit_next, np.zeros((num_vs, 1))]),
227+
np.hstack([unit_previous, np.zeros((num_vs, 1))]),
228+
axis=-1,
229+
)
217230
convexity = cross_product[:, 2] < 0
218231
ind_filter = angle <= np.pi - self.angle_threshold
219232
return vs_orig[ind_filter], convexity[ind_filter]

tidy3d/components/grid/grid_spec.py

+14-8
Original file line numberDiff line numberDiff line change
@@ -1281,7 +1281,7 @@ def suggested_dl_min(self, grid_size_in_vacuum: float, structures: List[Structur
12811281
if self.corner_finder is not None and self.corner_refinement is not None:
12821282
dl_min = min(dl_min, self.corner_refinement._grid_size(grid_size_in_vacuum))
12831283

1284-
# min feature size
1284+
# min feature size
12851285
if self.corner_finder is not None and not self.corner_finder.dl_min_spec._no_restriction:
12861286
dl_suggested = self._dl_min_from_smallest_feature(structures)
12871287
dl_min = min(dl_min, dl_suggested)
@@ -1322,7 +1322,9 @@ def _inplane_inside(self, point: ArrayFloat2D) -> bool:
13221322
)
13231323
return self.inside(point_3d[0], point_3d[1], point_3d[2])
13241324

1325-
def _corners_and_convexity_2d(self, structure_list: List[Structure], ravel: bool) -> List[CoordinateOptional]:
1325+
def _corners_and_convexity_2d(
1326+
self, structure_list: List[Structure], ravel: bool
1327+
) -> List[CoordinateOptional]:
13261328
"""Raw inplane corners and their convexity."""
13271329
if self.corner_finder is None:
13281330
return [], []
@@ -1336,7 +1338,8 @@ def _corners_and_convexity_2d(self, structure_list: List[Structure], ravel: bool
13361338
)
13371339

13381340
# filter corners outside the inplane bounds
1339-
if self._is_inplane_bounded:
1341+
if self._is_inplane_bounded and len(inplane_points) > 0:
1342+
# flatten temporary list of arrays for faster processing
13401343
if not ravel:
13411344
split_inds = np.cumsum([len(pts) for pts in inplane_points])[:-1]
13421345
inplane_points = np.concatenate(inplane_points)
@@ -1349,17 +1352,19 @@ def _corners_and_convexity_2d(self, structure_list: List[Structure], ravel: bool
13491352
convexity = np.split(convexity, split_inds)
13501353

13511354
return inplane_points, convexity
1352-
1355+
13531356
def _dl_min_from_smallest_feature(self, structure_list: List[Structure]):
13541357
"""Calculate `dl_min` suggestion based on smallest feature size."""
13551358

1356-
inplane_points, convexity = self._corners_and_convexity_2d(structure_list=structure_list, ravel=False)
1359+
inplane_points, convexity = self._corners_and_convexity_2d(
1360+
structure_list=structure_list, ravel=False
1361+
)
13571362

13581363
dl_min = inf
13591364

13601365
if self.corner_finder is None or self.corner_finder.dl_min_spec._no_restriction:
13611366
return dl_min
1362-
1367+
13631368
dl_min_spec = self.corner_finder.dl_min_spec
13641369

13651370
for points, conv in zip(inplane_points, convexity):
@@ -1378,7 +1383,6 @@ def _dl_min_from_smallest_feature(self, structure_list: List[Structure]):
13781383
min_concave_size = np.min(lengths[concave_features])
13791384
dl_min = min(dl_min, min_concave_size / dl_min_spec.concave_resolution)
13801385

1381-
13821386
if dl_min_spec.mixed_resolution > 0:
13831387
mixed_features = np.logical_xor(conv, conv_nei)
13841388
if np.any(mixed_features):
@@ -1389,7 +1393,9 @@ def _dl_min_from_smallest_feature(self, structure_list: List[Structure]):
13891393

13901394
def _corners(self, structure_list: List[Structure]) -> List[CoordinateOptional]:
13911395
"""Inplane corners in 3D coordinate."""
1392-
inplane_points, _ = self._corners_and_convexity_2d(structure_list=structure_list, ravel=True)
1396+
inplane_points, _ = self._corners_and_convexity_2d(
1397+
structure_list=structure_list, ravel=True
1398+
)
13931399

13941400
# convert 2d points to 3d
13951401
return [

0 commit comments

Comments
 (0)