In this example, we demonstrate the inverse design of a metasurface color router as an alternative to conventional Bayer filters, which suffer from light loss due to absorption. We could significantly improve each pixel's efficiency by using the integrated intensity over R/G/B/G pixels as the figure of merit in the Lumopt (Python-based Lumerical optimization tool).
Overview
Understand the simulation workflow and key results
To design the metasurface we use a multi-parameters, multi-objectives topology Inverse Design optimization method from Lumerical Lumopt. We vary the refractive indexes of meta-atoms between 1.45 (SiO2) to 2.4 (TiO2) and maximize the optical efficiencies of the 4 3D 2x2x2 μm RGGB sensitive sensor zones.
Run and Results
Instructions for running the model and discussion of key results
Step 1: Define base simulation project
Download the file attached to this example and unzip all the files into one common directory. Then we need to define a base simulation project which contains the general structure of the device. This includes the simulation region, optimization region, the source and the Field Region monitors. The initial simulation project is generated via the script file Base_script_3D_TE_volume.lsf . We can inspect the setup by opening and running the script in FDTD:
First, we need to define a refractive index of two materials for metasurface. Here, we define 1.45 and 2.4 for two materials’ refractive indices. We can set the refractive index as 1 for air.
# SIMULATION PARAMETERS:
bg_index = 1.45; # refractive index of material_1
wg_index = 2.40; # refractive index of material_2
Second, we need to define the Field Region monitors location as Figure of Merit (FOM) monitors for each color. We define the size of monitors as 1 x 1 μm. You can modify the size and location of pixels by changing the size of Field Region monitors.
## FOM MONITOR LOCATION
## Red FOM
fom_xpos_red = -0.5e-6;
fom_ypos_red = 0.5e-6;
fom_zpos_red = -4e-6;
fom_xspan_red=1e-6;
fom_yspan_red=1e-6;
addfieldregion;
Finally, we need to define the optimization region by an optimization monitor. We define the size of optimization region as 2 x 2 x 2 μm. Also, you can change the optimization region as you want.
## OPTIMIZATION MONITOR LOCATION (0, 0, 0) size 1 x 1 x 1
opt_xpos = 0;
opt_ypos = 0;
opt_zpos = 0.5e-6;
opt_xspan = 2e-6;
opt_yspan = 2e-6;
opt_zmin = 0;
opt_zmax = 2e-6;
addpower;
Step 2: Define optimization region
For the next step, we need to define several optimization parameters in the script file topo_focus_3D_basic.py .
First, we need to define the figure of merit like below. Open the topo_focus_3D_basic.py in the FDTD Script File Editor. The field_region_name should be same as the name of field region monitor in the script file Base_script_3D_TE_volume.lsf .
######## DEFINE FIGURE OF MERIT ########
fom_red = IntensityVolume(field_region_name='fom_red')
fom_green_right = IntensityVolume(field_region_name='fom_green_right')
fom_green_left = IntensityVolume(field_region_name='fom_green_left')
fom_blue = IntensityVolume(field_region_name='fom_blue')
Second, we define the optimization algorithm.
######## DEFINE OPTIMIZATION ALGORITHM ########
optimizer_red = ScipyOptimizers(max_iter=50, method='L-BFGS-B', pgtol=1e-6, ftol=1e-4, scale_initial_gradient_to=0.25)
optimizer_green_right = ScipyOptimizers(max_iter=50, method='L-BFGS-B', pgtol=1e-6, ftol=1e-4, scale_initial_gradient_to=0.25)
optimizer_green_left = ScipyOptimizers(max_iter=50, method='L-BFGS-B', pgtol=1e-6, ftol=1e-4, scale_initial_gradient_to=0.25)
optimizer_blue = ScipyOptimizers(max_iter=50, method='L-BFGS-B', pgtol=1e-6, ftol=1e-4, scale_initial_gradient_to=0.25)
- max_iter : Determines after how many iterations, the greyscale phase ends. The optimizer can terminate before this number due to other criteria, but it will never perform more iterations. Increasing this number will often require more computational time but can lead to better performance.
- ftol : The minimum require change in the figure of merit (FOM) between two subsequent iterations for the greyscale optimization to continue.
- scale_initial_gradient_to : Enforces a rescaling of the gradient to change the optimization parameters by at least this much.
For more information, please see Getting Started with lumopt - Python API – Ansys Optics .
Third, we use SuperOptimization to co-optimize for RGGB pixels. We give a weight on blue wavelength because optical efficiency of blue wavelength is frequently higher than other wavelengths. The optical efficiency of other wavelengths is quite small, so we give the weight.
######## RUN THE OPTIMIZER ########
optT=[opt_red,opt_green_left,opt_green_right,opt_blue]
weights = [1,1,1,0.75]
opt= SuperOptimization(optimizations=optT, weights=weights)
opt.run()
Fourth, we should cross check the below values with the values in the script file Base_script_3D_TE_volume.lsf .
size_x = 2000 # equals to opt_field size @ 2um optimization monitor (optimization region only)
size_y = 2000 # equals to opt_field size @ 2um optimization monitor (optimization region only)
size_z = 2000 # equals to opt_field size @ 2um optimization monitor (optimization region only)
filter_R = 100e-9 # minimum feature size (filtering, that creates differences between df_deps: noisy and df_dp: smooth)
eps_wg = 2.40 ** 2
eps_bg = 1.45 ** 2
if len(sys.argv) > 2:
size_x = int(sys.argv[1])
filter_R = int(sys.argv[2]) * 1e-9
print(size_x, filter_R)
mesh_size = 30 ## in (nm) # Checkpoint *** [change mesh settings in FDTD using lsf file, crosscheck !! ]
x_points = int(size_x / mesh_size) + 1
y_points = int(size_y / mesh_size) + 1
z_points = int(size_z / mesh_size) + 1
x_pos = np.linspace(-size_x / 2 * 1e-9, size_x / 2 * 1e-9, x_points)
y_pos = np.linspace(-size_y / 2 * 1e-9, size_y / 2 * 1e-9, y_points)
z_pos = np.linspace((-size_z / 2 + 1000) * 1e-9, (size_z / 2 + 1000) * 1e-9, z_points)
- size_x, size_y, size_z : Length of the device. The unit is [nm]
- filter_R : Radius of the smoothing filter which removes small features and sharp corners. This value is only in the topo_focus_3D_basic.py so you don’t need to double check.
- eps_wg, eps_bg : Effective permittivity for materials. This valuesThese values should be checked with bg_indx and wg_index in *.lsf file.
- mesh size : FDTD mesh size.
- x_pos, y_pos, z_pos : Position of the optimization region. First and second values in the linspace function should be same as minimum and maximum of the optimization region for each axis.
Finally, we define the initial conditions for starting parameters. Since we use a local, gradient-based optimizer, the result often strongly depends on the initial guess. The given example has four different built-in initial conditions to try:
#### A list with different initial conditions for starting params
# params = None # use structure as user defined in the Lumerical FDTD
# params = np.ones((x_points,y_points)) # start with the domain filled with permittivity eps_wg
params = 0.5 * np.ones((x_points, y_points)) # start with the domain filled with permittivity (eps_lens + eps_bg)/2
# params = np.zeros((x_points,y_points)) # start with the domain filled with permittivity eps_bg
By uncommenting any of the lines, one can try different initial conditions. In addition, it is possible to provide custom initial conditions such as random noise or specific structures. After optimization, you can get the results of electric field distribution like below picture. We can see each light is well propagated to each pixel.
Also, you can calculate the optical efficiency by using the T (transmission) results of in the frequency-domain profile and power monitor.
Additional Resources
Additional documentation, examples and training material
Related Publications
- Zou, Xiujuan, et al. "Pixel-level Bayer-type colour router based on metasurfaces." Nature Communications 13.1 (2022): 3288.
- Christopher M. Lalau-Keraly, Samarth Bhargava, Owen D. Miller, and Eli Yablonovitch, "Adjoint shape optimization applied to electromagnetic design," Opt. Express 21 , 21693-21701, 2013.
See Also
- Grating coupler
- SOI taper design
- Spot size converter
- Convergence testing process for EME simulations
- Python API
- S-parameter simulator (SPS)
- S-parameter matrix sweep feature in KB
- S-parameter file formats