Skip to content

Commit 34938d1

Browse files
committed
moving to backend
1 parent 710f8c3 commit 34938d1

File tree

3 files changed

+52
-325
lines changed

3 files changed

+52
-325
lines changed

tests/test_plugins/test_mode_solver.py

Lines changed: 0 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1237,87 +1237,6 @@ def test_high_order_mode_normalization():
12371237
assert (values[: values.size // 3] > 0).all()
12381238

12391239

1240-
# Test that a mode solver with an angle and PEC symmetry does not produce unphysical modes
1241-
def test_mode_solver_angle_symmetry():
1242-
# Angle to test
1243-
theta = np.pi / 180
1244-
# theta = np.pi / 6
1245-
1246-
# Other parameters
1247-
plane = td.Box(center=(0, 0, 0), size=(5, 0, 8))
1248-
sim_size = (10, 10, 10)
1249-
# sim_size = (4, 3, 3)
1250-
freq0 = td.C_0 / 1.0
1251-
1252-
# Make the default waveguide lossless to also test numerical loss artifact in the angled case
1253-
wg = WAVEGUIDE.updated_copy(medium=td.Medium(permittivity=4))
1254-
1255-
# ModeSource at an angle for visualization aid
1256-
src = td.ModeSource(
1257-
source_time=td.GaussianPulse(freq0=2e14, fwidth=1e13),
1258-
center=plane.center,
1259-
size=plane.size,
1260-
mode_spec=td.ModeSpec(num_modes=1, angle_theta=theta),
1261-
mode_index=0,
1262-
direction="+",
1263-
)
1264-
1265-
# Mode solver without angle
1266-
simulation = td.Simulation(
1267-
size=sim_size,
1268-
grid_spec=td.GridSpec.auto(wavelength=1.0, min_steps_per_wvl=10),
1269-
# grid_spec=td.GridSpec.uniform(dl=0.04),
1270-
structures=[wg],
1271-
run_time=1e-12,
1272-
symmetry=(-1, 0, 0),
1273-
sources=[src],
1274-
# medium=td.Medium(permittivity=4.5),
1275-
)
1276-
1277-
# simulation = td.Simulation.from_file("/home/momchil/flexcompute/test_fdtd/lucas/FDTD_Setup_P1@0_v1.json")
1278-
# print(simulation.grid.num_cells)
1279-
# freq0 = simulation.sources[0].source_time.freq0
1280-
# plane = td.Box(center=simulation.monitors[1].center, size=simulation.monitors[1].size)
1281-
1282-
mode_spec = td.ModeSpec(num_modes=5)
1283-
ms = ModeSolver(
1284-
simulation=simulation,
1285-
plane=plane,
1286-
mode_spec=mode_spec,
1287-
freqs=[freq0],
1288-
)
1289-
modes_zero = ms.solve()
1290-
1291-
# Compute modes with angle
1292-
wg = wg.updated_copy(geometry=wg.geometry.rotated(angle=-theta, axis=[0, 0, 1]))
1293-
simulation = simulation.updated_copy(structures=[wg])
1294-
mode_spec = mode_spec.updated_copy(angle_theta=theta)
1295-
ms_angle = ms.updated_copy(mode_spec=mode_spec, simulation=simulation)
1296-
modes_angle = ms_angle.solve()
1297-
1298-
# import matplotlib.pyplot as plt
1299-
1300-
# fig, ax = plt.subplots(1, 3)
1301-
# simulation.plot(x=0, ax=ax[0])
1302-
# simulation.plot(y=0, ax=ax[1])
1303-
# simulation.plot(z=0, ax=ax[2])
1304-
# plt.show()
1305-
1306-
# Plot the mode_index = 0 mode for both
1307-
_, ax = plt.subplots(1, 2)
1308-
ms.plot_field("E", mode_index=0, ax=ax[0], robust=False)
1309-
ms_angle.plot_field("E", mode_index=0, ax=ax[1], robust=False)
1310-
plt.show()
1311-
1312-
print(modes_zero.n_complex.values)
1313-
print(modes_angle.n_complex.values)
1314-
1315-
# Modes with and without an angle are close
1316-
assert np.allclose(modes_zero.n_complex.values, modes_angle.n_complex.values, atol=2e-2)
1317-
# Modes with angle (tensorial mode solver) have a small k_eff
1318-
assert np.all(np.abs(modes_angle.k_eff) < 1e-10)
1319-
1320-
13211240
def test_gauge_robustness():
13221241
array = np.zeros((5, 5), dtype=float)
13231242
ij = np.arange(5)
@@ -1367,7 +1286,3 @@ def test_translated_dot():
13671286

13681287
assert np.allclose(data2.outer_dot(data_translated), data2.outer_dot(data2), atol=atol)
13691288
assert np.allclose(data_translated.outer_dot(data2), data2.outer_dot(data2), atol=atol)
1370-
1371-
1372-
if __name__ == "__main__":
1373-
test_mode_solver_angle_symmetry()

tidy3d/components/mode/derivatives.py

Lines changed: 0 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -240,119 +240,3 @@ def s_value(
240240
kappa = kappa_min + (kappa_max - kappa_min) * step**order
241241
sigma = sigma_max * avg_speed / (ETA_0 * dl) * step**order
242242
return kappa + 1j * sigma / (omega * EPSILON_0)
243-
244-
245-
def make_cxf(dls, shape, pmc):
246-
"""Forward colocation in x."""
247-
import scipy.sparse as sp
248-
249-
Nx, Ny = shape
250-
if Nx == 1:
251-
return sp.csr_matrix((Ny, Ny))
252-
# Create matrix with [1,1,0,...,0], [0,1,1,...,0], etc pattern
253-
cxf = 0.5 * sp.csr_matrix(sp.diags([1, 1], [0, 1], shape=(Nx, Nx)))
254-
255-
# Apply boundary conditions before Kronecker product
256-
if not pmc:
257-
cxf[0, 0] = 0
258-
259-
return sp.kron(cxf, sp.eye(Ny))
260-
261-
262-
def make_cxb(dls, shape, pmc):
263-
"""Backward colocation in x."""
264-
265-
# return make_cxf(dls, shape, pmc).T
266-
267-
import scipy.sparse as sp
268-
269-
Nx, Ny = shape
270-
if Nx == 1:
271-
return sp.csr_matrix((Ny, Ny))
272-
273-
# Calculate weights for each position
274-
p1 = dls[:-1] # First grid spacing
275-
p2 = dls[1:] # Second grid spacing
276-
277-
weights_curr = np.ones(Nx)
278-
weights_curr[1:] = p1 / (p1 + p2)
279-
280-
weights_prev = np.zeros(Nx)
281-
weights_prev[:-1] = p2 / (p1 + p2)
282-
283-
# Create the matrix using diagonals
284-
cxb = sp.diags([weights_curr, weights_prev], [0, -1], shape=(Nx, Nx))
285-
286-
# Apply boundary conditions before Kronecker product
287-
# The matrix is already set up for PEC (cxb[0, 0] = 1)
288-
if pmc:
289-
cxb[0, 0] = 0
290-
291-
return sp.kron(cxb, sp.eye(Ny))
292-
293-
294-
def make_cyf(dls, shape, pmc):
295-
"""Forward colocation in y."""
296-
import scipy.sparse as sp
297-
298-
Nx, Ny = shape
299-
if Ny == 1:
300-
return sp.csr_matrix((Nx, Nx))
301-
# Create matrix with [1,1,0,...,0], [0,1,1,...,0], etc pattern
302-
cyf = 0.5 * sp.csr_matrix(sp.diags([1, 1], [0, 1], shape=(Ny, Ny)))
303-
304-
# Apply boundary conditions before Kronecker product
305-
if not pmc:
306-
cyf[0, 0] = 0
307-
308-
return sp.kron(sp.eye(Nx), cyf)
309-
310-
311-
def make_cyb(dls, shape, pmc):
312-
"""Backward colocation in y."""
313-
314-
# return make_cyf(dls, shape, pmc).T
315-
316-
import scipy.sparse as sp
317-
318-
Nx, Ny = shape
319-
if Ny == 1:
320-
return sp.csr_matrix((Nx, Nx))
321-
322-
# Calculate weights for each position
323-
p1 = dls[:-1] # First grid spacing
324-
p2 = dls[1:] # Second grid spacing
325-
326-
weights_curr = np.ones(Ny)
327-
weights_curr[1:] = p1 / (p1 + p2)
328-
329-
weights_prev = np.zeros(Ny)
330-
weights_prev[:-1] = p2 / (p1 + p2)
331-
332-
# Create the matrix using diagonals
333-
cyb = sp.diags([weights_curr, weights_prev], [0, -1], shape=(Ny, Ny))
334-
335-
# Apply boundary conditions before Kronecker product
336-
# The matrix is already set up for PEC (cyb[0, 0] = 1)
337-
if pmc:
338-
cyb[0, 0] = 0
339-
340-
return sp.kron(sp.eye(Nx), cyb)
341-
342-
343-
def create_c_matrices(shape, dls, dmin_pmc=(False, False)):
344-
"""Make the colocation matrices. If dmin_pmc is True, the matrices will be modified
345-
to implement PMC boundary conditions, otherwise they will implement PEC."""
346-
347-
dlf, _ = dls
348-
cxf = make_cxf(dlf[0], shape, dmin_pmc[0])
349-
cxb = make_cxb(dlf[0], shape, dmin_pmc[0]) # Note: uses primal grid spacings
350-
cyf = make_cyf(dlf[1], shape, dmin_pmc[1])
351-
cyb = make_cyb(dlf[1], shape, dmin_pmc[1]) # Note: uses primal grid spacings
352-
353-
# cxf = sp.eye(shape[0] * shape[1])
354-
# cxb = sp.eye(shape[0] * shape[1])
355-
# cyf = sp.eye(shape[0] * shape[1])
356-
# cyb = sp.eye(shape[0] * shape[1])
357-
358-
return (cxf, cxb, cyf, cyb)

0 commit comments

Comments
 (0)