mirror of
https://github.com/edoverg/modeconverter.git
synced 2026-10-14 23:06:39 +00:00
220 lines
6.5 KiB
Python
220 lines
6.5 KiB
Python
#this file serves to simulate the optimized design parameters
|
|
#it imports data from the optimization process and runs a meep simulation to verify the results
|
|
import faulthandler
|
|
faulthandler.enable()
|
|
from typing import List, NamedTuple, Tuple
|
|
from autograd import numpy as npa, tensor_jacobian_product, grad
|
|
import matplotlib.pyplot as plt
|
|
import matplotlib.animation as animation
|
|
import meep as mp
|
|
import meep.adjoint as mpa
|
|
import nlopt
|
|
import numpy as np
|
|
import os
|
|
import xarray as xr
|
|
from PIL import Image
|
|
import pickle
|
|
|
|
if not os.path.exists("sim_opt_design_results"):
|
|
os.makedirs("sim_opt_design_results")
|
|
#import data from previous savez file
|
|
try:
|
|
with open("results/optimal_design.pkl", "rb") as f:
|
|
data = pickle.load(f)
|
|
RESOLUTION=data['RESOLUTION']
|
|
MAX_RUN_TIME = data['MAX_RUN_TIME']
|
|
WAVELENGTH_MIN_UM = data['WAVELENGTH_MIN_UM']
|
|
WAVELENGTH_MAX_UM = data['WAVELENGTH_MAX_UM']
|
|
DESIGN_REGION_CENTER = data['DESIGN_REGION_CENTER']
|
|
SILICON = data['SILICON']
|
|
SILICON_DIOXIDE = data['SILICON_DIOXIDE']
|
|
AIR = data['AIR']
|
|
cell_um = data['cell_um']
|
|
SUBSTRATE_THICKNESS = data['SUBSTRATE_THICKNESS']
|
|
SUBSTRATE_SIZE = data['SUBSTRATE_SIZE']
|
|
SUBSTRATE_CENTER = data['SUBSTRATE_CENTER']
|
|
physical_domains_size = data['physical_domains_size']
|
|
frequency_min = data['frequency_min']
|
|
frequency_max = data['frequency_max']
|
|
frequency_center = data['frequency_center']
|
|
frequency_width = data['frequency_width']
|
|
frequencies = data['frequencies']
|
|
num_wavelength = data['num_wavelengths']
|
|
SOURCE_CENTER = data['SOURCE_CENTER']
|
|
SOURCE_SIZE = data['SOURCE_SIZE']
|
|
NEAR_REGION_MONITOR_CENTER = data['NEAR_REGION_MONITOR_CENTER']
|
|
NEAR_REGION_MONITOR_SIZE = data['NEAR_REGION_MONITOR_SIZE']
|
|
FF_MONITOR_CENTER = data['FF_MONITOR_CENTER']
|
|
FF_MONITOR_SIZE = data['FF_MONITOR_SIZE']
|
|
xs = data['xs']
|
|
ys = data['ys']
|
|
ff_points = data['ff_points']
|
|
DESIGN_WAVELENGTHS_UM=data['DESIGN_WAVELENGTHS_UM']
|
|
BUFFER=data['BUFFER']
|
|
PML_UM=data['PML_UM']
|
|
DESIGN_REGION_UM=data['DESIGN_REGION_UM']
|
|
DESIGN_REGION_RESOLUTION=data['DESIGN_REGION_RESOLUTION']
|
|
NX_DESIGN_GRID=data['NX_DESIGN_GRID']
|
|
NY_DESIGN_GRID=data['NY_DESIGN_GRID']
|
|
MIN_LENGTH_UM=data['MIN_LENGTH_UM']
|
|
sigmoid_biases=data['sigmoid_biases']
|
|
max_eval=data['max_eval']
|
|
objfunc_history=data['objfunc_history']
|
|
epivar_history=data['epivar_history']
|
|
epigraph_variable=data['epigraph_variable']
|
|
unmapped_design_weights=data['unmapped_design_weights']
|
|
optimal_design_weights=data['optimal_design_weights']
|
|
except FileNotFoundError:
|
|
raise FileNotFoundError("Optimal design data not found.")
|
|
|
|
print(optimal_design_weights)
|
|
pml_layers = [mp.PML(PML_UM)]
|
|
|
|
view_2D_plane_xz = mp.Volume(
|
|
center=mp.Vector3(0,0,0),
|
|
size=mp.Vector3(cell_um.x,0,cell_um.z)
|
|
)
|
|
|
|
view_2D_plane_xy = mp.Volume(
|
|
center=mp.Vector3(0,0,DESIGN_REGION_CENTER.z/2),
|
|
size=mp.Vector3(cell_um.x,cell_um.y,0)
|
|
)
|
|
|
|
matgrid = mp.MaterialGrid(
|
|
grid_size = mp.Vector3(NX_DESIGN_GRID, NY_DESIGN_GRID,0),
|
|
medium1 = AIR,
|
|
medium2 = SILICON,
|
|
weights = optimal_design_weights.reshape((NX_DESIGN_GRID, NY_DESIGN_GRID))
|
|
)
|
|
|
|
matgrid_region = mpa.DesignRegion(
|
|
matgrid,
|
|
volume=mp.Volume(
|
|
center=DESIGN_REGION_CENTER,
|
|
size=DESIGN_REGION_UM
|
|
)
|
|
)
|
|
|
|
matgrid_block = mp.Block(
|
|
center=matgrid_region.center,
|
|
size=matgrid_region.size,
|
|
material=matgrid,
|
|
)
|
|
|
|
substrate_block = mp.Block(
|
|
center = SUBSTRATE_CENTER,
|
|
size = SUBSTRATE_SIZE,
|
|
material = SILICON_DIOXIDE,
|
|
)
|
|
|
|
geometry = [
|
|
matgrid_block,
|
|
substrate_block,
|
|
]
|
|
|
|
sources = [
|
|
mp.Source(
|
|
src=mp.GaussianSource(frequency_center, fwidth=frequency_width),
|
|
component=mp.Ex,
|
|
size=SOURCE_SIZE,
|
|
center=SOURCE_CENTER,
|
|
)
|
|
]
|
|
|
|
sim = mp.Simulation(
|
|
resolution=RESOLUTION,
|
|
default_material=AIR,
|
|
cell_size=cell_um,
|
|
sources=sources,
|
|
geometry=geometry,
|
|
boundary_layers=pml_layers,
|
|
k_point=mp.Vector3(),
|
|
)
|
|
|
|
plt.figure()
|
|
ax = plt.gca()
|
|
sim.plot2D(output_plane=view_2D_plane_xz, ax=ax)
|
|
plt.savefig(f"sim_opt_design_results/simulation_setup.pdf")
|
|
plt.close()
|
|
|
|
NearRegions = [
|
|
mp.Near2FarRegion(
|
|
center=NEAR_REGION_MONITOR_CENTER,
|
|
size=NEAR_REGION_MONITOR_SIZE,
|
|
weight=+1,
|
|
)
|
|
]
|
|
|
|
FarFields = mpa.Near2FarFields(
|
|
sim=sim,
|
|
Near2FarRegions=NearRegions,
|
|
far_pts=ff_points,
|
|
)
|
|
obj_list = [FarFields]
|
|
|
|
def dummy_J1(ff):
|
|
return [1]*num_wavelength
|
|
|
|
opt = mpa.OptimizationProblem(
|
|
simulation=sim,
|
|
objective_functions=[dummy_J1],
|
|
objective_arguments=[FarFields],
|
|
design_regions=[matgrid_region],
|
|
frequencies=frequencies,
|
|
maximum_run_time=MAX_RUN_TIME,
|
|
)
|
|
|
|
#make a plot of the optimization setup
|
|
plt.figure(figsize=(12,6))
|
|
ax1 = plt.subplot(1,2,1)
|
|
ax2 = plt.subplot(1,2,2)
|
|
opt.plot2D(True, output_plane=view_2D_plane_xz, ax=ax1)
|
|
|
|
opt.plot2D(True, output_plane=view_2D_plane_xy, ax=ax2)
|
|
|
|
plt.savefig(f"sim_opt_design_results/optimization_setup.pdf")
|
|
|
|
plt.close()
|
|
|
|
|
|
print(type(optimal_design_weights), optimal_design_weights.shape)
|
|
dummy = opt(
|
|
[
|
|
optimal_design_weights.flatten()
|
|
],
|
|
need_gradient=False,
|
|
)
|
|
|
|
#note that get_objective_arguments returns
|
|
# a LIST of the arguments passed to the obj. fun.
|
|
#we select the first list element, since we ony have one obj. fun.
|
|
solved_ff = opt.get_objective_arguments()[0]
|
|
|
|
def intensity_from_farfields(FarFields) -> np.ndarray:
|
|
'''Computes the intensity pattern at the monitor location from the simulated far-fields
|
|
|
|
Args:
|
|
FarFields: the simulated far-field patterns at the farfield
|
|
monitor location, for each wavelength
|
|
Returns:
|
|
A 2D-array [Nx*Ny,num_wavelengths] of intensities, for each wavelength,
|
|
at the monitor location.
|
|
'''
|
|
intensity_x = npa.abs(FarFields[:,:,0]) ** 2
|
|
|
|
return intensity_x
|
|
|
|
solved_intensity = intensity_from_farfields(solved_ff)
|
|
|
|
#make a plot of the ff intensities (at the center frequency)
|
|
array_to_plot = solved_intensity[:,1].reshape(NX_DESIGN_GRID, NY_DESIGN_GRID)
|
|
plt.figure()
|
|
plt.imshow(array_to_plot, origin='lower', extent=(-cell_um.x/2,cell_um.x/2,-cell_um.y/2,cell_um.y/2))
|
|
plt.xlabel("x (um)")
|
|
plt.ylabel("y (um)")
|
|
plt.title("Simulated far-field intensity at center frequency")
|
|
plt.colorbar(label="Intensity (a.u.)")
|
|
plt.savefig(f"sim_opt_design_results/simulated_farfield_intensity.pdf")
|
|
plt.close()
|
|
|