mirror of
https://github.com/edoverg/MPID.git
synced 2026-10-14 23:26:38 +00:00
implemented new filtering system based on a Filter Class. Previously, filtering was made expensive by extreme padding, now this has been fixed by choosing a more appropriate padding size. The gradient chain based on unitcells has been implemented but the results have yet to be tested using FDTD, which will be the next step. Added some utilities to visualize the effect of filter radius on given input masks and added all data concerning unit cell simulations. Still to be done is to fix materials in the MEEP simulations, so as to account for true material behavior instead of relying on constant refractive indices.
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
import meep as mp
|
||||
mp.verbosity(0)
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
from mpi4py import MPI
|
||||
|
||||
comm = MPI.COMM_WORLD
|
||||
rank = comm.Get_rank()
|
||||
size = comm.Get_size()
|
||||
|
||||
resolution = 50 # pixels/unit length
|
||||
|
||||
wvl_min = 1.5
|
||||
wvl_max = 1.6
|
||||
wvl_cen = 0.5*(wvl_min+wvl_max)
|
||||
fmin = 1/wvl_max
|
||||
fmax = 1/wvl_min
|
||||
fcen = 1/wvl_cen
|
||||
df = fmax-fmin
|
||||
nfreq = 20
|
||||
|
||||
dpml = 1.0 #PML thickness
|
||||
dsub = 1.5 + wvl_cen #substrate thickness
|
||||
dpad = dsub #padding between cell and PML
|
||||
|
||||
k_point = mp.Vector3(0,0,0) #used for PBC
|
||||
|
||||
n_si = 3.45 #silicon refractive index
|
||||
si = mp.Medium(index=n_si)
|
||||
n_sio2 = 1.45
|
||||
sio2 = mp.Medium(index=n_sio2)
|
||||
n_air = 1.0 #air refractive index
|
||||
air = mp.Medium(index=n_air)
|
||||
|
||||
P = 0.7 #unit cell pitch
|
||||
h = 0.9 #pillar height
|
||||
|
||||
def unitCell_paramsweep(D):
|
||||
print("Rank {}: Running simulation for diameter {}".format(rank, D))
|
||||
sim_x_size = dpml + dsub + dpad + dpml
|
||||
sim_z_size = P
|
||||
sim_y_size = P
|
||||
|
||||
cell_size = mp.Vector3(sim_x_size, sim_y_size, sim_z_size)
|
||||
|
||||
source_position = mp.Vector3(-wvl_cen,0,0) #source position in the middle of the substrate
|
||||
source = mp.Source(
|
||||
mp.GaussianSource(fcen, fwidth=df),
|
||||
component = mp.Ez,
|
||||
center = source_position,
|
||||
size = mp.Vector3(0, sim_y_size, sim_z_size),
|
||||
)
|
||||
|
||||
pml_layers = [mp.PML(dpml,direction=mp.X)]
|
||||
|
||||
monitor_position = mp.Vector3(h + wvl_cen,0,0)
|
||||
obs_point = monitor_position
|
||||
stop_cond = mp.stop_when_fields_decayed(50, mp.Ez, obs_point, 1e-9)
|
||||
#stop_cond = 10
|
||||
sim = mp.Simulation(
|
||||
resolution = resolution,
|
||||
cell_size = cell_size,
|
||||
boundary_layers = pml_layers,
|
||||
k_point = k_point,
|
||||
default_material = sio2,
|
||||
sources = [source],
|
||||
)
|
||||
|
||||
flux_mon = sim.add_flux(
|
||||
fcen,
|
||||
df,
|
||||
nfreq,
|
||||
mp.FluxRegion(center=monitor_position, size=mp.Vector3(0, sim_y_size, sim_z_size))
|
||||
)
|
||||
|
||||
sim.run(until_after_sources=stop_cond)
|
||||
input_flux = mp.get_fluxes(flux_mon)
|
||||
|
||||
sim.reset_meep()
|
||||
|
||||
pillar_geo = mp.Cylinder(
|
||||
material = si,
|
||||
radius = D/2,
|
||||
height = h,
|
||||
center = mp.Vector3(h/2,0,0),
|
||||
axis=mp.Vector3(1,0,0),
|
||||
)
|
||||
|
||||
substrate_geo = mp.Block(
|
||||
material = sio2,
|
||||
size = mp.Vector3(dsub+dpml, mp.inf, mp.inf),
|
||||
center = mp.Vector3(-(dsub+dpml)/2,0,0),
|
||||
)
|
||||
|
||||
geometries = [substrate_geo, pillar_geo]
|
||||
|
||||
sim = mp.Simulation(
|
||||
resolution = resolution,
|
||||
cell_size = cell_size,
|
||||
boundary_layers = pml_layers,
|
||||
geometry = geometries,
|
||||
k_point = k_point,
|
||||
sources = [source],
|
||||
)
|
||||
|
||||
mode_mon = sim.add_flux(
|
||||
fcen, df, nfreq, mp.FluxRegion(center=monitor_position, size=mp.Vector3(0, sim_y_size, sim_z_size))
|
||||
)
|
||||
|
||||
sim.run(until_after_sources=stop_cond)
|
||||
|
||||
freqs = mp.get_eigenmode_freqs(mode_mon)
|
||||
res = sim.get_eigenmode_coefficients(
|
||||
mode_mon, [1], eig_parity=mp.ODD_Z + mp.EVEN_Y
|
||||
)
|
||||
coeffs = res.alpha
|
||||
|
||||
mode_wvl = [1/freqs[nf] for nf in range(nfreq)]
|
||||
mode_tran = [abs(coeffs[0,nf,0])**2 / input_flux[nf] for nf in range(nfreq)]
|
||||
mode_phase = [np.angle(coeffs[0,nf,0]) for nf in range(nfreq)]
|
||||
|
||||
return mode_wvl, mode_tran, mode_phase
|
||||
|
||||
if rank == 0:
|
||||
diameters = np.linspace(0.1, 0.6, 24)
|
||||
else:
|
||||
diameters = None
|
||||
diameters = comm.bcast(diameters, root=0)
|
||||
local_diameters = np.array_split(diameters, size)[rank]
|
||||
local_indices = np.array_split(np.arange(len(diameters)), size)[rank]
|
||||
|
||||
local_mode_tran_arr = np.zeros((len(diameters), nfreq))
|
||||
local_mode_phase_arr = np.zeros((len(diameters), nfreq))
|
||||
|
||||
for local_i, (global_i, D) in enumerate(zip(local_indices,local_diameters)):
|
||||
mode_wvl, mode_tran, mode_phase = unitCell_paramsweep(D)
|
||||
local_mode_tran_arr[global_i,:] = mode_tran
|
||||
local_mode_phase_arr[global_i,:] = mode_phase
|
||||
|
||||
|
||||
mode_tran_arr = comm.gather(local_mode_tran_arr, root=0)
|
||||
mode_phase_arr = comm.gather(local_mode_phase_arr, root=0)
|
||||
|
||||
if rank == 0:
|
||||
final_mode_tran_arr = np.zeros((len(diameters), nfreq))
|
||||
final_mode_phase_arr = np.zeros((len(diameters), nfreq))
|
||||
num_diameters_per_rank = len(diameters) // size
|
||||
for i in range(0, size):
|
||||
for j in range(num_diameters_per_rank):
|
||||
global_index = i * num_diameters_per_rank + j
|
||||
final_mode_tran_arr[global_index, :] = mode_tran_arr[i][global_index, :]
|
||||
final_mode_phase_arr[global_index, :] = mode_phase_arr[i][global_index, :]
|
||||
|
||||
|
||||
np.save("unit_cell_param_sweep_diameters.npy", diameters)
|
||||
np.save("unit_cell_param_sweep_mode_wvl.npy", mode_wvl)
|
||||
np.save("unit_cell_param_sweep_mode_tran.npy", final_mode_tran_arr)
|
||||
np.save("unit_cell_param_sweep_mode_phase.npy", final_mode_phase_arr)
|
||||
|
||||
plt.figure()
|
||||
plt.subplot(1,2,1)
|
||||
plt.pcolormesh(
|
||||
mode_wvl,
|
||||
diameters,
|
||||
final_mode_tran_arr,
|
||||
cmap='hot_r',
|
||||
shading='gouraud',
|
||||
vmin=0,
|
||||
vmax=final_mode_tran_arr.max(),
|
||||
)
|
||||
|
||||
plt.axis([wvl_min, wvl_max, diameters[0], diameters[-1]])
|
||||
plt.xlabel("Wavelength (um)")
|
||||
plt.xticks([t for t in np.linspace(wvl_min, wvl_max, 3)])
|
||||
plt.ylabel("Pillar Diameter (um)")
|
||||
plt.title("Transmission")
|
||||
cbar=plt.colorbar()
|
||||
cbar.set_ticks([t for t in np.arange(0, 1.2, 0.2)])
|
||||
|
||||
plt.subplot(1,2,2)
|
||||
plt.pcolormesh(
|
||||
mode_wvl,
|
||||
diameters,
|
||||
final_mode_phase_arr,
|
||||
cmap='RdBu',
|
||||
shading='gouraud',
|
||||
vmin=final_mode_phase_arr.min(),
|
||||
vmax=final_mode_phase_arr.max(),
|
||||
)
|
||||
|
||||
plt.axis([wvl_min, wvl_max, diameters[0], diameters[-1]])
|
||||
plt.xlabel("Wavelength (um)")
|
||||
plt.xticks([t for t in np.linspace(wvl_min, wvl_max, 3)])
|
||||
plt.ylabel("Pillar Diameter (um)")
|
||||
plt.title("phase")
|
||||
cbar=plt.colorbar()
|
||||
cbar.set_ticks([t for t in np.arange(-3, 4, 1)])
|
||||
|
||||
|
||||
plt.subplots_adjust(wspace=0.5)
|
||||
plt.savefig("unit_cell_param_sweep.pdf")
|
||||
|
||||
Reference in New Issue
Block a user