def adjoint_solver(design_params, mon_type): matgrid = mp.MaterialGrid(mp.Vector3(Nx,Ny), mp.air, silicon, design_parameters=np.ones((Nx,Ny))) matgrid_region = mpa.DesignRegion(matgrid, volume=mp.Volume(center=mp.Vector3(), size=mp.Vector3(design_shape.x,design_shape.y,0))) matgrid_geometry = [mp.Block(center=matgrid_region.center, size=matgrid_region.size, material=matgrid)] geometry = waveguide_geometry + matgrid_geometry sim = mp.Simulation(resolution=resolution, cell_size=cell_size, boundary_layers=boundary_layers, sources=sources, geometry=geometry) if mon_type.name == 'EIGENMODE': obj_list = [mpa.EigenmodeCoefficient(sim, mp.Volume(center=mp.Vector3(0.5*sxy-dpml), size=mp.Vector3(0,sxy,0)),1)] def J(mode_mon): return npa.abs(mode_mon)**2 elif mon_type.name == 'DFT': obj_list = [mpa.FourierFields(sim, mp.Volume(center=mp.Vector3(0.5*sxy-dpml), size=mp.Vector3(0,sxy,0)), mp.Ez)] def J(mode_mon): return npa.abs(mode_mon[0,63])**2 opt = mpa.OptimizationProblem( simulation = sim, objective_functions = J, objective_arguments = obj_list, design_regions = [matgrid_region], frequencies=[fcen], decay_fields=[mp.Ez]) f, dJ_du = opt([design_params]) sim.reset_meep() return f, dJ_du
def adjoint_solver_complex_fields(design_params, frequencies=None): matgrid = mp.MaterialGrid(mp.Vector3(Nx, Ny), mp.air, silicon, weights=np.ones((Nx, Ny))) matgrid_region = mpa.DesignRegion( matgrid, volume=mp.Volume(center=mp.Vector3(), size=mp.Vector3(design_region_size.x, design_region_size.y, 0))) geometry = [ mp.Block(center=matgrid_region.center, size=matgrid_region.size, material=matgrid) ] sim = mp.Simulation(resolution=resolution, cell_size=cell_size, k_point=k_point, boundary_layers=pml_x, sources=pt_source, geometry=geometry) if not frequencies: frequencies = [fcen] obj_list = [ mpa.FourierFields( sim, mp.Volume(center=mp.Vector3(0.9), size=mp.Vector3(0.2, 0.5)), mp.Ez) ] def J(dft_mon): return npa.power(npa.abs(dft_mon[:, 3, 9]), 2) opt = mpa.OptimizationProblem(simulation=sim, objective_functions=J, objective_arguments=obj_list, design_regions=[matgrid_region], frequencies=frequencies) f, dJ_du = opt([design_params]) sim.reset_meep() return f, dJ_du
def adjoint_solver(design_params, mon_type, frequencies=None, mat2=silicon): matgrid = mp.MaterialGrid(mp.Vector3(Nx, Ny), mp.air, mat2, weights=np.ones((Nx, Ny))) matgrid_region = mpa.DesignRegion( matgrid, volume=mp.Volume(center=mp.Vector3(), size=mp.Vector3(design_region_size.x, design_region_size.y, 0))) matgrid_geometry = [ mp.Block(center=matgrid_region.center, size=matgrid_region.size, material=matgrid) ] geometry = waveguide_geometry + matgrid_geometry sim = mp.Simulation(resolution=resolution, cell_size=cell_size, boundary_layers=pml_xy, sources=wvg_source, geometry=geometry) if not frequencies: frequencies = [fcen] if mon_type.name == 'EIGENMODE': obj_list = [ mpa.EigenmodeCoefficient( sim, mp.Volume(center=mp.Vector3(0.5 * sxy - dpml - 0.1), size=mp.Vector3(0, sxy - 2 * dpml, 0)), 1, eig_parity=eig_parity) ] def J(mode_mon): return npa.power(npa.abs(mode_mon), 2) elif mon_type.name == 'DFT': obj_list = [ mpa.FourierFields( sim, mp.Volume(center=mp.Vector3(1.25), size=mp.Vector3(0.25, 1, 0)), mp.Ez) ] def J(mode_mon): return npa.power(npa.abs(mode_mon[:, 4, 10]), 2) opt = mpa.OptimizationProblem(simulation=sim, objective_functions=J, objective_arguments=obj_list, design_regions=[matgrid_region], frequencies=frequencies) f, dJ_du = opt([design_params]) sim.reset_meep() return f, dJ_du