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_damping(design_params, frequencies=None, mat2=silicon): matgrid = mp.MaterialGrid(mp.Vector3(Nx, Ny), mp.air, mat2, weights=np.ones((Nx, Ny)), damping=3.14 * fcen) 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] 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) opt = mpa.OptimizationProblem(simulation=sim, objective_functions=J, objective_arguments=obj_list, design_regions=[matgrid_region], frequencies=frequencies, minimum_run_time=150) 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): design_variables = mp.MaterialGrid(mp.Vector3(Nr, 0, Nz), SiO2, Si) design_region = mpa.DesignRegion( design_variables, volume=mp.Volume(center=mp.Vector3(design_r / 2, 0, 0), size=mp.Vector3(design_r, 0, design_z))) geometry = [ mp.Block(center=design_region.center, size=design_region.size, material=design_variables) ] sim = mp.Simulation(cell_size=cell_size, boundary_layers=boundary_layers, geometry=geometry, sources=source, resolution=resolution, dimensions=dimensions, m=m) far_x = [mp.Vector3(5, 0, 20)] NearRegions = [ mp.Near2FarRegion(center=mp.Vector3( design_r / 2, 0, (sz / 2 - dpml + design_z / 2) / 2), size=mp.Vector3(design_r, 0, 0), weight=+1) ] FarFields = mpa.Near2FarFields(sim, NearRegions, far_x) ob_list = [FarFields] def J(alpha): return npa.abs(alpha[0, 0, 0])**2 opt = mpa.OptimizationProblem(simulation=sim, objective_functions=J, objective_arguments=ob_list, design_regions=[design_region], fcen=fcen, df=0, nf=1, maximum_run_time=1200) f, dJ_du = opt([design_params]) sim.reset_meep() return f, dJ_du
def build_straight_wg_simulation( wg_width=0.5, wg_padding=1.0, wg_length=1.0, pml_width=1.0, source_to_pml=0.5, source_to_monitor=0.1, frequencies=[1 / 1.55], gaussian_rel_width=0.2, sim_resolution=20, design_region_resolution=20, ): """Builds a simulation of a straight waveguide with a design region segment.""" design_region_shape = (1.0, wg_width) # Simulation domain size sx = 2 * pml_width + 2 * wg_length + design_region_shape[0] sy = 2 * pml_width + 2 * wg_padding + max( wg_width, design_region_shape[1], ) # Mean / center frequency fmean = onp.mean(frequencies) si = mp.Medium(index=3.4) sio2 = mp.Medium(index=1.44) sources = [ mp.EigenModeSource( mp.GaussianSource(frequency=fmean, fwidth=fmean * gaussian_rel_width), eig_band=1, direction=mp.NO_DIRECTION, eig_kpoint=mp.Vector3(1, 0, 0), size=mp.Vector3(0, wg_width + 2 * wg_padding, 0), center=[-sx / 2 + pml_width + source_to_pml, 0, 0], ), mp.EigenModeSource( mp.GaussianSource(frequency=fmean, fwidth=fmean * gaussian_rel_width), eig_band=1, direction=mp.NO_DIRECTION, eig_kpoint=mp.Vector3(-1, 0, 0), size=mp.Vector3(0, wg_width + 2 * wg_padding, 0), center=[sx / 2 - pml_width - source_to_pml, 0, 0], ), ] nx, ny = int(design_region_shape[0] * design_region_resolution), int( design_region_shape[1] * design_region_resolution) mat_grid = mp.MaterialGrid( mp.Vector3(nx, ny), sio2, si, grid_type='U_DEFAULT', ) design_regions = [ mpa.DesignRegion( mat_grid, volume=mp.Volume( center=mp.Vector3(), size=mp.Vector3( design_region_shape[0], design_region_shape[1], 0, ), ), ) ] geometry = [ mp.Block(center=mp.Vector3(x=-design_region_shape[0] / 2 - wg_length / 2 - pml_width / 2), material=si, size=mp.Vector3(wg_length + pml_width, wg_width, 0)), # left wg mp.Block(center=mp.Vector3(x=+design_region_shape[0] / 2 + wg_length / 2 + pml_width / 2), material=si, size=mp.Vector3(wg_length + pml_width, wg_width, 0)), # right wg mp.Block(center=design_regions[0].center, size=design_regions[0].size, material=mat_grid), # design region ] simulation = mp.Simulation( cell_size=mp.Vector3(sx, sy), boundary_layers=[mp.PML(pml_width)], geometry=geometry, sources=sources, resolution=sim_resolution, ) monitor_centers = [ mp.Vector3(-sx / 2 + pml_width + source_to_pml + source_to_monitor), mp.Vector3(sx / 2 - pml_width - source_to_pml - source_to_monitor), ] monitor_size = mp.Vector3(y=wg_width + 2 * wg_padding) monitors = [ mpa.EigenmodeCoefficient(simulation, mp.Volume(center=center, size=monitor_size), mode=1, forward=forward) for center in monitor_centers for forward in [True, False] ] return simulation, sources, monitors, design_regions, frequencies
direction=mp.NO_DIRECTION, eig_kpoint=kpoint, size=source_size, center=source_center) ] design_region_resolution = 10 Nx = design_region_resolution Ny = design_region_resolution design_variables = mp.MaterialGrid(mp.Vector3(Nx, Ny), SiO2, Si, grid_type='U_SUM') design_region = mpa.DesignRegion(design_variables, volume=mp.Volume(center=mp.Vector3(), size=mp.Vector3(1, 1, 0))) geometry = [ mp.Block(center=mp.Vector3(x=-Sx / 4), material=Si, size=mp.Vector3(Sx / 2, 0.5, 0)), # horizontal waveguide mp.Block(center=mp.Vector3(y=Sy / 4), material=Si, size=mp.Vector3(0.5, Sy / 2, 0)), # vertical waveguide mp.Block(center=design_region.center, size=design_region.size, material=design_variables), # design region mp.Block(center=design_region.center, size=design_region.size, material=design_variables,