meanas/examples/fdfd1.py

171 lines
5.9 KiB
Python
Raw Normal View History

import importlib
2016-05-30 22:30:45 -07:00
import numpy
from numpy.linalg import norm
from matplotlib import pyplot, colors
import logging
2016-05-30 22:30:45 -07:00
2019-08-04 14:13:51 -07:00
import meanas
2019-11-27 22:59:52 -08:00
from meanas import fdtd
from meanas.fdmath import vec, unvec
from meanas.fdfd import waveguide_3d, functional, scpml, operators
2019-08-04 14:13:51 -07:00
from meanas.fdfd.solvers import generic as generic_solver
2016-05-30 22:30:45 -07:00
import gridlock
2019-11-27 22:59:52 -08:00
logging.basicConfig(level=logging.DEBUG)
2021-09-05 17:49:08 -07:00
logging.getLogger('matplotlib').setLevel(logging.WARNING)
2016-07-04 16:35:28 -07:00
2016-05-30 22:30:45 -07:00
__author__ = 'Jan Petykiewicz'
def test1(solver=generic_solver):
2016-05-30 22:30:45 -07:00
dx = 40 # discretization (nm/cell)
pml_thickness = 10 # (number of cells)
wl = 1550 # Excitation wavelength
omega = 2 * numpy.pi / wl
# Device design parameters
w = 600
th = 220
center = [0, 0, 0]
# refractive indices
n_wg = numpy.sqrt(12.6) # ~Si
n_air = 1.0 # air
# Half-dimensions of the simulation grid
xyz_max = numpy.array([0.8, 0.9, 0.6]) * 1000 + (pml_thickness + 2) * dx
# Coordinates of the edges of the cells.
half_edge_coords = [numpy.arange(dx/2, m + dx/2, step=dx) for m in xyz_max]
edge_coords = [numpy.hstack((-h[::-1], h)) for h in half_edge_coords]
# #### Create the grid and draw the device ####
2022-10-04 12:29:11 -07:00
grid = gridlock.Grid(edge_coords)
epsilon = grid.allocate(n_air**2, dtype=numpy.float32)
grid.draw_cuboid(epsilon, x=dict(center=0, span=8e3), y=dict(center=0, span=w), z=dict(center=0, span=th), foreground=n_wg**2)
2016-05-30 22:30:45 -07:00
2016-07-03 14:23:24 -07:00
dxes = [grid.dxyz, grid.autoshifted_dxyz()]
2016-05-30 22:30:45 -07:00
for a in (0, 1, 2):
for p in (-1, 1):
2019-08-04 14:13:51 -07:00
dxes = scpml.stretch_with_scpml(dxes,omega=omega, axis=a, polarity=p,
thickness=pml_thickness)
2016-05-30 22:30:45 -07:00
half_dims = numpy.array([10, 20, 15]) * dx
dims = [-half_dims, half_dims]
dims[1][0] = dims[0][0]
ind_dims = (grid.pos2ind(dims[0], which_shifts=None).astype(int),
grid.pos2ind(dims[1], which_shifts=None).astype(int))
2019-08-26 01:12:36 -07:00
src_axis = 0
2016-05-30 22:30:45 -07:00
wg_args = {
'slices': [slice(i, f+1) for i, f in zip(*ind_dims)],
'dxes': dxes,
2019-08-26 01:12:36 -07:00
'axis': src_axis,
2016-05-30 22:30:45 -07:00
'polarity': +1,
}
2022-10-04 12:29:11 -07:00
wg_results = waveguide_3d.solve_mode(mode_number=0, omega=omega, epsilon=epsilon, **wg_args)
2019-11-27 22:59:52 -08:00
J = waveguide_3d.compute_source(E=wg_results['E'], wavenumber=wg_results['wavenumber'],
2022-10-04 12:29:11 -07:00
omega=omega, epsilon=epsilon, **wg_args)
2019-11-27 22:59:52 -08:00
e_overlap = waveguide_3d.compute_overlap_e(E=wg_results['E'], wavenumber=wg_results['wavenumber'], **wg_args)
2016-05-30 22:30:45 -07:00
2022-10-04 12:29:11 -07:00
pecg = numpy.zeros_like(epsilon)
# pecg.draw_cuboid(pecg, center=[700, 0, 0], dimensions=[80, 1e8, 1e8], eps=1)
# pecg.visualize_isosurface(pecg)
2016-07-03 14:23:51 -07:00
2022-10-04 12:29:11 -07:00
pmcg = numpy.zeros_like(epsilon)
# grid.draw_cuboid(pmcg, center=[700, 0, 0], dimensions=[80, 1e8, 1e8], eps=1)
# grid.visualize_isosurface(pmcg)
2016-07-03 16:45:38 -07:00
grid.visualize_slice(J.imag, plane=dict(y=6*dx), which_shifts=1, pcolormesh_args=dict(norm=colors.CenteredNorm(), cmap='bwr'))
fig, ax = pyplot.subplots()
ax.pcolormesh((numpy.abs(J).sum(axis=2).sum(axis=0) > 0).astype(float).T, cmap='hot')
2019-08-30 22:03:54 -07:00
pyplot.show(block=True)
2025-01-14 21:59:12 -08:00
#
# Solve!
#
sim_args = {
'omega': omega,
'dxes': dxes,
2022-10-04 12:29:11 -07:00
'epsilon': vec(epsilon),
'pec': vec(pecg),
'pmc': vec(pmcg),
}
x = solver(J=vec(J), **sim_args)
2016-05-30 22:30:45 -07:00
b = -1j * omega * vec(J)
2019-08-04 14:13:51 -07:00
A = operators.e_full(**sim_args).tocsr()
print('Norm of the residual is ', norm(A @ x - b))
2016-07-04 16:35:28 -07:00
2016-05-30 22:30:45 -07:00
E = unvec(x, grid.shape)
2025-01-14 21:59:12 -08:00
#
# Plot results
#
2016-05-30 22:30:45 -07:00
center = grid.pos2ind([0, 0, 0], None).astype(int)
fig, axes = pyplot.subplots(2, 2)
grid.visualize_slice(E.real, plane=dict(x=0), which_shifts=1, ax=axes[0, 0], finalize=False, pcolormesh_args=dict(norm=colors.CenteredNorm(), cmap='bwr'))
grid.visualize_slice(E.real, plane=dict(z=0), which_shifts=1, ax=axes[0, 1], finalize=False, pcolormesh_args=dict(norm=colors.CenteredNorm(), cmap='bwr'))
# pcolor(axes[0, 0], numpy.real(E[1][center[0], :, :]).T)
# pcolor(axes[0, 1], numpy.real(E[1][:, :, center[2]]).T)
axes[1, 0].plot(numpy.log10(numpy.abs(E[1][:, center[1], center[2]]) + 1e-10))
axes[1, 0].grid(alpha=0.6)
axes[1, 0].set_ylabel('log10 of field')
2016-05-30 22:30:45 -07:00
def poyntings(E):
2019-08-30 22:03:54 -07:00
H = functional.e2h(omega, dxes)(E)
2019-10-27 12:46:12 -07:00
poynting = fdtd.poynting(e=E, h=H.conj(), dxes=dxes)
2019-08-30 22:03:54 -07:00
cross1 = operators.poynting_e_cross(vec(E), dxes) @ vec(H).conj()
2019-09-27 20:48:03 -07:00
cross2 = operators.poynting_h_cross(vec(H), dxes) @ vec(E).conj() * -1
2019-10-27 12:46:12 -07:00
s1 = 0.5 * unvec(numpy.real(cross1), grid.shape)
s2 = 0.5 * unvec(numpy.real(cross2), grid.shape)
s0 = 0.5 * poynting.real
2019-08-30 22:03:54 -07:00
# s2 = poynting.imag
2019-09-27 20:48:03 -07:00
return s0, s1, s2
2016-05-30 22:30:45 -07:00
2019-09-27 20:48:03 -07:00
s0x, s1x, s2x = poyntings(E)
ax = axes[1, 1]
ax.plot(s0x[0].sum(axis=2).sum(axis=1), label='s0', marker='.')
ax.plot(s1x[0].sum(axis=2).sum(axis=1), label='s1', marker='.')
ax.plot(s2x[0].sum(axis=2).sum(axis=1), label='s2', marker='.')
ax.plot(E[1][:, center[1], center[2]].real.T, label='Ey', marker='x')
ax.grid(alpha=0.6)
ax.legend()
p_in = (-E * J.conj()).sum() / 2 * (dx * dx * dx)
print(f'{p_in=}')
2016-05-30 22:30:45 -07:00
q = []
for i in range(-5, 30):
2019-09-05 22:42:39 +02:00
e_ovl_rolled = numpy.roll(e_overlap, i, axis=1)
q += [numpy.abs(vec(E).conj() @ vec(e_ovl_rolled))]
fig, ax = pyplot.subplots()
ax.plot(q, marker='.')
ax.grid(alpha=0.6)
ax.set_title('Overlap with mode')
print('Average overlap with mode:', sum(q[8:32])/len(q[8:32]))
2016-05-30 22:30:45 -07:00
pyplot.show(block=True)
def module_available(name):
return importlib.util.find_spec(name) is not None
2016-05-30 22:30:45 -07:00
if __name__ == '__main__':
if module_available('opencl_fdfd'):
from opencl_fdfd import cg_solver as opencl_solver
test1(opencl_solver)
# from opencl_fdfd.csr import fdfd_cg_solver as opencl_csr_solver
# test1(opencl_csr_solver)
# elif module_available('magma_fdfd'):
# from magma_fdfd import solver as magma_solver
# test1(magma_solver)
else:
test1()