mirror of
https://github.com/edoverg/modeconverter.git
synced 2026-10-14 23:06:39 +00:00
repo cleanup
This commit is contained in:
+191
-159
@@ -12,13 +12,17 @@ import nlopt
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
#set the global font size for all plots
|
||||
plt.rcParams.update({'font.size': 14})
|
||||
|
||||
from scipy.special import jv, kv
|
||||
|
||||
##############################
|
||||
#physics and simulation domain
|
||||
wavelength = 1.55e-6
|
||||
k0 = 2 * np.pi / wavelength
|
||||
|
||||
opt_max_eval = 200
|
||||
opt_max_eval = 250
|
||||
|
||||
unit_cell_pitch = 400e-9 #equivalent to spatial sampling
|
||||
|
||||
@@ -29,7 +33,29 @@ S = Nx * Ny
|
||||
size_x = unit_cell_pitch * Nx #actual physical size
|
||||
size_y = unit_cell_pitch * Ny
|
||||
|
||||
######################
|
||||
xs = np.linspace(-size_x/2, size_x/2 - size_x / Nx, Nx)
|
||||
ys = np.linspace(-size_y/2, size_y/2 - size_y / Ny, Ny)
|
||||
|
||||
X, Y = np.meshgrid(xs, ys)
|
||||
rho = np.sqrt(X**2 + Y**2)
|
||||
|
||||
sampling_period = xs[1] - xs[0]
|
||||
|
||||
d0 = 345e-6 #propagation distance: source - MS1
|
||||
d1 = 500e-6 #propagation distance: MS1 - MS2
|
||||
d2 = 500e-6 #propagation distance: MS2 - target
|
||||
d = [d1, d2] #d = [d1,d2] d1:distance MS1-MS2, d2: distance MS2-target
|
||||
|
||||
phase_min = 0
|
||||
phase_max = 2 * np.pi
|
||||
##############################
|
||||
|
||||
##############################
|
||||
#Source
|
||||
beam_waist = 9e-6
|
||||
##############################
|
||||
|
||||
##############################
|
||||
#plan pyfftw objects for forward and inverse FFTs
|
||||
fft_input_array = pyfftw.empty_aligned((Nx, Ny), dtype='complex128', n=16)
|
||||
fft_output_array = pyfftw.empty_aligned((Nx, Ny), dtype='complex128', n=16)
|
||||
@@ -38,22 +64,37 @@ ifft_output_array = pyfftw.empty_aligned((Nx, Ny), dtype='complex128', n=16)
|
||||
|
||||
fft_operator = pyfftw.FFTW(fft_input_array, fft_output_array, axes=(0,1), direction='FFTW_FORWARD', threads=n_cpu, flags=('FFTW_MEASURE','FFTW_DESTROY_INPUT',))
|
||||
ifft_operator = pyfftw.FFTW(ifft_input_array, ifft_output_array, axes=(0,1), direction='FFTW_BACKWARD', threads=n_cpu, flags=('FFTW_MEASURE','FFTW_DESTROY_INPUT',))
|
||||
######################
|
||||
##############################
|
||||
|
||||
phase_min = 0
|
||||
phase_max = 2 * np.pi
|
||||
##############################
|
||||
#setting up spatial frequencies
|
||||
ks = 2 * np.pi / sampling_period
|
||||
kappas = np.arange(-Nx//2, Nx//2) * ks / Nx
|
||||
KX, KY = np.meshgrid(kappas, kappas)
|
||||
K_parallel = np.sqrt(KX**2 + KY**2)
|
||||
nu_parallel = K_parallel / (2 * np.pi)
|
||||
|
||||
xs = np.linspace(-size_x/2, size_x/2, Nx)
|
||||
ys = np.linspace(-size_y/2, size_y/2, Ny)
|
||||
phase_factor_0 = k0 * d0 * np.sqrt(1 - (wavelength * nu_parallel) ** 2 + 0*1j)
|
||||
P_0 = np.exp(1j * phase_factor_0)
|
||||
P_0_nat = np.fft.ifftshift(P_0)
|
||||
phase_factor_1 = k0 * d1 * np.sqrt(1 - (wavelength * nu_parallel) ** 2 + 0*1j)
|
||||
P_1 = np.exp(1j * phase_factor_1)
|
||||
P_1_nat = np.fft.ifftshift(P_1)
|
||||
phase_factor_2 = k0 * d2 * np.sqrt(1 - (wavelength * nu_parallel) ** 2 + 0*1j)
|
||||
P_2 = np.exp(1j * phase_factor_2)
|
||||
P_2_nat = np.fft.ifftshift(P_2)
|
||||
|
||||
X, Y = np.meshgrid(xs, ys)
|
||||
rho = np.sqrt(X**2 + Y**2)
|
||||
P_1_dagger = P_1.T.conj()
|
||||
P_2_dagger = P_2.T.conj()
|
||||
P_1_dagger_nat = np.fft.ifftshift(P_1).T.conj()
|
||||
P_2_dagger_nat = np.fft.ifftshift(P_2).T.conj()
|
||||
##############################
|
||||
|
||||
sampling_period = xs[1] - xs[0]
|
||||
|
||||
d1 = 1000e-6 #propagation distance
|
||||
d2 = 1000e-6 #propagation distance
|
||||
d = [d1, d2] #d = [d1,d2] d1:distance MS1-MS2, d2: distance MS2-target
|
||||
##############################
|
||||
#Plot zoom parameters [um]
|
||||
zoom_x = 60*3
|
||||
zoom_y = 60*3
|
||||
##############################
|
||||
|
||||
def phase_given_w(w):
|
||||
'''Returns the phase shift given the design parameters w.
|
||||
@@ -131,22 +172,98 @@ def get_fiber_mode_pattern():
|
||||
|
||||
return E_field
|
||||
|
||||
def get_source_field(beam_waist):
|
||||
'''Returns a normalized Gaussian source field for a given beam waist. Normalization consists in scaling
|
||||
the field such that its integrated intensity is 1.'''
|
||||
gaussian_field = np.exp(-rho**2 / (beam_waist)**2) #Gaussian input field, flattened
|
||||
gaussian_field_normalized = (gaussian_field / np.sqrt(np.sum(np.abs(gaussian_field)**2))) #normalize the input field to have power = 1
|
||||
return gaussian_field_normalized
|
||||
|
||||
def propagate_source():
|
||||
'''Returns the propagated source field just before metasurface 1 (MS1). This involves propagating the
|
||||
source for a distance d0: from its plane of definition up to MS1.'''
|
||||
fft_input_array[:,:] = source_field_2d
|
||||
fft_operator()
|
||||
ifft_input_array[:,:] = fft_operator.output_array * P_0_nat
|
||||
ifft_operator()
|
||||
propagated_source_field = ifft_operator.output_array.flatten()
|
||||
return propagated_source_field
|
||||
|
||||
def make_1Dplot_of(x_axis,y_axis,plot_zoom_x=zoom_x,save_name="plot_1D",) -> None:
|
||||
'''Makes a 1D plot of the given data and saves it to a PDF file.
|
||||
Args:
|
||||
x_axis: list of x-axis data (list of 1D arrays)
|
||||
y_axis: list of y-axis data (list of 1D arrays)
|
||||
plot_zoom_x: zoom level for the x-axis (in micrometers)
|
||||
save_name: name of the file to save the plot (without extension)
|
||||
Returns:
|
||||
None
|
||||
'''
|
||||
if len(x_axis) != len(y_axis):
|
||||
raise ValueError("Lists x_axis and y_axis must have the same length.")
|
||||
plt.figure()
|
||||
for i in range(len(x_axis)):
|
||||
plt.plot(x_axis[i], y_axis[i])
|
||||
plt.xlabel("x [um]")
|
||||
plt.tight_layout()
|
||||
plt.savefig("results/" + save_name + ".pdf")
|
||||
plt.xlim(-plot_zoom_x, plot_zoom_x)
|
||||
plt.close()
|
||||
|
||||
def make_2Dplot_of(given_field,choose_quantity="amplitude",save_name="plot",plot_zoom_x=zoom_x,plot_zoom_y=zoom_y) -> None:
|
||||
'''Makes a plot of the given 2D field in a zoomed region.
|
||||
Saves the plot with the chosen filename to a PDF file.
|
||||
Args:
|
||||
given_field: the 2D field to be plotted (flattened)
|
||||
choose_quantity: either "amplitude" or "phase" to select quantity to plot
|
||||
save_name: name of the file to save the plot (without extension)
|
||||
plot_zoom_x: zoom level for the x-axis (in micrometers)
|
||||
plot_zoom_y: zoom level for the y-axis (in micrometers)
|
||||
Returns:
|
||||
None'''
|
||||
|
||||
given_field_2d = given_field.reshape((Nx, Ny)) #assure the field is 2D before plotting
|
||||
plt.figure()
|
||||
if choose_quantity == "amplitude":
|
||||
plt.imshow(np.abs(given_field_2d), extent=(-size_x*1e6/2, size_x*1e6/2, -size_y*1e6/2, size_y*1e6/2))
|
||||
elif choose_quantity == "phase":
|
||||
plt.imshow((np.angle(given_field_2d)+2*np.pi)%(2*np.pi), extent=(-size_x*1e6/2, size_x*1e6/2, -size_y*1e6/2, size_y*1e6/2), cmap='hsv', vmin=0, vmax=2*np.pi)
|
||||
elif choose_quantity == "phase_mask":
|
||||
plt.imshow((given_field_2d+2*np.pi)%(2*np.pi), extent=(-size_x*1e6/2, size_x*1e6/2, -size_y*1e6/2, size_y*1e6/2), cmap='hsv', vmin=0, vmax=2*np.pi)
|
||||
else:
|
||||
raise ValueError("choose_quantity must be either 'amplitude' or 'phase'")
|
||||
|
||||
plt.xlim(-plot_zoom_x, plot_zoom_x)
|
||||
plt.ylim(-plot_zoom_y, plot_zoom_y)
|
||||
plt.xlabel("x [um]")
|
||||
plt.ylabel("y [um]")
|
||||
plt.colorbar()
|
||||
plt.tight_layout()
|
||||
plt.savefig("results/" + save_name + ".pdf")
|
||||
plt.close()
|
||||
|
||||
###########################
|
||||
#initialize input field
|
||||
beam_waist = 80e-6
|
||||
gaussian_field = np.exp(-rho**2 / (beam_waist)**2) #Gaussian input field, flattened
|
||||
input_field_2d = (gaussian_field / np.sqrt(np.sum(np.abs(gaussian_field)**2))) #normalize the input field to have power = 1
|
||||
input_field = input_field_2d.flatten() #normalize the input field to have power = 1
|
||||
#initialize source field
|
||||
source_field = get_source_field(beam_waist)
|
||||
source_field_2d = source_field.reshape((Nx, Ny)) #reshape to 2D for plotting
|
||||
#source field integrated intensity
|
||||
source_power = np.sum(np.abs(source_field)**2)
|
||||
print("Source field integrated intensity: %.4e" % source_power)
|
||||
#make a plot and save the source field
|
||||
make_2Dplot_of(source_field_2d, choose_quantity="amplitude", save_name="source_field_amplitude", plot_zoom_x=zoom_x, plot_zoom_y=zoom_y)
|
||||
make_2Dplot_of(source_field_2d, choose_quantity="phase", save_name="source_field_phase", plot_zoom_x=zoom_x, plot_zoom_y=zoom_y)
|
||||
###########################
|
||||
|
||||
###########################
|
||||
#initialize input field (propagated source field)
|
||||
input_field = propagate_source()
|
||||
input_field_2d = input_field.reshape((Nx, Ny)) #reshape to 2D for plotting
|
||||
#input field integrated intensity
|
||||
input_field_intensity = np.sum(np.abs(input_field)**2)
|
||||
print("Input field integrated intensity: %.4e" % input_field_intensity)
|
||||
#make a plot and save the input field
|
||||
plt.figure()
|
||||
plt.imshow(np.abs(input_field_2d), extent=(-size_x*1e6/2, size_x*1e6/2, -size_y*1e6/2, size_y*1e6/2))
|
||||
plt.title("Input Field Amplitude")
|
||||
plt.xlabel("x (um)")
|
||||
plt.ylabel("y (um)")
|
||||
plt.colorbar()
|
||||
plt.tight_layout()
|
||||
plt.savefig("results/input_field_amplitude.pdf")
|
||||
plt.close()
|
||||
make_2Dplot_of(input_field_2d, choose_quantity="amplitude", save_name="input_field_amplitude", plot_zoom_x=zoom_x*2, plot_zoom_y=zoom_y*2)
|
||||
make_2Dplot_of(input_field_2d, choose_quantity="phase", save_name="input_field_phase", plot_zoom_x=zoom_x*2, plot_zoom_y=zoom_y*2)
|
||||
###########################
|
||||
|
||||
###########################
|
||||
@@ -154,6 +271,10 @@ plt.close()
|
||||
fiber_mode_pattern = get_fiber_mode_pattern()
|
||||
target_Efield_2d = fiber_mode_pattern / np.sqrt(np.sum(np.abs(fiber_mode_pattern)**2))
|
||||
target_Efield = target_Efield_2d.flatten() #normalized target field (intensity = 1)
|
||||
|
||||
# Plot: Target field
|
||||
make_2Dplot_of(target_Efield_2d, choose_quantity="amplitude", save_name="target_field_amplitude", plot_zoom_x=zoom_x, plot_zoom_y=zoom_y)
|
||||
make_2Dplot_of(target_Efield_2d, choose_quantity="phase", save_name="target_field_phase", plot_zoom_x=zoom_x, plot_zoom_y=zoom_y)
|
||||
###########################
|
||||
|
||||
###########################
|
||||
@@ -177,41 +298,32 @@ mask_upper_bounds = np.concatenate((mask_upper_bounds, mask_upper_bounds),axis=0
|
||||
mask_lower_bounds = np.zeros_like(mask_upper_bounds)
|
||||
###########################
|
||||
|
||||
###########################
|
||||
#setting up spatial frequencies
|
||||
ks = 2 * np.pi / sampling_period
|
||||
kappas = np.arange(-Nx//2, Nx//2) * ks / Nx
|
||||
KX, KY = np.meshgrid(kappas, kappas)
|
||||
K_parallel = np.sqrt(KX**2 + KY**2)
|
||||
nu_parallel = K_parallel / (2 * np.pi)
|
||||
|
||||
phase_factor = k0 * d1 * np.sqrt(1 - (wavelength * nu_parallel) ** 2 + 0*1j)
|
||||
P_1 = np.exp(1j * phase_factor)
|
||||
P_1_nat = np.fft.ifftshift(P_1)
|
||||
phase_factor_2 = k0 * d2 * np.sqrt(1 - (wavelength * nu_parallel) ** 2 + 0*1j)
|
||||
P_2 = np.exp(1j * phase_factor_2)
|
||||
P_2_nat = np.fft.ifftshift(P_2)
|
||||
|
||||
P_1_dagger = P_1.T.conj()
|
||||
P_2_dagger = P_2.T.conj()
|
||||
P_1_dagger_nat = np.fft.ifftshift(P_1).T.conj()
|
||||
P_2_dagger_nat = np.fft.ifftshift(P_2).T.conj()
|
||||
###########################
|
||||
|
||||
intermediate_fields = [None, None]
|
||||
def forward_propagate() -> None:
|
||||
'''Propagates the input field through the system with the given phase mask.
|
||||
Args:
|
||||
phase_mask: the concatenated phase mask of the system. Masks are flattened and in order. Any mask has always S elements.
|
||||
'''Propagates the input field through the system. Stores results in-place within the intermediate_fields list.
|
||||
Returns:
|
||||
The output field after propagation (flattened) and the propagation matrices P used in the forward propagation.
|
||||
None
|
||||
'''
|
||||
print("Starting propagating...")
|
||||
start_time = time.time()
|
||||
|
||||
fft_input_array[:,:] = (input_field * np.exp(1j * phase_mask[:S])).reshape((Nx, Ny))
|
||||
fft_operator()
|
||||
print("BEFORE")
|
||||
fft_power = np.sum(np.abs(fft_operator.output_array)**2)/S
|
||||
non_propagating_mask = np.where((wavelength * nu_parallel)**2 > 1, 0, 1)
|
||||
non_propagating_mask = np.fft.ifftshift(non_propagating_mask)
|
||||
propagating_power = np.sum(np.abs(fft_operator.output_array * non_propagating_mask)**2)/S
|
||||
print("FFT power: %.4e, Propagating power: %.4e, Non-propagating power: %.4e" % (fft_power, propagating_power, fft_power - propagating_power))
|
||||
ifft_input_array[:,:] = fft_operator.output_array * P_1_nat #element wise product
|
||||
print("AFTER")
|
||||
|
||||
fft_power = np.sum(np.abs(ifft_operator.input_array)**2)/S
|
||||
non_propagating_mask = np.where((wavelength * nu_parallel)**2 > 1, 0, 1)
|
||||
non_propagating_mask = np.fft.ifftshift(non_propagating_mask)
|
||||
propagating_power = np.sum(np.abs(ifft_operator.input_array * non_propagating_mask)**2)/S
|
||||
print("FFT power: %.4e, Propagating power: %.4e, Non-propagating power: %.4e" % (fft_power, propagating_power, fft_power - propagating_power))
|
||||
|
||||
ifft_operator()
|
||||
intermediate_fields[0] = ifft_operator.output_array.copy()
|
||||
print("Field intensity after first phase mask and propagation: %.4e" % np.sum(np.abs(intermediate_fields[0])**2))
|
||||
@@ -223,17 +335,18 @@ def forward_propagate() -> None:
|
||||
intermediate_fields[1] = ifft_operator.output_array.copy()
|
||||
|
||||
end_time = time.time()
|
||||
make_2Dplot_of(intermediate_fields[0], choose_quantity="amplitude", save_name="intermediate_field_after_first_phase_mask_amplitude", plot_zoom_x=zoom_x, plot_zoom_y=zoom_y)
|
||||
make_2Dplot_of(intermediate_fields[0], choose_quantity="phase", save_name="intermediate_field_after_first_phase_mask_phase", plot_zoom_x=zoom_x, plot_zoom_y=zoom_y)
|
||||
make_2Dplot_of(intermediate_fields[1], choose_quantity="amplitude", save_name="intermediate_field_after_second_phase_mask_amplitude", plot_zoom_x=zoom_x, plot_zoom_y=zoom_y)
|
||||
make_2Dplot_of(intermediate_fields[1], choose_quantity="phase", save_name="intermediate_field_after_second_phase_mask_phase", plot_zoom_x=zoom_x, plot_zoom_y=zoom_y)
|
||||
|
||||
print("Propagation finished in {:.6f} seconds.".format(end_time - start_time))
|
||||
|
||||
|
||||
def adjoint_propagate():
|
||||
'''Backpropagates the output field using the adjoint of the propagation matrix P.
|
||||
Args:
|
||||
output_field: the output field to be backpropagated (flattened)
|
||||
P: the propagation matrix used in the forward propagation
|
||||
phase_mask: the phase mask used in the forward propagation (flattened)
|
||||
Returns:
|
||||
The backpropagated field (flattened)
|
||||
the gradient of the cost function with respect to the phase mask (flattened)
|
||||
'''
|
||||
print("Computing adjoint...")
|
||||
start_time = time.time()
|
||||
@@ -261,7 +374,6 @@ def adjoint_propagate():
|
||||
return np.concatenate((grad_C_phi_1, grad_C_phi_2))
|
||||
|
||||
def _compute_cost():
|
||||
|
||||
forward_propagate()
|
||||
|
||||
output_field = intermediate_fields[-1].flatten()
|
||||
@@ -307,8 +419,7 @@ def cost_fun(x, grad):
|
||||
if __name__ == "__main__":
|
||||
#initialize nlopt solver
|
||||
solver = nlopt.opt(nlopt.LD_CCSAQ, 2*S)
|
||||
print("Type of bounds",type(mask_lower_bounds.flatten()), type(mask_upper_bounds.flatten()))
|
||||
print("Size of bounds",mask_lower_bounds.flatten().shape, mask_upper_bounds.flatten().shape)
|
||||
|
||||
solver.set_lower_bounds(mask_lower_bounds.flatten())
|
||||
solver.set_upper_bounds(mask_upper_bounds.flatten())
|
||||
solver.set_max_objective(cost_fun)
|
||||
@@ -338,106 +449,34 @@ if __name__ == "__main__":
|
||||
|
||||
# Reshape fields to 2D for visualization
|
||||
output_field_2d = output_field.reshape((Nx, Ny))
|
||||
target_field_2d = target_Efield.reshape((Nx, Ny))
|
||||
phase_mask_1 = phase_given_w(w_norm[:S]).reshape((Nx, Ny))
|
||||
phase_mask_2 = phase_given_w(w_norm[S:]).reshape((Nx, Ny))
|
||||
|
||||
a = 6e-6
|
||||
d = 10 * a * 1e6
|
||||
# Plot 1: Output field amplitude
|
||||
fig, ax = plt.subplots(figsize=(10, 8))
|
||||
im = ax.imshow(np.abs(output_field_2d),extent=(-size_x*1e6/2, size_x*1e6/2, -size_y*1e6/2, size_y*1e6/2), origin='lower', cmap='viridis')
|
||||
ax.set_title('Output Field Amplitude')
|
||||
ax.set_xlabel('x')
|
||||
ax.set_ylabel('y')
|
||||
#ax.set_xlim(-d, d)
|
||||
#ax.set_ylim(-d, d)
|
||||
ax.set_aspect('equal')
|
||||
plt.colorbar(im, ax=ax)
|
||||
plt.tight_layout()
|
||||
plt.savefig("results/output_field_amplitude.pdf")
|
||||
plt.close()
|
||||
|
||||
# Plot: Output field amplitude and phase
|
||||
make_2Dplot_of(output_field_2d, choose_quantity="amplitude", save_name="output_field_amplitude", plot_zoom_x=d, plot_zoom_y=d)
|
||||
make_2Dplot_of(output_field_2d, choose_quantity="phase", save_name="output_field_phase", plot_zoom_x=d, plot_zoom_y=d)
|
||||
|
||||
# Plot 2: Output field phase
|
||||
fig, ax = plt.subplots(figsize=(10, 8))
|
||||
im = ax.imshow((np.angle(output_field_2d)+2*np.pi)%(2*np.pi),extent=(-size_x*1e6/2, size_x*1e6/2, -size_y*1e6/2, size_y*1e6/2), origin='lower', cmap='hsv')
|
||||
ax.set_title('Output Field Phase')
|
||||
ax.set_xlabel('x')
|
||||
ax.set_ylabel('y')
|
||||
ax.set_xlim(-d, d)
|
||||
ax.set_ylim(-d, d)
|
||||
ax.set_aspect('equal')
|
||||
plt.colorbar(im, ax=ax)
|
||||
plt.tight_layout()
|
||||
plt.savefig("results/output_field_phase.pdf")
|
||||
plt.close()
|
||||
phase_mask_zoom = 150
|
||||
# Plot: Phase mask 1
|
||||
make_2Dplot_of(phase_mask_1, choose_quantity="phase_mask", save_name="phase_mask_1", plot_zoom_x=phase_mask_zoom, plot_zoom_y=phase_mask_zoom)
|
||||
# Plot: Phase mask 2
|
||||
make_2Dplot_of(phase_mask_2, choose_quantity="phase_mask", save_name="phase_mask_2", plot_zoom_x=phase_mask_zoom, plot_zoom_y=phase_mask_zoom)
|
||||
|
||||
# Plot 3: Target field amplitude
|
||||
fig, ax = plt.subplots(figsize=(10, 8))
|
||||
im = ax.imshow(np.abs(target_field_2d),extent=(-size_x*1e6/2, size_x*1e6/2, -size_y*1e6/2, size_y*1e6/2), origin='lower', cmap='viridis')
|
||||
ax.set_title('Target Field Amplitude')
|
||||
ax.set_xlabel('x')
|
||||
ax.set_ylabel('y')
|
||||
ax.set_xlim(-d, d)
|
||||
ax.set_ylim(-d, d)
|
||||
ax.set_aspect('equal')
|
||||
plt.colorbar(im, ax=ax)
|
||||
plt.tight_layout()
|
||||
plt.savefig("results/target_field_amplitude.pdf")
|
||||
plt.close()
|
||||
|
||||
# Plot 4: Target field phase
|
||||
fig, ax = plt.subplots(figsize=(10, 8))
|
||||
im = ax.imshow((np.angle(target_field_2d)+2*np.pi)%(2*np.pi),extent=(-size_x*1e6/2, size_x*1e6/2, -size_y*1e6/2, size_y*1e6/2), origin='lower', cmap='hsv', vmin=0, vmax=2*np.pi)
|
||||
ax.set_title('Target Field Phase')
|
||||
ax.set_xlabel('x')
|
||||
ax.set_ylabel('y')
|
||||
ax.set_xlim(-d, d)
|
||||
ax.set_ylim(-d, d)
|
||||
ax.set_aspect('equal')
|
||||
plt.colorbar(im, ax=ax)
|
||||
plt.tight_layout()
|
||||
plt.savefig("results/target_field_phase.pdf")
|
||||
plt.close()
|
||||
|
||||
# Plot 5: Phase mask 1
|
||||
fig, ax = plt.subplots(figsize=(10, 8))
|
||||
im = ax.imshow((phase_mask_1+2*np.pi)%(2*np.pi),extent=(-size_x*1e6/2, size_x*1e6/2, -size_y*1e6/2, size_y*1e6/2), origin='lower', cmap='hsv', vmin=0, vmax=2*np.pi)
|
||||
ax.set_title('Phase Mask 1')
|
||||
ax.set_xlabel('x')
|
||||
ax.set_ylabel('y')
|
||||
ax.set_aspect('equal')
|
||||
plt.colorbar(im, ax=ax)
|
||||
plt.tight_layout()
|
||||
plt.savefig("results/phase_mask_1.pdf")
|
||||
plt.show()
|
||||
#plt.close()
|
||||
|
||||
# Plot 6: Phase mask 2
|
||||
fig, ax = plt.subplots(figsize=(10, 8))
|
||||
im = ax.imshow((phase_mask_2+2*np.pi)%(2*np.pi),extent=(-size_x*1e6/2, size_x*1e6/2, -size_y*1e6/2, size_y*1e6/2), origin='lower', cmap='hsv', vmin=0, vmax=2*np.pi)
|
||||
ax.set_title('Phase Mask 2')
|
||||
ax.set_xlabel('x')
|
||||
ax.set_ylabel('y')
|
||||
ax.set_aspect('equal')
|
||||
plt.colorbar(im, ax=ax)
|
||||
plt.tight_layout()
|
||||
plt.savefig("results/phase_mask_2.pdf")
|
||||
plt.show()
|
||||
#plt.close()
|
||||
|
||||
# Plot 7: Cuts along y=0 axis - Amplitude comparison
|
||||
# Plot: Cuts along y=0 axis - Amplitude comparison
|
||||
y_center_idx = Ny // 2
|
||||
output_amplitude_cut = np.abs(output_field_2d[y_center_idx, :])
|
||||
target_amplitude_cut = np.abs(target_field_2d[y_center_idx, :])
|
||||
output_amplitude_cut = np.abs(output_field_2d[y_center_idx, :]) / np.max(np.abs(output_field_2d[y_center_idx, :]))
|
||||
target_amplitude_cut = np.abs(target_Efield_2d[y_center_idx, :]) / np.max(np.abs(target_Efield_2d[y_center_idx, :]))
|
||||
|
||||
fig, ax = plt.subplots(figsize=(12, 6))
|
||||
ax.plot(xs*1e6, output_amplitude_cut, label='Output Field', linewidth=2)
|
||||
ax.plot(xs*1e6, target_amplitude_cut, label='Target Field', linewidth=2)
|
||||
ax.set_xlabel('x (m)')
|
||||
ax.set_xlabel('x [um]')
|
||||
ax.set_xlim(-d,d)
|
||||
ax.set_ylabel('Amplitude')
|
||||
ax.set_title('Field Amplitude along y=0 axis')
|
||||
ax.set_title('Norm. Field Amplitude along y=0 axis')
|
||||
ax.legend()
|
||||
ax.grid(True, alpha=0.3)
|
||||
plt.tight_layout()
|
||||
@@ -446,12 +485,13 @@ if __name__ == "__main__":
|
||||
|
||||
# Plot 8: Cuts along y=0 axis - Phase comparison
|
||||
output_phase_cut = (np.angle(output_field_2d[y_center_idx, :]) + 2*np.pi) % (2*np.pi)
|
||||
target_phase_cut = (np.angle(target_field_2d[y_center_idx, :]) + 2*np.pi) % (2*np.pi)
|
||||
|
||||
target_phase_cut = (np.angle(target_Efield_2d[y_center_idx, :]) + 2*np.pi) % (2*np.pi)
|
||||
x_ax = xs*1e6
|
||||
make_1Dplot_of([x_ax, x_ax], [output_phase_cut, target_phase_cut], save_name="phase_cut_comparison")
|
||||
fig, ax = plt.subplots(figsize=(12, 6))
|
||||
ax.plot(xs*1e6, output_phase_cut, label='Output Field', linewidth=2)
|
||||
ax.plot(xs*1e6, target_phase_cut, label='Target Field', linewidth=2)
|
||||
ax.set_xlabel('x (m)')
|
||||
ax.set_xlabel('x [um]')
|
||||
ax.set_ylabel('Phase (rad)')
|
||||
ax.set_xlim(-d,d)
|
||||
ax.set_title('Field Phase along y=0 axis')
|
||||
@@ -462,15 +502,7 @@ if __name__ == "__main__":
|
||||
plt.close()
|
||||
|
||||
# Plot 9: Intermediate field before second phase mask
|
||||
fig, ax = plt.subplots(figsize=(10, 8))
|
||||
im = ax.imshow(np.abs(intermediate_fields[0]),extent=(-size_x*1e6/2, size_x*1e6/2, -size_y*1e6/2, size_y*1e6/2), origin='lower', cmap='viridis')
|
||||
ax.set_title('Intermediate Field Amplitude (Before Second Phase Mask)')
|
||||
ax.set_xlabel('x')
|
||||
ax.set_ylabel('y')
|
||||
ax.set_aspect('equal')
|
||||
plt.colorbar(im, ax=ax)
|
||||
plt.tight_layout()
|
||||
plt.savefig("results/intermediate_field_amplitude.pdf")
|
||||
make_2Dplot_of(intermediate_fields[0], choose_quantity="amplitude", save_name="intermediate_field_amplitude", plot_zoom_x=d, plot_zoom_y=d)
|
||||
|
||||
#save the phase masks for later use
|
||||
np.savetxt("results/optimized_phase_mask_1.txt", phase_mask_1)
|
||||
|
||||
Reference in New Issue
Block a user