Skip to content

Commit e32683d

Browse files
tests
1 parent 5ea418c commit e32683d

File tree

3 files changed

+123
-25
lines changed

3 files changed

+123
-25
lines changed

tests/test_components/test_layerrefinement.py

+86
Original file line numberDiff line numberDiff line change
@@ -402,3 +402,89 @@ def test_dl_min_from_smallest_feature():
402402
)
403403

404404
_ = sim.grid
405+
406+
407+
def test_gap_meshing():
408+
w = 1
409+
l = 10
410+
411+
l_shape_1 = td.Structure(
412+
medium=td.PECMedium(),
413+
geometry=td.PolySlab(
414+
axis=2,
415+
slab_bounds=[0, 2],
416+
vertices=[
417+
[0, 0],
418+
[l, 0],
419+
[l, w],
420+
[w, w],
421+
[w, l],
422+
[0, l],
423+
],
424+
),
425+
)
426+
427+
gap = 0.1
428+
l_shape_2 = td.Structure(
429+
medium=td.PECMedium(),
430+
geometry=td.PolySlab(
431+
axis=2,
432+
slab_bounds=[0, 2],
433+
vertices=[
434+
[w + gap, w + gap],
435+
[w + gap + l, w + gap],
436+
[w + gap + l, w + gap + w],
437+
[w + gap + w, w + gap + w],
438+
[w + gap + w, w + gap + l],
439+
[w + gap, w + gap + l],
440+
[0, w + gap + l],
441+
[0, gap + l],
442+
[w + gap, gap + l],
443+
],
444+
),
445+
)
446+
447+
# ax = l_shape_1.plot(z=1)
448+
# l_shape_2.plot(z=1, ax=ax)
449+
450+
for num_iters in range(2):
451+
grid_spec = td.GridSpec(
452+
grid_x=td.AutoGrid(min_steps_per_wvl=10),
453+
grid_y=td.AutoGrid(min_steps_per_wvl=10),
454+
grid_z=td.AutoGrid(min_steps_per_wvl=10),
455+
layer_refinement_specs=[
456+
td.LayerRefinementSpec(
457+
axis=2,
458+
corner_finder=None,
459+
gap_meshing_iters=num_iters,
460+
size=[td.inf, td.inf, 2],
461+
center=[0, 0, 1],
462+
)
463+
],
464+
wavelength=7,
465+
)
466+
467+
sim = td.Simulation(
468+
structures=[l_shape_1, l_shape_2],
469+
grid_spec=grid_spec,
470+
size=(1.2 * l, 1.2 * l, 2),
471+
center=(0.5 * l, 0.5 * l, 0),
472+
run_time=1e-15,
473+
)
474+
475+
# ax = sim.plot(z=1)
476+
# sim.plot_grid(z=1, ax=ax)
477+
# ax.set_xlim([0, 2])
478+
# ax.set_ylim([0, 2])
479+
480+
resolved_x = np.any(
481+
np.logical_and(sim.grid.boundaries.x > w, sim.grid.boundaries.x < w + gap)
482+
)
483+
resolved_y = np.any(
484+
np.logical_and(sim.grid.boundaries.y > w, sim.grid.boundaries.y < w + gap)
485+
)
486+
487+
if num_iters == 0:
488+
assert (not resolved_x) and (not resolved_y)
489+
else:
490+
assert resolved_x and resolved_y

