Skip to content

Commit b8de2ee

Browse files
authored
Fix bug in collapse_array for point objects of DFT fields in 1D cell and add unit test (#3010)
* fix bug in collapse_array for point objects and add unit test * add support for planewave with arbitrary wavevector
1 parent bc5ac50 commit b8de2ee

File tree

3 files changed

+157
-4
lines changed

3 files changed

+157
-4
lines changed

python/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ TESTS = \
8585
$(TEST_DIR)/test_oblique_source.py \
8686
$(TEST_DIR)/test_pml_cyl.py \
8787
$(TEST_DIR)/test_physical.py \
88+
$(TEST_DIR)/test_planewave_1D.py \
8889
$(TEST_DIR)/test_prism.py \
8990
$(TEST_DIR)/test_pw_source.py \
9091
$(TEST_DIR)/test_refl_angular.py \

python/tests/test_planewave_1D.py

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# Verifies properties of the fields of a planewave using a 1D or 3D simulation.
2+
3+
4+
from typing import Tuple
5+
import unittest
6+
7+
import meep as mp
8+
import numpy as np
9+
10+
11+
class TestPlanewave1D(unittest.TestCase):
12+
def planewave_in_vacuum(
13+
self,
14+
resolution_um: float,
15+
polar_rad: float,
16+
azimuth_rad: float,
17+
cell_dim: int,
18+
yee_grid: bool,
19+
) -> None:
20+
"""
21+
Verifies properties of the fields of a planewave in 1D or 3D.
22+
23+
Computes the DFT fields at two different positions in the 1D grid and
24+
determines that these fields:
25+
(1) have the expected relative phase, and
26+
(2) are the same when obtained as a single point or a slice of an
27+
array over the entire cell.
28+
29+
Args:
30+
resolution_um: resolution of the grid (number of pixels per um).
31+
polar_rad: polar angle of the incident planewave. 0 is +x axis.
32+
azimuth_rad: azimuth angle of the incident planewave. 0 is +z axis.
33+
cell_dim: dimension of the cell (1 or 3).
34+
yee_grid: whether the DFT fields are on a centered or Yee grid.
35+
"""
36+
print(
37+
f"Testing planewaves in vacuum using {cell_dim}D simulation and "
38+
f"{'yee' if yee_grid else 'centered'} grid..."
39+
)
40+
41+
pml_um = 1.0
42+
air_um = 10.0
43+
size_z_um = pml_um + air_um + pml_um
44+
cell_size = mp.Vector3(0, 0, size_z_um)
45+
pml_layers = [mp.PML(thickness=pml_um)]
46+
47+
wavelength_um = 1.0
48+
frequency = 1 / wavelength_um
49+
kx = frequency * np.sin(azimuth_rad) * np.cos(azimuth_rad)
50+
ky = frequency * np.sin(azimuth_rad) * np.sin(azimuth_rad)
51+
kz = frequency * np.cos(azimuth_rad)
52+
53+
if cell_dim == 1 and polar_rad != 0 and azimuth_rad != 0:
54+
raise ValueError("An oblique planewave cannot be simulated in 1D.")
55+
56+
if cell_dim == 1:
57+
k_point = False
58+
dimensions = 1
59+
elif cell_dim == 3:
60+
k_point = mp.Vector3(kx, ky, 0)
61+
dimensions = 3
62+
else:
63+
raise ValueError("cell_dim can only be 1 or 3.")
64+
65+
src_cmpt = mp.Ex
66+
sources = [
67+
mp.Source(
68+
src=mp.GaussianSource(frequency, fwidth=0.1 * frequency),
69+
component=src_cmpt,
70+
center=mp.Vector3(0, 0, -0.5 * air_um),
71+
)
72+
]
73+
74+
sim = mp.Simulation(
75+
resolution=resolution_um,
76+
force_complex_fields=True,
77+
cell_size=cell_size,
78+
sources=sources,
79+
boundary_layers=pml_layers,
80+
k_point=k_point,
81+
dimensions=dimensions,
82+
)
83+
84+
dft_fields = sim.add_dft_fields(
85+
[mp.Ex],
86+
frequency,
87+
0,
88+
1,
89+
center=mp.Vector3(0, 0, 0),
90+
size=mp.Vector3(0, 0, size_z_um),
91+
yee_grid=yee_grid,
92+
)
93+
94+
z_pos_1 = -0.234804
95+
dft_fields_1 = sim.add_dft_fields(
96+
[mp.Ex],
97+
frequency,
98+
0,
99+
1,
100+
center=mp.Vector3(0, 0, z_pos_1),
101+
size=mp.Vector3(0, 0, 0),
102+
yee_grid=yee_grid,
103+
)
104+
105+
z_pos_2 = 2.432973
106+
dft_fields_2 = sim.add_dft_fields(
107+
[mp.Ex],
108+
frequency,
109+
0,
110+
1,
111+
center=mp.Vector3(0, 0, z_pos_2),
112+
size=mp.Vector3(0, 0, 0),
113+
yee_grid=yee_grid,
114+
)
115+
116+
sim.run(
117+
until_after_sources=mp.stop_when_fields_decayed(
118+
25, src_cmpt, mp.Vector3(0, 0, 0.5 * air_um), 1e-6
119+
)
120+
)
121+
122+
# Check that the relative phase of the fields obtained from a slice of
123+
# an array of the fields over the entire cell matches the analytic
124+
# result.
125+
ex_dft = sim.get_dft_array(dft_fields, mp.Ex, 0)
126+
z_um = np.linspace(-0.5 * size_z_um, 0.5 * size_z_um, len(ex_dft))
127+
z_idx_1 = np.argmin(np.abs(z_pos_1 - z_um))
128+
z_idx_2 = np.argmin(np.abs(z_pos_2 - z_um))
129+
meep_phase = ex_dft[z_idx_2] / ex_dft[z_idx_1]
130+
expected_phase = np.exp(1j * 2 * np.pi * kz * (z_um[z_idx_2] - z_um[z_idx_1]))
131+
self.assertAlmostEqual(meep_phase, expected_phase, delta=0.05)
132+
133+
# Check that the relative phase of the fields obtained from a point
134+
# location matches the analytic result.
135+
ex_dft_pos_1 = sim.get_dft_array(dft_fields_1, mp.Ex, 0)
136+
ex_dft_pos_2 = sim.get_dft_array(dft_fields_2, mp.Ex, 0)
137+
meep_phase = ex_dft_pos_2 / ex_dft_pos_1
138+
expected_phase = np.exp(1j * 2 * np.pi * kz * (z_pos_2 - z_pos_1))
139+
self.assertAlmostEqual(meep_phase, expected_phase, delta=0.05)
140+
141+
# Check that the fields obtained using the two approaches match.
142+
self.assertAlmostEqual(ex_dft[z_idx_1], ex_dft_pos_1, delta=0.08)
143+
self.assertAlmostEqual(ex_dft[z_idx_2], ex_dft_pos_2, delta=0.08)
144+
145+
print("PASSED.")
146+
147+
def test_planewave_1D(self):
148+
self.planewave_in_vacuum(400.0, 0.0, 0.0, 1, False)
149+
self.planewave_in_vacuum(200.0, 0.0, 0.0, 3, False)
150+
151+
self.planewave_in_vacuum(400.0, 0.0, 0.0, 1, True)
152+
self.planewave_in_vacuum(200.0, 0.0, 0.0, 3, True)
153+
154+
155+
if __name__ == "__main__":
156+
unittest.main()

src/array_slice.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -567,10 +567,6 @@ realnum *collapse_array(realnum *array, int *rank, size_t dims[3], direction dir
567567
reduced_dirs, reduced_stride);
568568

569569
if (full_rank == 0) return array;
570-
if (reduced_rank == 0) {
571-
*rank = 0;
572-
return array; // return array as is for singleton use case
573-
}
574570
if (reduced_rank == full_rank) return array; // nothing to collapse
575571

576572
/*--------------------------------------------------------------*/

0 commit comments

Comments
 (0)