mirror of
https://github.com/edoverg/modeconverter.git
synced 2026-10-14 23:06:39 +00:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a37ba4f0e | ||
|
|
87d8d7f15c | ||
|
|
7380eabf54 | ||
|
|
0b9dfffe89 |
@@ -73,9 +73,9 @@ rho = np.sqrt(X**2 + Y**2)
|
||||
|
||||
sampling_period = xs[1] - xs[0]
|
||||
|
||||
d0 = 535e-6 #propagation distance: source - MS1 [m]
|
||||
d0 = 353e-6 #propagation distance: source - MS1 [m]
|
||||
d_source = d0 - lda0 / 2 #propagation distance: source - MS1 used for FDTD simulations [m]
|
||||
d1 = 415e-6 #propagation distance: MS1 - MS2 [m]
|
||||
d1 = 218e-6 #propagation distance: MS1 - MS2 [m]
|
||||
d2 = d0 #propagation distance: MS2 - target [m]
|
||||
|
||||
phase_min = 0
|
||||
@@ -539,8 +539,8 @@ def forward_propagate() -> None:
|
||||
intermediate_fields[1] = np.fft.fftshift(ifft_operator.output_array.copy())
|
||||
|
||||
end_time = time.time()
|
||||
#make_2Dplot_of(intermediate_fields[0], choose_quantity="amplitude", save_name="intermediate_field_1_amplitude", plot_zoom_x=full_view_x, plot_zoom_y=full_view_y)
|
||||
#make_2Dplot_of(intermediate_fields[1], choose_quantity="amplitude", save_name="intermediate_field_2_amplitude", plot_zoom_x=full_view_x, plot_zoom_y=full_view_y)
|
||||
make_2Dplot_of(intermediate_fields[0], choose_quantity="amplitude", save_name="intermediate_field_1_amplitude", plot_zoom_x=zoom_output_fiber_radius, plot_zoom_y=zoom_output_fiber_radius)
|
||||
make_2Dplot_of(intermediate_fields[1], choose_quantity="amplitude", save_name="intermediate_field_2_amplitude", plot_zoom_x=zoom_output_fiber_radius, plot_zoom_y=zoom_output_fiber_radius)
|
||||
|
||||
print("Propagation finished in {:.6f} seconds.".format(end_time - start_time))
|
||||
|
||||
|
||||
+35
-118
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -0,0 +1,205 @@
|
||||
import meep as mp
|
||||
mp.verbosity(1)
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
resolution = 15 #[px/um]
|
||||
|
||||
#all dimensions in [um]
|
||||
lda0 = 1.55
|
||||
freq0 = 1 / lda0
|
||||
wvl_min = 1.5
|
||||
wvl_max = 1.6
|
||||
wvl_cen = lda0
|
||||
fmin = 1/wvl_max
|
||||
fmax = 1/wvl_min
|
||||
fcen = 1/wvl_cen
|
||||
df = fmax-fmin
|
||||
fwidth = df
|
||||
nfreq = 1
|
||||
|
||||
dpml = 0.5 #PML thickness
|
||||
dsub = 0.2*lda0 #substrate thickness
|
||||
#dpad = dsub #padding between cell and PML
|
||||
|
||||
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 [um]
|
||||
unit_cell_pitch = P
|
||||
h = 0.9 #pillar height [um]
|
||||
|
||||
#propgation distances
|
||||
d0 = 535 #[um]
|
||||
d1 = 415 #[um]
|
||||
d2 = d0 #[um]
|
||||
|
||||
Nx = 1025 #pixels per dimension
|
||||
Ny = Nx
|
||||
nx = (Nx - 1) // 2 #indices without axes (= #512)
|
||||
ny = (Ny - 1) // 2
|
||||
dof = 2*((nx + 1)**2) #number of degrees of freedom per metasurface
|
||||
S = Nx * Ny
|
||||
|
||||
size_x = unit_cell_pitch * Nx #actual physical size
|
||||
size_y = unit_cell_pitch * Ny
|
||||
|
||||
xs = np.arange(-Nx//2+1, Nx//2+1) * (size_x / Nx)
|
||||
ys = np.arange(-Ny//2+1, Ny//2+1) * (size_y / Ny)
|
||||
print(xs[0],xs[-1])
|
||||
X, Y = np.meshgrid(xs, ys)
|
||||
rho = np.sqrt(X**2 + Y**2)
|
||||
|
||||
|
||||
####################################################
|
||||
#LOAD PHASE MASK
|
||||
#___________________________________________________
|
||||
#load the phase mask data
|
||||
phase_mask_filename = "results_sym/optimized_phase_mask_1.npy"
|
||||
phase_mask = np.load(phase_mask_filename)
|
||||
|
||||
#sim_domain_pixel_size = #full simulation domain (full axis)
|
||||
sim_domain_size = 140 #[um]
|
||||
|
||||
max_sim_radius = 60
|
||||
|
||||
X_quadrant = X[nx:, ny:]
|
||||
xs_quadrant = xs[nx:]
|
||||
xs_sim = xs[np.abs(xs) <= sim_domain_size/2]
|
||||
xs_sim_quadrant = xs_quadrant[np.abs(xs_quadrant) <= sim_domain_size/2]
|
||||
|
||||
Y_quadrant = Y[nx:, ny:]
|
||||
ys_quadrant = ys[ny:]
|
||||
ys_sim = ys[np.abs(ys) <= sim_domain_size/2]
|
||||
ys_sim_quadrant = ys_quadrant[np.abs(ys_quadrant) <= sim_domain_size/2]
|
||||
|
||||
X_sim, Y_sim = np.meshgrid(xs_sim, ys_sim)
|
||||
|
||||
phase_mask_quadrant = phase_mask[nx:, ny:]
|
||||
|
||||
#import the input field (just before MS1)
|
||||
input_field = np.load("results_sym/input_field.npy")
|
||||
|
||||
mask = (np.abs(X) <= sim_domain_size/2) & (np.abs(Y) <= sim_domain_size/2)
|
||||
|
||||
eta_0 = 1 #due to meep's internal normalization
|
||||
Ex_field_after_MS1 = input_field * np.exp(1j*phase_mask) / np.max(np.abs(input_field))
|
||||
|
||||
Ex_field_after_MS1_sim = Ex_field_after_MS1[mask].reshape((len(xs_sim), len(ys_sim)))
|
||||
Hy_field_after_MS1_sim = Ex_field_after_MS1_sim / eta_0
|
||||
|
||||
# [markdown]
|
||||
# for the equivalence principle, if we want to use the field after MS1
|
||||
# as an actual source, we need to define proper magnetic and electric currents
|
||||
# we assume the input electric field is polarized along the x-axis
|
||||
# and the magnetic field is polarized along the y-axis.
|
||||
# Specifying both electric and magnetic fields is necessary
|
||||
# to obtain a directional source.
|
||||
|
||||
#define the source field dataset
|
||||
source_position = mp.Vector3(0,0,-0.1)
|
||||
|
||||
#the surface currents due to the equivalance principle are:
|
||||
#Js_x = -Hy_field_after_MS1
|
||||
#Ms_y = -Ex_field_after_MS1
|
||||
|
||||
sources = [
|
||||
mp.Source(#electric current
|
||||
src=mp.GaussianSource(frequency=freq0, fwidth=fwidth),
|
||||
component=mp.Ex,
|
||||
center=source_position,
|
||||
size=mp.Vector3(sim_domain_size, sim_domain_size, 0),
|
||||
amplitude=-1,
|
||||
amp_data=Hy_field_after_MS1_sim[:, :, np.newaxis]
|
||||
),
|
||||
|
||||
mp.Source(#magnetic current
|
||||
src=mp.GaussianSource(frequency=freq0, fwidth=fwidth),
|
||||
component=mp.Hy,
|
||||
center=source_position,
|
||||
size=mp.Vector3(sim_domain_size, sim_domain_size, 0),
|
||||
amplitude=-1,
|
||||
amp_data=Ex_field_after_MS1_sim[:, :, np.newaxis]
|
||||
),
|
||||
]
|
||||
|
||||
pml_layers = [mp.PML(dpml)]
|
||||
|
||||
Lx = sim_domain_size + 2*dpml
|
||||
Ly = sim_domain_size + 2*dpml
|
||||
Lz = 2*dpml + 0.4
|
||||
|
||||
cell_size = mp.Vector3(Lx, Ly, Lz)
|
||||
|
||||
sim = mp.Simulation(
|
||||
resolution=resolution,
|
||||
cell_size = cell_size,
|
||||
boundary_layers = pml_layers,
|
||||
default_material = air,
|
||||
sources = sources,
|
||||
symmetries = [mp.Mirror(0, phase=-1), mp.Mirror(1, phase=+1)]
|
||||
)
|
||||
|
||||
#far field points for projection monitor
|
||||
ff_resolution = 3
|
||||
ff_plane_size = 60 #[um]
|
||||
|
||||
xs_far = np.linspace(-ff_plane_size/2, ff_plane_size/2, ff_resolution * ff_plane_size)
|
||||
ys_far = np.linspace(-ff_plane_size/2, ff_plane_size/2, ff_resolution * ff_plane_size)
|
||||
|
||||
X_far, Y_far = np.meshgrid(xs_far, ys_far)
|
||||
|
||||
projection_distance = d1 - np.abs(source_position.z)
|
||||
|
||||
near_region_monitor = mp.Near2FarRegion(
|
||||
center=mp.Vector3(0, 0, 0),
|
||||
size=mp.Vector3(sim_domain_size, sim_domain_size, 0),
|
||||
)
|
||||
|
||||
n2f_obj = sim.add_near2far([freq0], near_region_monitor)
|
||||
|
||||
#flux_mon = sim.add_flux(
|
||||
# [fcen],
|
||||
# mp.FluxRegion(center=mp.Vector3(0,0,0), size=mp.Vector3(sim_domain_size, sim_domain_size, 0))
|
||||
# )
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
plot_xz_plane = mp.Volume(center=mp.Vector3(0,0,0), size=mp.Vector3(Lx, 0, Lz))
|
||||
sim.plot2D(ax=ax,output_plane=plot_xz_plane)
|
||||
ax.set_aspect('auto')
|
||||
|
||||
obs_point = mp.Vector3(0,0,0)
|
||||
stop_cond = mp.stop_when_fields_decayed(50, mp.Ez, obs_point, 1e-9)
|
||||
|
||||
sim.run(until_after_sources=stop_cond)
|
||||
|
||||
far_plane = mp.Volume(
|
||||
center=mp.Vector3(0, 0, projection_distance),
|
||||
size=mp.Vector3(ff_plane_size, ff_plane_size, 0)
|
||||
)
|
||||
|
||||
ff_data = sim.get_farfields(n2f_obj, ff_resolution, where=far_plane)
|
||||
|
||||
ff_Ex = ff_data['Ex']
|
||||
np.save("ff_Ex.npy", ff_Ex)
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
im = ax.pcolormesh(X_far, Y_far, np.abs(ff_Ex), cmap='viridis', shading='auto')
|
||||
ax.set_xlabel('X [um]')
|
||||
ax.set_ylabel('Y [um]')
|
||||
fig.colorbar(im, ax=ax)
|
||||
fig.savefig("magnitude_field_before_MS2.pdf")
|
||||
|
||||
#make a line plot that is a slice along the y=0 axis
|
||||
fig, az = plt.subplots()
|
||||
im = az.plot(xs_far, np.abs(ff_Ex[ff_resolution * ff_plane_size//2, :]))
|
||||
az.set_xlabel('X [um]')
|
||||
az.set_ylabel('Magnitude of E-field')
|
||||
fig.savefig("magnitude_field_before_MS2_slice.pdf")
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -2,15 +2,16 @@ import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
#import the parameter sweep arrays for the central wavelength
|
||||
diameters = np.load("unit_cell_center_1550_h900nm_res50_wvl_diameters.npy")
|
||||
mode_wvl = np.load("unit_cell_center_1550_h900nm_res50_wvl_mode_wvl.npy")
|
||||
mode_tran_arr = np.load("unit_cell_center_1550_h900nm_res50_wvl_mode_tran.npy")
|
||||
diameters = np.load("unit_cell/unit_cell_center_1550_h900nm_res50_wvl_diameters.npy")
|
||||
print(diameters)
|
||||
mode_wvl = np.load("unit_cell/unit_cell_center_1550_h900nm_res50_wvl_mode_wvl.npy")
|
||||
mode_tran_arr = np.load("unit_cell/unit_cell_center_1550_h900nm_res50_wvl_mode_tran.npy")
|
||||
print(mode_tran_arr)
|
||||
mode_phase_arr = np.load("unit_cell_center_1550_h900nm_res50_wvl_mode_phase.npy")
|
||||
mode_phase_arr = np.load("unit_cell/unit_cell_center_1550_h900nm_res50_wvl_mode_phase.npy")
|
||||
print(mode_wvl)
|
||||
unwrap_mode_phase_arr = np.abs(np.unwrap(mode_phase_arr - mode_phase_arr[0], period=2*np.pi))
|
||||
#import the reference value array
|
||||
ref_results = np.loadtxt("results_S21_p700nm_h900nm.txt", skiprows=5,dtype=complex)
|
||||
ref_results = np.loadtxt("unit_cell/results_S21_p700nm_h900nm.txt", skiprows=5,dtype=complex)
|
||||
R_ref = np.real(ref_results[:,1])
|
||||
S21_ref = ref_results[:,3]
|
||||
S21_ref_mag = np.abs(S21_ref)
|
||||
@@ -22,7 +23,7 @@ plt.figure()
|
||||
plt.subplot(1,2,1)
|
||||
plt.plot(1e3*diameters/2,mode_tran_arr, '^r-.', label='FDTD')
|
||||
plt.plot(R_ref,S21_ref_mag, '*k--',label='FEM')
|
||||
plt.xlabel("Pillar Radius (um)")
|
||||
plt.xlabel("Pillar Radius (nm)")
|
||||
plt.xticks([t for t in np.linspace(1e3*diameters[0]/2, 1e3*diameters[-1]/2, 5)])
|
||||
plt.gca().set_xticklabels([f"{t:.0f}" for t in np.linspace(1e3*diameters[0]/2, 1e3*diameters[-1]/2, 5)])
|
||||
plt.ylabel("Transmission")
|
||||
@@ -31,11 +32,11 @@ plt.legend()
|
||||
plt.subplot(1,2,2)
|
||||
plt.plot(1e3*diameters/2,unwrap_mode_phase_arr, '^r-.', label='FDTD')
|
||||
plt.plot(R_ref,S21_ref_phase, '*k--', label='FEM')
|
||||
plt.xlabel("Pillar Radius (um)")
|
||||
plt.xlabel("Pillar Radius (nm)")
|
||||
plt.xticks([t for t in np.linspace(1e3*diameters[0]/2, 1e3*diameters[-1]/2, 5)])
|
||||
plt.gca().set_xticklabels([f"{t:.0f}" for t in np.linspace(1e3*diameters[0]/2, 1e3*diameters[-1]/2, 5)])
|
||||
plt.ylabel("Phase (rad)")
|
||||
plt.legend()
|
||||
|
||||
plt.subplots_adjust(wspace=0.5)
|
||||
plt.savefig("unit_cell_param_sweep_lineplot.pdf")
|
||||
plt.savefig("unit_cell/unit_cell_param_sweep_lineplot.pdf")
|
||||
Reference in New Issue
Block a user