tidy3d/components/grid/corner_finder.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,6 @@ def _merged_pec_on_plane(
119119

120120
return merged_geos
121121

122-
123122
def _corners_and_convexity(
124123
self,
125124
normal_axis: Axis,
@@ -149,7 +148,9 @@ def _corners_and_convexity(
149148
"""
150149

151150
# merge geometries
152-
merged_geos = self._merged_pec_on_plane(normal_axis=normal_axis, coord=coord, structure_list=structure_list)
151+
merged_geos = self._merged_pec_on_plane(
152+
normal_axis=normal_axis, coord=coord, structure_list=structure_list
153+
)
153154

154155
# corner finder
155156
corner_list = []

tidy3d/components/grid/grid_spec.py

+34-23
Original file line numberDiff line numberDiff line change
@@ -1533,36 +1533,37 @@ def _override_structures_along_axis(
15331533
if refinement_structures[0].dl[self.axis] <= dl:
15341534
override_structures += refinement_structures
15351535
return override_structures
1536-
1536+
15371537
def _find_vertical_intersections(self, x, y, vertices):
15381538
"""Detect intersection points of single polygon and vertical grid lines."""
15391539

15401540
cells_ij = []
15411541
cells_dy = []
15421542
h_inds = np.argmax(x[:, None] > vertices[None, :, 0], axis=0)
15431543
h_inds[vertices[:, 0] > x[-1]] = len(x)
1544-
for ind_beg, ind_end, v_beg, v_end in zip(h_inds, np.roll(h_inds, -1), vertices, np.roll(vertices, axis=0, shift=-1)):
1544+
for ind_beg, ind_end, v_beg, v_end in zip(
1545+
h_inds, np.roll(h_inds, -1), vertices, np.roll(vertices, axis=0, shift=-1)
1546+
):
15451547
# sort vertices in ascending order
15461548
if ind_beg > ind_end:
15471549
ind_beg, ind_end, v_beg, v_end = ind_end, ind_beg, v_end, v_beg
1548-
1550+
15491551
if ind_end > ind_beg:
1550-
15511552
# x coordinates are simply grid x points that are covered by each segment
15521553
h_x = x[ind_beg:ind_end]
1553-
1554+
15541555
# y coordinates can be found from line equation
15551556
h_y = v_beg[1] + (v_end[1] - v_beg[1]) / (v_end[0] - v_beg[0]) * (h_x - v_beg[0])
1556-
1557+
15571558
# however, we need to see which ones are actually inside along y axis
15581559
inds_inside_grid = np.logical_and(h_y >= y[0], h_y <= y[-1])
1559-
1560+
15601561
h_y = h_y[inds_inside_grid]
1561-
1562+
15621563
# find cell j coordinates which contain these intersections
15631564
cell_is = np.arange(ind_beg, ind_end)[inds_inside_grid]
15641565
cell_js = np.searchsorted(y, h_y) - 1
1565-
1566+
15661567
# find local dy
15671568
dy = h_y - y[cell_js]
15681569

@@ -1576,7 +1577,7 @@ def _find_vertical_intersections(self, x, y, vertices):
15761577
cells_dy = np.concatenate(cells_dy)
15771578

15781579
return cells_ij, cells_dy
1579-
1580+
15801581
def _process_poly(self, x, y, vertices):
15811582
"""Detect intersection points of single polygon and grid lines."""
15821583
v_cells_ij, v_cells_dy = self._find_vertical_intersections(x, y, vertices)
@@ -1585,7 +1586,7 @@ def _process_poly(self, x, y, vertices):
15851586
if len(h_cells_ij) > 0:
15861587
h_cells_ij = np.roll(h_cells_ij, axis=1, shift=1)
15871588
return v_cells_ij, v_cells_dy, h_cells_ij, h_cells_dx
1588-
1589+
15891590
def _process_slice(self, x, y, merged_geos):
15901591
"""Detect intersection points of geometries boundaries and grid lines."""
15911592
v_cells_ij = []
@@ -1600,15 +1601,15 @@ def _process_slice(self, x, y, merged_geos):
16001601
for poly in polygon_list:
16011602
poly = poly.normalize().buffer(0)
16021603
data = self._process_poly(x, y, np.array(poly.exterior.coords)[:-1])
1603-
1604+
16041605
if len(data[0]) > 0:
16051606
v_cells_ij.append(data[0])
16061607
v_cells_dy.append(data[1])
16071608

16081609
if len(data[2]) > 0:
16091610
h_cells_ij.append(data[2])
16101611
h_cells_dx.append(data[3])
1611-
1612+
16121613
# in case the polygon has holes
16131614
for poly_inner in poly.interiors:
16141615
data = self._process_poly(x, y, np.array(poly_inner.coords)[:-1])
@@ -1633,13 +1634,14 @@ def _process_slice(self, x, y, merged_geos):
16331634
h_cells_dx = np.concatenate(h_cells_dx)
16341635

16351636
return v_cells_ij, v_cells_dy, h_cells_ij, h_cells_dx
1636-
16371637

16381638
def _resolve_gaps(self, structures: List, grid: Grid):
16391639
"""Detect underresolved gaps and place snapping lines in them. Also return the detected minimal gap width."""
16401640

16411641
# get merged pec structures on plane
1642-
plane_slice = CornerFinderSpec._merged_pec_on_plane(coord=self.center_axis, normal_axis=self.axis, structure_list=structures)
1642+
plane_slice = CornerFinderSpec._merged_pec_on_plane(
1643+
coord=self.center_axis, normal_axis=self.axis, structure_list=structures
1644+
)
16431645

16441646
_, tan_dims = Box.pop_axis([0, 1, 2], self.axis)
16451647
x = grid.boundaries.to_list[tan_dims[0]]
@@ -1654,7 +1656,9 @@ def _resolve_gaps(self, structures: List, grid: Grid):
16541656
snapping_lines_y = []
16551657
if len(v_cells_ij) > 0:
16561658
# add number of intersections
1657-
ind_unique, counts = np.unique(v_cells_ij[:, 0] * len(y) + v_cells_ij[:, 1], return_counts=True)
1659+
ind_unique, counts = np.unique(
1660+
v_cells_ij[:, 0] * len(y) + v_cells_ij[:, 1], return_counts=True
1661+
)
16581662
ind_unique_j = ind_unique % len(y)
16591663
for ind_j in np.unique(ind_unique_j):
16601664
max_count = np.max(counts[ind_unique_j == ind_j])
@@ -1669,7 +1673,9 @@ def _resolve_gaps(self, structures: List, grid: Grid):
16691673
snapping_lines_x = []
16701674
if len(h_cells_ij) > 0:
16711675
# add number of intersections
1672-
ind_unique, counts = np.unique(h_cells_ij[:, 0] * len(y) + h_cells_ij[:, 1], return_counts=True)
1676+
ind_unique, counts = np.unique(
1677+
h_cells_ij[:, 0] * len(y) + h_cells_ij[:, 1], return_counts=True
1678+
)
16731679
ind_unique_i = ind_unique // len(y)
16741680
for ind_i in np.unique(ind_unique_i):
16751681
max_count = np.max(counts[ind_unique_i == ind_i])
@@ -1680,7 +1686,9 @@ def _resolve_gaps(self, structures: List, grid: Grid):
16801686
snapping_lines_x.append(x[ind_i] + 0.5 * (min_dx + max_dx))
16811687
detected_gap_width = min(detected_gap_width, max_dy - min_dy)
16821688

1683-
return [Box.unpop_axis(X, (None, None), axis=tan_dims[0]) for X in snapping_lines_x] + [Box.unpop_axis(Y, (None, None), axis=tan_dims[1]) for Y in snapping_lines_y], detected_gap_width
1689+
return [Box.unpop_axis(X, (None, None), axis=tan_dims[0]) for X in snapping_lines_x] + [
1690+
Box.unpop_axis(Y, (None, None), axis=tan_dims[1]) for Y in snapping_lines_y
1691+
], detected_gap_width
16841692

16851693

16861694
class GridSpec(Tidy3dBaseModel):
@@ -2067,7 +2075,7 @@ def get_wavelength(self, sources: List[SourceType]) -> float:
20672075
wavelength = self.wavelength_from_sources(sources)
20682076
log.info(f"Auto meshing using wavelength {wavelength:1.4f} defined from sources.")
20692077
return wavelength
2070-
2078+
20712079
def make_grid(
20722080
self,
20732081
structures: List[Structure],
@@ -2118,15 +2126,19 @@ def make_grid(
21182126
)
21192127

21202128
if len(self.layer_refinement_specs) > 0:
2121-
num_iters = max(layer_spec.gap_meshing_iters for layer_spec in self.layer_refinement_specs)
2122-
2129+
num_iters = max(
2130+
layer_spec.gap_meshing_iters for layer_spec in self.layer_refinement_specs
2131+
)
2132+
21232133
snapping_lines = []
21242134
min_gap_width = inf
21252135
for ind in range(num_iters):
21262136
new_snapping_lines = []
21272137
for layer_spec in self.layer_refinement_specs:
21282138
if layer_spec.gap_meshing_iters > ind:
2129-
one_layer_snapping_lines, gap_width = layer_spec._resolve_gaps(structures, old_grid)
2139+
one_layer_snapping_lines, gap_width = layer_spec._resolve_gaps(
2140+
structures, old_grid
2141+
)
21302142
new_snapping_lines = new_snapping_lines + one_layer_snapping_lines
21312143
if layer_spec.dl_min_from_gap_width:
21322144
min_gap_width = min(min_gap_width, gap_width)
@@ -2158,7 +2170,6 @@ def make_grid(
21582170
old_grid = new_grid
21592171

21602172
return old_grid
2161-
21622173

21632174
def _make_grid_one_iteration(
21642175
self,

0 commit comments

Comments
 (0)