Skip to content

Commit 97fab18

Browse files
formatting
1 parent 7dcbefb commit 97fab18

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
@@ -541,35 +541,3 @@ def test_uniform_grid_dl_validation(dl, expect_exception):
541541
grid_spec=td.GridSpec.uniform(dl=dl),
542542
run_time=1e-12,
543543
)
544-
545-
def test_dl_min_from_smallest_feature():
546-
547-
structure = td.Structure(
548-
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),
549-
medium=td.PECMedium(),
550-
)
551-
552-
# check expected dl_min
553-
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)))
554-
dl_min = layer_spec._dl_min_from_smallest_feature([structure])
555-
assert(np.allclose(0.3 / 10, dl_min))
556-
557-
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)))
558-
dl_min = layer_spec._dl_min_from_smallest_feature([structure])
559-
assert(np.allclose(0.2 / 10, dl_min))
560-
561-
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)))
562-
dl_min = layer_spec._dl_min_from_smallest_feature([structure])
563-
assert(np.allclose(0.1 / 10, dl_min))
564-
565-
566-
# check grid is generated succesfully
567-
sim = td.Simulation(
568-
size=(5, 5, 5),
569-
structures=[structure],
570-
grid_spec=td.GridSpec.auto(layer_refinement_specs=[layer_spec], wavelength=100 * td.C_0),
571-
run_time=1e-20,
572-
)
573-
574-
_ = sim.grid
575-

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
@@ -1294,7 +1294,7 @@ def suggested_dl_min(self, grid_size_in_vacuum: float, structures: List[Structur
12941294
if self.corner_finder is not None and self.corner_refinement is not None:
12951295
dl_min = min(dl_min, self.corner_refinement._grid_size(grid_size_in_vacuum))
12961296

1297-
# min feature size
1297+
# min feature size
12981298
if self.corner_finder is not None and not self.corner_finder.dl_min_spec._no_restriction:
12991299
dl_suggested = self._dl_min_from_smallest_feature(structures)
13001300
dl_min = min(dl_min, dl_suggested)
@@ -1335,7 +1335,9 @@ def _inplane_inside(self, point: ArrayFloat2D) -> bool:
13351335
)
13361336
return self.inside(point_3d[0], point_3d[1], point_3d[2])
13371337

1338-
def _corners_and_convexity_2d(self, structure_list: List[Structure], ravel: bool) -> List[CoordinateOptional]:
1338+
def _corners_and_convexity_2d(
1339+
self, structure_list: List[Structure], ravel: bool
1340+
) -> List[CoordinateOptional]:
13391341
"""Raw inplane corners and their convexity."""
13401342
if self.corner_finder is None:
13411343
return [], []
@@ -1349,7 +1351,8 @@ def _corners_and_convexity_2d(self, structure_list: List[Structure], ravel: bool
13491351
)
13501352

13511353
# filter corners outside the inplane bounds
1352-
if self._is_inplane_bounded:
1354+
if self._is_inplane_bounded and len(inplane_points) > 0:
1355+
# flatten temporary list of arrays for faster processing
13531356
if not ravel:
13541357
split_inds = np.cumsum([len(pts) for pts in inplane_points])[:-1]
13551358
inplane_points = np.concatenate(inplane_points)
@@ -1362,17 +1365,19 @@ def _corners_and_convexity_2d(self, structure_list: List[Structure], ravel: bool
13621365
convexity = np.split(convexity, split_inds)
13631366

13641367
return inplane_points, convexity
1365-
1368+
13661369
def _dl_min_from_smallest_feature(self, structure_list: List[Structure]):
13671370
"""Calculate `dl_min` suggestion based on smallest feature size."""
13681371

1369-
inplane_points, convexity = self._corners_and_convexity_2d(structure_list=structure_list, ravel=False)
1372+
inplane_points, convexity = self._corners_and_convexity_2d(
1373+
structure_list=structure_list, ravel=False
1374+
)
13701375

13711376
dl_min = inf
13721377

13731378
if self.corner_finder is None or self.corner_finder.dl_min_spec._no_restriction:
13741379
return dl_min
1375-
1380+
13761381
dl_min_spec = self.corner_finder.dl_min_spec
13771382

13781383
for points, conv in zip(inplane_points, convexity):
@@ -1391,7 +1396,6 @@ def _dl_min_from_smallest_feature(self, structure_list: List[Structure]):
13911396
min_concave_size = np.min(lengths[concave_features])
13921397
dl_min = min(dl_min, min_concave_size / dl_min_spec.concave_resolution)
13931398

1394-
13951399
if dl_min_spec.mixed_resolution > 0:
13961400
mixed_features = np.logical_xor(conv, conv_nei)
13971401
if np.any(mixed_features):
@@ -1402,7 +1406,9 @@ def _dl_min_from_smallest_feature(self, structure_list: List[Structure]):
14021406

14031407
def _corners(self, structure_list: List[Structure]) -> List[CoordinateOptional]:
14041408
"""Inplane corners in 3D coordinate."""
1405-
inplane_points, _ = self._corners_and_convexity_2d(structure_list=structure_list, ravel=True)
1409+
inplane_points, _ = self._corners_and_convexity_2d(
1410+
structure_list=structure_list, ravel=True
1411+
)
14061412

14071413
# convert 2d points to 3d
14081414
return [

0 commit comments

Comments
 (0)