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, e1=mp.Vector3(x=-1).rotate(mp.Vector3(z=1), np.pi / 2), e2=mp.Vector3(y=1).rotate(mp.Vector3(z=1), np.pi / 2)) ] sim = mp.Simulation(cell_size=cell_size, boundary_layers=pml_layers, geometry=geometry, sources=source, eps_averaging=False, resolution=resolution) TE_top = mpa.EigenmodeCoefficient(sim, mp.Volume(center=mp.Vector3(0, 1, 0), size=mp.Vector3(x=2)), mode=1) ob_list = [TE_top] def J(alpha): return npa.abs(alpha)**2 opt = mpa.OptimizationProblem(simulation=sim,
def __init__(self, dir_name, wavelength, thy_absorb, cyt_absorb): self.base_directory = base_directory + str(dir_name) self.wavelength = wavelength self.thy_absorb = thy_absorb self.cyt_absorb = cyt_absorb self.frequency = 1 / wavelength # Calculate wavelengths dependent on RI self.wavelength_in_media = wavelength / ri_media self.wavelength_in_cytoplasm = wavelength / ri_cytoplasm self.wavelength_in_thylakoid = wavelength / ri_thylakoid max_freq = self.frequency - 0.01 min_freq = self.frequency + 0.01 self.pulse_width = abs(max_freq - min_freq) cell = mp.Vector3(sxx, sxy, sxz) pml_layers = [mp.PML(dpml)] thylakoid_material = mp.Medium(index=ri_thylakoid, D_conductivity=2 * math.pi * self.frequency * (thy_absorb / (ri_thylakoid**2))) cytoplasm_material = mp.Medium(index=ri_cytoplasm, D_conductivity=2 * math.pi * self.frequency * (cyt_absorb / (ri_cytoplasm**2))) thylakoid_region = mp.Sphere(radius=cell_radius, center=mp.Vector3(0, 0, 0), material=thylakoid_material) cytoplasm_region = mp.Sphere(radius=cell_radius - thylakoid_thickness, center=mp.Vector3(0, 0, 0), material=cytoplasm_material) geometry = [thylakoid_region, cytoplasm_region] # Sources kdir = mp.Vector3(1, 0, 0) # direction of k (length is irrelevant) n = ri_media # refractive index of material containing the source k = kdir.unit().scale(2 * math.pi * self.frequency * n) # k with correct length def pw_amp(k, x0): def _pw_amp(x): return cmath.exp(1j * k.dot(x + x0)) return _pw_amp source = [ mp.Source( mp.ContinuousSource(frequency=self.frequency, fwidth=self.pulse_width), # along x axis component=mp.Ez, center=mp.Vector3(-0.5 * simulation_size, 0, 0), # x, ,y ,z size=mp.Vector3(0, sxy, sxz), amp_func=pw_amp(k, mp.Vector3(x=-0.5 * simulation_size))) ] sim = mp.Simulation( cell_size=cell, sources=source, boundary_layers=pml_layers, resolution=resolution, geometry=geometry, default_material=mp.Medium(index=ri_media), force_complex_fields=complex_f, eps_averaging=eps_av, ) def output_fields(sim): ez_output = open(base_directory + "Ez Field 650 HiAbs" + ".npy", 'wb') ez_array = sim.get_array(component=mp.Ez, cmplx=complex_f) ez_field_output = np.asarray(ez_array) np.save(ez_output, ez_field_output) ez_output.close() # ey_output = open(base_directory + "Ey Field 300 Std" + ".npy", 'wb') # ey_array = sim.get_array(component=mp.Ey, cmplx=complex_f) # ey_field_output = np.asarray(ey_array) # np.save(ey_output, ey_field_output) # ey_output.close() # # ex_output = open(base_directory + "Ex Field 300 std abs" + ".npy", 'wb') # ex_array = sim.get_array(component=mp.Ex, cmplx=complex_f) # ex_field_output = np.asarray(ex_array) # np.save(ex_output, ex_field_output) # ex_output.close() # eps_output = open(base_directory + "Refractive Index" + ".npy", 'wb') # eps_array = sim.get_array(component=mp.Dielectric, cmplx=complex_f) # np.save(eps_output, eps_array) # eps_output.close() sim.use_output_directory(self.base_directory) sim.run(mp.at_every(1, output_fields), until=t)
component=comp, center=mp.Vector3(-sizex / 2, 0)) ] # Absorber on grating side because of field divergence at metal/pml interface pml_layers = [ mp.PML(pml_th, direction=mp.X), mp.Absorber(pml_th, direction=mp.Y) ] # empty cell for reference run geometry = [] sim = mp.Simulation(cell_size=cell, boundary_layers=pml_layers, geometry=geometry, sources=sources, resolution=resolution, filename_prefix="data", split_chunks_evenly=False) # define monitors for further spectra calculation mon_height = sizey nfreq = 200 mon_skip = sizex / 20 # small skip from PML layers refl_fr = mp.FluxRegion(center=mp.Vector3(-sizex / 2 + mon_skip, 0, 0), size=mp.Vector3(0, mon_height, 0)) # flux region FFT region refl = sim.add_flux(cfreq, fwidth, nfreq, refl_fr) tran_fr = mp.FluxRegion(center=mp.Vector3(sizex / 2 - mon_skip, 0, 0), size=mp.Vector3(0, mon_height, 0))
# create a transparent source that excites a right-going waveguide mode modeNumber = 2 sources = [ mp.EigenModeSource(src=mp.ContinuousSource(1/1.55), direction=mp.X, center=mp.Vector3(),eig_band=modeNumber) ] force_complex_fields = True # so we can get time-average flux resolution = 20 sim = mp.Simulation( cell_size=cell, geometry=geometry, sources=sources, boundary_layers=pml_layers, force_complex_fields=force_complex_fields, resolution=resolution ) sim.run( mp.at_beginning(mp.output_epsilon), mp.at_end(mp.output_png(mp.Ex, "-a yarg -A $EPS -S3 -Zc dkbluered", rm_h5=False)), until=200 ) flux1 = sim.flux_in_box(mp.X, mp.Volume(center=mp.Vector3(-2.0), size=mp.Vector3(1.8, 6))) flux2 = sim.flux_in_box(mp.X, mp.Volume(center=mp.Vector3(2.0), size=mp.Vector3(1.8, 6))) # averaged over y region of width 1.8 print("left-going flux = {}".format(flux1 / -1.8))
def simulate_metalens(metalens): # Setup the MEEP objects cell = mp.Vector3(metalens['sim_cell_width'], metalens['sim_cell_height']) # All around the simulation cell pml_layers = [mp.PML(metalens['pml_width'])] # Set up the sources sources = [ mp.Source(src=mp.ContinuousSource(wavelength=metalens['wavelength'], width=metalens['source_width']), component=mp.Ex, amp_func=in_plane_dip_amp_func_Ex(metalens), center=mp.Vector3(0, metalens['source_coord']), size=mp.Vector3(2 * metalens['ws'], 0)), mp.Source(src=mp.ContinuousSource(wavelength=metalens['wavelength'], width=metalens['source_width']), component=mp.Hz, amp_func=in_plane_dip_amp_func_Hz(metalens), center=mp.Vector3(0, metalens['source_coord']), size=mp.Vector3(2 * metalens['ws'], 0)) ] # Set up the symmetries syms = [] if metalens['x_mirror_symmetry'] and (metalens['beta'] == 0 or metalens['beta'] == np.pi / 2): syms.append(mp.Mirror(mp.X)) sim = mp.Simulation(cell_size=cell, boundary_layers=pml_layers, geometry=metalens['geometry'], force_complex_fields=metalens['complex_fields'], symmetries=syms, sources=sources, resolution=metalens['resolution']) start_time = time.time() metalens['run_date'] = ( datetime.datetime.now().strftime("%b %d %Y at %H:%M:%S")) mp.quiet(metalens['quiet']) sim.init_sim() # Branch if saving for making an animation if metalens['save_output']: sim.run(mp.to_appended( "ez-{sim_id}".format(**metalens), mp.at_every(metalens['simulation_time'] / 1000., mp.output_efield_z)), until=metalens['simulation_time']) else: sim.run(until=metalens['simulation_time']) # Compute the clock run time and grab the fields metalens['array_metadata'] = sim.get_array_metadata() metalens['run_time_in_s'] = time.time() - start_time metalens['fields'] = { 'Ex': sim.get_array(component=mp.Ex).transpose(), 'Ey': sim.get_array(component=mp.Ey).transpose(), 'Hz': sim.get_array(component=mp.Hz).transpose() } metalens['eps'] = sim.get_epsilon().transpose() # Dump the result to disk if metalens['log_to_pkl'][0]: if metalens['log_to_pkl'][1] == '': pkl_fname = '%smetalens-%s.pkl' % (datadir, metalens['sim_id']) else: pkl_fname = metalens['log_to_pkl'][1] print(pkl_fname) pickle.dump(metalens, open(pkl_fname, 'wb')) return metalens
def init(self, no_bend=False, gdsii=False): sx = 16 sy = 32 cell = mp.Vector3(sx, sy, 0) pad = 4 w = 1 wvg_ycen = -0.5 * (sy - w - (2 * pad)) wvg_xcen = 0.5 * (sx - w - (2 * pad)) height = 100 data_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data') gdsii_file = os.path.join(data_dir, 'bend-flux.gds') if no_bend: if gdsii: geometry = mp.get_GDSII_prisms(mp.Medium(epsilon=12), gdsii_file, 1) else: no_bend_vertices = [ mp.Vector3(-0.5 * sx - 5, wvg_ycen - 0.5 * w), mp.Vector3(+0.5 * sx + 5, wvg_ycen - 0.5 * w), mp.Vector3(+0.5 * sx + 5, wvg_ycen + 0.5 * w), mp.Vector3(-0.5 * sx - 5, wvg_ycen + 0.5 * w) ] geometry = [ mp.Prism(no_bend_vertices, height, material=mp.Medium(epsilon=12)) ] else: if gdsii: geometry = mp.get_GDSII_prisms(mp.Medium(epsilon=12), gdsii_file, 2) else: bend_vertices = [ mp.Vector3(-0.5 * sx, wvg_ycen - 0.5 * w), mp.Vector3(wvg_xcen + 0.5 * w, wvg_ycen - 0.5 * w), mp.Vector3(wvg_xcen + 0.5 * w, 0.5 * sy), mp.Vector3(wvg_xcen - 0.5 * w, 0.5 * sy), mp.Vector3(wvg_xcen - 0.5 * w, wvg_ycen + 0.5 * w), mp.Vector3(-0.5 * sx, wvg_ycen + 0.5 * w) ] geometry = [ mp.Prism(bend_vertices, height, material=mp.Medium(epsilon=12)) ] fcen = 0.15 df = 0.1 sources = [ mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Ez, center=mp.Vector3(1 + (-0.5 * sx), wvg_ycen), size=mp.Vector3(0, w)) ] pml_layers = [mp.PML(1.0)] resolution = 10 nfreq = 100 self.sim = mp.Simulation(cell_size=cell, boundary_layers=pml_layers, geometry=geometry, sources=sources, resolution=resolution) if no_bend: fr = mp.FluxRegion(center=mp.Vector3((sx / 2) - 1.5, wvg_ycen), size=mp.Vector3(0, w * 2)) else: fr = mp.FluxRegion(center=mp.Vector3(wvg_xcen, (sy / 2) - 1.5), size=mp.Vector3(w * 2, 0)) self.trans = self.sim.add_flux(fcen, df, nfreq, fr) refl_fr = mp.FluxRegion(center=mp.Vector3((-0.5 * sx) + 1.5, wvg_ycen), size=mp.Vector3(0, w * 2)) self.refl = self.sim.add_flux(fcen, df, nfreq, refl_fr) if no_bend: self.pt = mp.Vector3((sx / 2) - 1.5, wvg_ycen) else: self.pt = mp.Vector3(wvg_xcen, (sy / 2) - 1.5)
material=mp.Medium(epsilon=12)) ] fcen = 0.15 df = 0.1 sources = [ mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Ez, center=mp.Vector3(-0.5 * sx + dpml, wvg_ycen, 0), size=mp.Vector3(0, w, 0)) ] sim = mp.Simulation(cell_size=cell, boundary_layers=pml_layers, geometry=geometry, sources=sources, resolution=resolution) nfreq = 100 # reflected flux refl_fr = mp.FluxRegion(center=mp.Vector3(-0.5 * sx + dpml + 0.5, wvg_ycen, 0), size=mp.Vector3(0, 2 * w, 0)) refl = sim.add_flux(fcen, df, nfreq, refl_fr) # transmitted flux tran_fr = mp.FluxRegion(center=mp.Vector3(0.5 * sx - dpml, wvg_ycen, 0), size=mp.Vector3(0, 2 * w, 0)) tran = sim.add_flux(fcen, df, nfreq, tran_fr)
def parallel_waveguide(s, xodd): geometry = [ mp.Block(center=mp.Vector3(-0.5 * (s + a)), size=mp.Vector3(a, a, mp.inf), material=Si), mp.Block(center=mp.Vector3(0.5 * (s + a)), size=mp.Vector3(a, a, mp.inf), material=Si) ] symmetries = [ mp.Mirror(mp.X, phase=-1.0 if xodd else 1.0), mp.Mirror(mp.Y, phase=-1.0) ] sources = [ mp.Source(src=mp.GaussianSource(fcen, fwidth=df), component=mp.Ey, center=mp.Vector3(-0.5 * (s + a)), size=mp.Vector3(a, a)), mp.Source(src=mp.GaussianSource(fcen, fwidth=df), component=mp.Ey, center=mp.Vector3(0.5 * (s + a)), size=mp.Vector3(a, a), amplitude=-1.0 if xodd else 1.0) ] sim = mp.Simulation(resolution=resolution, cell_size=cell, boundary_layers=pml_layers, geometry=geometry, symmetries=symmetries, k_point=k_point, sources=sources) h = mp.Harminv(mp.Ey, mp.Vector3(0.5 * (s + a)), fcen, df) sim.run(mp.after_sources(h), until_after_sources=200) f = h.modes[0].freq print("freq:, {}, {}".format(s, f)) sim.reset_meep() eig_sources = [ mp.EigenModeSource(src=mp.GaussianSource(f, fwidth=df), size=mp.Vector3(a, a), center=mp.Vector3(-0.5 * (s + a)), direction=mp.Z, eig_kpoint=k_point, eig_match_freq=True, eig_parity=mp.ODD_Y), mp.EigenModeSource(src=mp.GaussianSource(f, fwidth=df), size=mp.Vector3(a, a), center=mp.Vector3(0.5 * (s + a)), direction=mp.Z, eig_kpoint=k_point, eig_match_freq=True, eig_parity=mp.ODD_Y, amplitude=-1.0 if xodd else 1.0) ] sim.change_sources(eig_sources) flux_reg = mp.FluxRegion(direction=mp.Z, center=mp.Vector3(), size=mp.Vector3(1.2 * (2 * a + s), 1.2 * a)) wvg_flux = sim.add_flux(f, 0, 1, flux_reg) force_reg1 = mp.ForceRegion(mp.Vector3(0.5 * s), direction=mp.X, weight=1.0, size=mp.Vector3(y=a)) force_reg2 = mp.ForceRegion(mp.Vector3(0.5 * s + a), direction=mp.X, weight=-1.0, size=mp.Vector3(y=a)) wvg_force = sim.add_force(f, 0, 1, force_reg1, force_reg2) sim.run(until_after_sources=500) flux = mp.get_fluxes(wvg_flux)[0] force = mp.get_forces(wvg_force)[0] sim.reset_meep() return flux, force
def run_mode_coeffs(self, mode_num, kpoint_func): resolution = 15 w = 1 # width of waveguide L = 10 # length of waveguide Si = mp.Medium(epsilon=12.0) dair = 3.0 dpml = 3.0 sx = dpml + L + dpml sy = dpml + dair + w + dair + dpml cell_size = mp.Vector3(sx, sy, 0) prism_x = sx + 1 prism_y = w / 2 vertices = [ mp.Vector3(-prism_x, prism_y), mp.Vector3(prism_x, prism_y), mp.Vector3(prism_x, -prism_y), mp.Vector3(-prism_x, -prism_y) ] geometry = [mp.Prism(vertices, height=mp.inf, material=Si)] boundary_layers = [mp.PML(dpml)] # mode frequency fcen = 0.20 # > 0.5/sqrt(11) to have at least 2 modes sources = [ mp.EigenModeSource(src=mp.GaussianSource(fcen, fwidth=0.5 * fcen), eig_band=mode_num, size=mp.Vector3(0, sy - 2 * dpml, 0), center=mp.Vector3(-0.5 * sx + dpml, 0, 0), eig_match_freq=True, eig_resolution=32) ] sim = mp.Simulation( resolution=resolution, cell_size=cell_size, boundary_layers=boundary_layers, geometry=geometry, sources=sources, symmetries=[mp.Mirror(mp.Y, phase=1 if mode_num % 2 == 1 else -1)]) xm = 0.5 * sx - dpml # x-coordinate of monitor mflux = sim.add_mode_monitor( fcen, 0, 1, mp.ModeRegion(center=mp.Vector3(xm, 0), size=mp.Vector3(0, sy - 2 * dpml))) mode_flux = sim.add_flux( fcen, 0, 1, mp.FluxRegion(center=mp.Vector3(xm, 0), size=mp.Vector3(0, sy - 2 * dpml))) # sim.run(until_after_sources=mp.stop_when_fields_decayed(50, mp.Ez, mp.Vector3(-0.5*sx+dpml,0), 1e-10)) sim.run(until_after_sources=100) modes_to_check = [ 1, 2 ] # indices of modes for which to compute expansion coefficients res = sim.get_eigenmode_coefficients(mflux, modes_to_check, kpoint_func=kpoint_func) self.assertTrue(res.kpoints[0].close(mp.Vector3(0.604301, 0, 0))) self.assertTrue(res.kpoints[1].close(mp.Vector3(0.494353, 0, 0), tol=1e-2)) self.assertTrue(res.kdom[0].close(mp.Vector3(0.604301, 0, 0))) self.assertTrue(res.kdom[1].close(mp.Vector3(0.494353, 0, 0), tol=1e-2)) mode_power = mp.get_fluxes(mode_flux)[0] TestPassed = True TOLERANCE = 5.0e-3 c0 = res.alpha[ mode_num - 1, 0, 0] # coefficient of forward-traveling wave for mode #mode_num for nm in range(1, len(modes_to_check) + 1): if nm != mode_num: cfrel = np.abs(res.alpha[nm - 1, 0, 0]) / np.abs(c0) cbrel = np.abs(res.alpha[nm - 1, 0, 1]) / np.abs(c0) if cfrel > TOLERANCE or cbrel > TOLERANCE: TestPassed = False self.sim = sim # test 1: coefficient of excited mode >> coeffs of all other modes self.assertTrue(TestPassed, msg="cfrel: {}, cbrel: {}".format(cfrel, cbrel)) # test 2: |mode coeff|^2 = power self.assertAlmostEqual(mode_power / abs(c0**2), 1.0, places=1) return res
def main(args): d = args.d cell_thickness = dpml + t_oxide + t_Si + t_air + dpml cell_zmax = 0.5 * cell_thickness if args.three_d else 0 cell_zmin = -0.5 * cell_thickness if args.three_d else 0 si_zmin = 0 si_zmax = t_Si if args.three_d else 0 # read cell size, volumes for source region and flux monitors, # and coupler geometry from GDSII file upper_branch = mp.get_GDSII_prisms(silicon, gdsII_file, UPPER_BRANCH_LAYER, si_zmin, si_zmax) lower_branch = mp.get_GDSII_prisms(silicon, gdsII_file, LOWER_BRANCH_LAYER, si_zmin, si_zmax) cell = mp.GDSII_vol(gdsII_file, CELL_LAYER, cell_zmin, cell_zmax) p1 = mp.GDSII_vol(gdsII_file, PORT1_LAYER, si_zmin, si_zmax) p2 = mp.GDSII_vol(gdsII_file, PORT2_LAYER, si_zmin, si_zmax) p3 = mp.GDSII_vol(gdsII_file, PORT3_LAYER, si_zmin, si_zmax) p4 = mp.GDSII_vol(gdsII_file, PORT4_LAYER, si_zmin, si_zmax) src_vol = mp.GDSII_vol(gdsII_file, SOURCE_LAYER, si_zmin, si_zmax) # displace upper and lower branches of coupler (as well as source and flux regions) if d != default_d: delta_y = 0.5 * (d - default_d) delta = mp.Vector3(y=delta_y) p1.center += delta p2.center -= delta p3.center += delta p4.center -= delta src_vol.center += delta cell.size += 2 * delta for np in range(len(lower_branch)): lower_branch[np].center -= delta for nv in range(len(lower_branch[np].vertices)): lower_branch[np].vertices[nv] -= delta for np in range(len(upper_branch)): upper_branch[np].center += delta for nv in range(len(upper_branch[np].vertices)): upper_branch[np].vertices[nv] += delta geometry = upper_branch + lower_branch if args.three_d: oxide_center = mp.Vector3(z=-0.5 * t_oxide) oxide_size = mp.Vector3(cell.size.x, cell.size.y, t_oxide) oxide_layer = [ mp.Block(material=oxide, center=oxide_center, size=oxide_size) ] geometry = geometry + oxide_layer sources = [ mp.EigenModeSource(src=mp.GaussianSource(fcen, fwidth=df), size=src_vol.size, center=src_vol.center, eig_match_freq=True) ] sim = mp.Simulation(resolution=resolution, cell_size=cell.size, boundary_layers=[mp.PML(dpml)], sources=sources, geometry=geometry) p1_region = mp.FluxRegion(volume=p1) flux1 = sim.add_flux(fcen, 0, 1, p1_region) p2_region = mp.FluxRegion(volume=p2) flux2 = sim.add_flux(fcen, 0, 1, p2_region) p3_region = mp.FluxRegion(volume=p3) flux3 = sim.add_flux(fcen, 0, 1, p3_region) p4_region = mp.FluxRegion(volume=p4) flux4 = sim.add_flux(fcen, 0, 1, p4_region) sim.run(until_after_sources=mp.stop_when_fields_decayed( 50, mp.Ez, p3.center, 1e-9)) p1_flux = mp.get_fluxes(flux1) p2_flux = mp.get_fluxes(flux2) p3_flux = mp.get_fluxes(flux3) p4_flux = mp.get_fluxes(flux4) mp.master_printf("data:, {}, {}, {}, {}".format(d, -p2_flux[0] / p1_flux[0], p3_flux[0] / p1_flux[0], p4_flux[0] / p1_flux[0]))
def refl_planar(self, theta, special_kz): resolution = 100 # pixels/um dpml = 1.0 sx = 3 + 2 * dpml sy = 1 / resolution cell_size = mp.Vector3(sx, sy) pml_layers = [mp.PML(dpml, direction=mp.X)] fcen = 1.0 # source wavelength = 1 um k_point = mp.Vector3(z=math.sin(theta)).scale(fcen) sources = [ mp.Source(mp.GaussianSource(fcen, fwidth=0.2 * fcen), component=mp.Ez, center=mp.Vector3(-0.5 * sx + dpml), size=mp.Vector3(y=sy)) ] sim = mp.Simulation(cell_size=cell_size, boundary_layers=pml_layers, sources=sources, k_point=k_point, special_kz=special_kz, resolution=resolution) refl_fr = mp.FluxRegion(center=mp.Vector3(-0.25 * sx), size=mp.Vector3(y=sy)) refl = sim.add_flux(fcen, 0, 1, refl_fr) sim.run(until_after_sources=mp.stop_when_fields_decayed( 50, mp.Ez, mp.Vector3(), 1e-9)) empty_flux = mp.get_fluxes(refl) empty_data = sim.get_flux_data(refl) sim.reset_meep() geometry = [ mp.Block(material=mp.Medium(index=3.5), size=mp.Vector3(0.5 * sx, mp.inf, mp.inf), center=mp.Vector3(0.25 * sx)) ] sim = mp.Simulation(cell_size=cell_size, boundary_layers=pml_layers, geometry=geometry, sources=sources, k_point=k_point, special_kz=special_kz, resolution=resolution) refl = sim.add_flux(fcen, 0, 1, refl_fr) sim.load_minus_flux_data(refl, empty_data) sim.run(until_after_sources=mp.stop_when_fields_decayed( 50, mp.Ez, mp.Vector3(), 1e-9)) refl_flux = mp.get_fluxes(refl) Rmeep = -refl_flux[0] / empty_flux[0] return Rmeep
math.sqrt(3) / 2), mp.Vector3(0.5, math.sqrt(3) / 2), mp.Vector3(1, 0), mp.Vector3(0.5, -math.sqrt(3) / 2), mp.Vector3(-0.5, -math.sqrt(3) / 2) ] geometry = [ #mp.Block(center=mp.Vector3(0,0,0), size=cell_size, material=mp.air), mp.Prism(vertices, height=1.9, material=mp.metal, center=mp.Vector3(0, 0, 0)) ] sim = mp.Simulation(resolution=50, cell_size=cell_size, geometry=geometry) sim.init_sim() eps_data = sim.get_epsilon() #eps_data = sim.get_array() #sim.plot3D(eps_data) #from mayavi import mlab #s = mlab.contour3d() #mlab.show() #mlab.savefig(filename='test2.png') from mayavi import mlab s = mlab.contour3d(eps_data, colormap="hsv")
#source=[mp.Source(mp.ContinuousSource(fcen,df,nfreq), # component=mp.Ex, # center=mp.Vector3(0,-0.90,0), # size=mp.Vector3(sx-2.1,0,0))] source = [ mp.Source(mp.GaussianSource(fcen, df, nfreq), component=mp.Ex, center=mp.Vector3(0, -0.90, 0), size=mp.Vector3(sx - 2.1, 0, 0)) ] symmetries = [mp.Mirror(mp.X), mp.Mirror(mp.Z)] sim = mp.Simulation(cell_size=cell, geometry=geometry, sources=source, resolution=resolution, boundary_layers=pml_layers, filename_prefix='ref_slab') pt = mp.Vector3(0, -0.90, 0) sim.run(mp.dft_ldos(fcen, 0, nfreq), mp.at_beginning(mp.output_epsilon), mp.to_appended("ref_hz", mp.at_every(0.05, mp.output_hfield_z)), until_after_sources=mp.stop_when_fields_decayed(10, mp.Hz, pt, 1e-3)) #sim.run(mp.dft_ldos(fcen,0,nfreq),mp.at_beginning(mp.output_epsilon),mp.at_end(mp.output_efield_x),until=50) eps_data1 = sim.get_array(center=mp.Vector3(0, 0, 0), size=mp.Vector3(sx - 2, sy - 2, sz), component=mp.Dielectric) ex_data1 = sim.get_array(center=mp.Vector3(0, 0, 0), size=mp.Vector3(sx - 2, sy - 2, sz), component=mp.Ex) hz_data1 = sim.get_array(center=mp.Vector3(0, 0, 0),
def grating(gp, gh, gdc, oddz): sx = dpml + dsub + gh + dpad + dpml sy = gp cell_size = mp.Vector3(sx, sy, 0) pml_layers = [mp.PML(thickness=dpml, direction=mp.X)] src_pt = mp.Vector3(-0.5 * sx + dpml + 0.5 * dsub, 0, 0) sources = [ mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Ez if oddz else mp.Hz, center=src_pt, size=mp.Vector3(0, sy, 0)) ] symmetries = [mp.Mirror(mp.Y, phase=+1 if oddz else -1)] sim = mp.Simulation(resolution=resolution, cell_size=cell_size, boundary_layers=pml_layers, k_point=k_point, default_material=glass, sources=sources, symmetries=symmetries) mon_pt = mp.Vector3(0.5 * sx - dpml - 0.5 * dpad, 0, 0) flux_mon = sim.add_flux( fcen, df, nfreq, mp.FluxRegion(center=mon_pt, size=mp.Vector3(0, sy, 0))) sim.run(until_after_sources=100) input_flux = mp.get_fluxes(flux_mon) sim.reset_meep() geometry = [ mp.Block(material=glass, size=mp.Vector3(dpml + dsub, mp.inf, mp.inf), center=mp.Vector3(-0.5 * sx + 0.5 * (dpml + dsub), 0, 0)), mp.Block(material=glass, size=mp.Vector3(gh, gdc * gp, mp.inf), center=mp.Vector3(-0.5 * sx + dpml + dsub + 0.5 * gh, 0, 0)) ] sim = mp.Simulation(resolution=resolution, cell_size=cell_size, boundary_layers=pml_layers, geometry=geometry, k_point=k_point, sources=sources, symmetries=symmetries) mode_mon = sim.add_flux( fcen, df, nfreq, mp.FluxRegion(center=mon_pt, size=mp.Vector3(0, sy, 0))) sim.run(until_after_sources=300) freqs = mp.get_eigenmode_freqs(mode_mon) res = sim.get_eigenmode_coefficients( mode_mon, [1], eig_parity=mp.ODD_Z + mp.EVEN_Y if oddz else mp.EVEN_Z + mp.ODD_Y) coeffs = res.alpha mode_wvl = [1 / freqs[nf] for nf in range(nfreq)] mode_tran = [ abs(coeffs[0, nf, 0])**2 / input_flux[nf] for nf in range(nfreq) ] mode_phase = [np.angle(coeffs[0, nf, 0]) for nf in range(nfreq)] return mode_wvl, mode_tran, mode_phase
3**0.5 / 6 * radius_percentage), material=mp.Medium(epsilon=eps_si_5200)) ] sources = [ mp.Source(mp.GaussianSource(frequency=fcen, fwidth=fwidth), mp.Ez, mp.Vector3(-10.5, 0)) ] pml_layers = [mp.PML(plmWidth)] resolution = 32 sim = mp.Simulation(cell_size=cell, boundary_layers=pml_layers, geometry=geometry, default_material=mp.Medium(index=1), sources=sources, resolution=resolution) sim.use_output_directory("wave_in_band_gap") def myhello(thisSim): # print(-0.4*sx+sim.meep_time()*v) if (thisSim.meep_time() > 90): movingSources = [] thisSim.change_sources(movingSources) return sim.run(mp.at_beginning(mp.output_epsilon),
def make_sim(cell, res, pml, dims, create_gv=True, k_point=False): sim = mp.Simulation(cell_size=cell, resolution=res, boundary_layers=pml, dimensions=dims, k_point=k_point) if create_gv: sim._create_grid_volume(False) return sim
def test_refl_angular(self): resolution = 100 dpml = 1.0 sz = 10 sz = sz + 2 * dpml cell_size = mp.Vector3(z=sz) pml_layers = [mp.PML(dpml)] wvl_min = 0.4 wvl_max = 0.8 fmin = 1 / wvl_max fmax = 1 / wvl_min fcen = 0.5 * (fmin + fmax) df = fmax - fmin nfreq = 50 theta_r = math.radians(0) k = mp.Vector3(math.sin(theta_r), 0, math.cos(theta_r)).scale(fcen) dimensions = 1 sources = [ mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Ex, center=mp.Vector3(z=-0.5 * sz + dpml)) ] sim = mp.Simulation(cell_size=cell_size, boundary_layers=pml_layers, sources=sources, k_point=k, dimensions=dimensions, resolution=resolution) refl_fr = mp.FluxRegion(center=mp.Vector3(z=-0.25 * sz)) refl = sim.add_flux(fcen, df, nfreq, refl_fr) sim.run(until_after_sources=mp.stop_when_fields_decayed( 50, mp.Ex, mp.Vector3(z=-0.5 * sz + dpml), 1e-9)) empty_data = sim.get_flux_data(refl) sim.reset_meep() geometry = [ mp.Block(mp.Vector3(mp.inf, mp.inf, 0.5 * sz), center=mp.Vector3(z=0.25 * sz), material=mp.Medium(index=3.5)) ] sim = mp.Simulation(cell_size=cell_size, geometry=geometry, boundary_layers=pml_layers, sources=sources, k_point=k, dimensions=dimensions, resolution=resolution) refl = sim.add_flux(fcen, df, nfreq, refl_fr) sim.load_minus_flux_data(refl, empty_data) sim.run(until_after_sources=mp.stop_when_fields_decayed( 50, mp.Ex, mp.Vector3(z=-0.5 * sz + dpml), 1e-9)) refl_flux = mp.get_fluxes(refl) freqs = mp.get_flux_freqs(refl) expected = [ (1.25, -1.123696883299492e-6), (1.2755102040816326, -2.5749667658387866e-6), (1.3010204081632653, -5.70480204599006e-6), (1.3265306122448979, -1.2220464827582253e-5), (1.3520408163265305, -2.531247480206961e-5), (1.3775510204081631, -5.069850309492639e-5), (1.4030612244897958, -9.819256552437341e-5), (1.4285714285714284, -1.8390448659017395e-4), (1.454081632653061, -3.330762066794769e-4), (1.4795918367346936, -5.833650417163753e-4), (1.5051020408163263, -9.8807834237052e-4), (1.5306122448979589, -0.001618472171445976), (1.5561224489795915, -0.0025638388059825985), (1.5816326530612241, -0.003927863989816029), (1.6071428571428568, -0.005819831283556752), (1.6326530612244894, -0.008339881000982728), (1.658163265306122, -0.011558769654206626), (1.6836734693877546, -0.015494308354153143), (1.7091836734693873, -0.02008850084337135), (1.73469387755102, -0.025190871516857616), (1.7602040816326525, -0.030553756123198477), (1.7857142857142851, -0.03584404966066722), (1.8112244897959178, -0.040672967700428275), (1.8367346938775504, -0.04464118393086191), (1.862244897959183, -0.047392712128477496), (1.8877551020408156, -0.048667403362887635), (1.9132653061224483, -0.048341494285878264), (1.938775510204081, -0.04644739000778679), (1.9642857142857135, -0.043168390293742316), (1.9897959183673462, -0.0388094755730579), (2.0153061224489788, -0.03375052221907117), (2.0408163265306114, -0.02839209067703472), (2.066326530612244, -0.023104245646230648), (2.0918367346938767, -0.01818725699718267), (2.1173469387755093, -0.013849270759480073), (2.142857142857142, -0.010201733597436358), (2.1683673469387745, -0.007269616609175294), (2.193877551020407, -0.005011210495189995), (2.21938775510204, -0.0033417192031464896), (2.2448979591836724, -0.0021557351734376256), (2.270408163265305, -0.0013453062176115673), (2.2959183673469377, -8.121742663131631e-4), (2.3214285714285703, -4.7433135191915683e-4), (2.346938775510203, -2.6799188013374266e-4), (2.3724489795918355, -1.464781343401766e-4), (2.397959183673468, -7.745339273024636e-5), (2.423469387755101, -3.9621374769542025e-5), (2.4489795918367334, -1.9608458558430508e-5), (2.474489795918366, -9.38818477949983e-6), (2.4999999999999987, -4.3484671364929225e-6), ] np.testing.assert_allclose(expected, list(zip(freqs, refl_flux)), rtol=1e-6)
def main(args): resolution = args.res w1 = 1 # width of waveguide 1 w2 = 2 # width of waveguide 2 Lw = 10 # length of waveguide 1 and 2 Lt = args.Lt # taper length Si = mp.Medium(epsilon=12.0) dair = 3.0 dpml = 5.0 sx = dpml + Lw + Lt + Lw + dpml sy = dpml + dair + w2 + dair + dpml cell_size = mp.Vector3(sx, sy, 0) prism_x = sx + 1 half_w1 = 0.5 * w1 half_w2 = 0.5 * w2 half_Lt = 0.5 * Lt if Lt > 0: vertices = [ mp.Vector3(-prism_x, half_w1), mp.Vector3(-half_Lt, half_w1), mp.Vector3(half_Lt, half_w2), mp.Vector3(prism_x, half_w2), mp.Vector3(prism_x, -half_w2), mp.Vector3(half_Lt, -half_w2), mp.Vector3(-half_Lt, -half_w1), mp.Vector3(-prism_x, -half_w1) ] else: vertices = [ mp.Vector3(-prism_x, half_w1), mp.Vector3(prism_x, half_w1), mp.Vector3(prism_x, -half_w1), mp.Vector3(-prism_x, -half_w1) ] geometry = [mp.Prism(vertices, height=mp.inf, material=Si)] boundary_layers = [mp.PML(dpml)] # mode wavelength lcen = 6.67 # mode frequency fcen = 1 / lcen sources = [ mp.EigenModeSource(src=mp.GaussianSource(fcen, fwidth=0.2 * fcen), component=mp.Ez, size=mp.Vector3(0, sy - 2 * dpml, 0), center=mp.Vector3(-0.5 * sx + dpml + 0.2 * Lw, 0, 0), eig_match_freq=True, eig_parity=mp.ODD_Z + mp.EVEN_Y) ] sim = mp.Simulation(resolution=resolution, cell_size=cell_size, boundary_layers=boundary_layers, geometry=geometry, sources=sources) xm = -0.5 * sx + dpml + 0.5 * Lw # x-coordinate of monitor mode_monitor = sim.add_eigenmode( fcen, 0, 1, mp.FluxRegion(center=mp.Vector3(xm, 0), size=mp.Vector3(0, sy - 2 * dpml))) sim.run(until_after_sources=mp.stop_when_fields_decayed( 50, mp.Ez, mp.Vector3(xm, 0, 0), 1e-9)) coeffs = sim.get_eigenmode_coefficients(mode_monitor, [1]) print("mode:, {}, {:.8f}, {:.8f}".format(Lt, abs(coeffs[0, 0, 0])**2, abs(coeffs[0, 0, 1])**2))
def pol_grating(d, ph, gp, nmode): sx = dpml + dsub + d + d + dpad + dpml sy = gp cell_size = mp.Vector3(sx, sy, 0) pml_layers = [mp.PML(thickness=dpml, direction=mp.X)] # twist angle of nematic director; from equation 1b def phi(p): xx = p.x - (-0.5 * sx + dpml + dsub) if (xx >= 0) and (xx <= d): return math.pi * p.y / gp + ph * xx / d else: return math.pi * p.y / gp - ph * xx / d + 2 * ph # return the anisotropic permittivity tensor for a uniaxial, twisted nematic liquid crystal def lc_mat(p): # rotation matrix for rotation around x axis Rx = mp.Matrix(mp.Vector3(1, 0, 0), mp.Vector3(0, math.cos(phi(p)), math.sin(phi(p))), mp.Vector3(0, -math.sin(phi(p)), math.cos(phi(p)))) lc_epsilon = Rx * epsilon_diag * Rx.transpose() lc_epsilon_diag = mp.Vector3(lc_epsilon[0].x, lc_epsilon[1].y, lc_epsilon[2].z) lc_epsilon_offdiag = mp.Vector3(lc_epsilon[1].x, lc_epsilon[2].x, lc_epsilon[2].y) return mp.Medium(epsilon_diag=lc_epsilon_diag, epsilon_offdiag=lc_epsilon_offdiag) geometry = [ mp.Block(center=mp.Vector3(-0.5 * sx + 0.5 * (dpml + dsub)), size=mp.Vector3(dpml + dsub, mp.inf, mp.inf), material=mp.Medium(index=n_0)), mp.Block(center=mp.Vector3(-0.5 * sx + dpml + dsub + d), size=mp.Vector3(2 * d, mp.inf, mp.inf), material=lc_mat) ] # linear-polarized planewave pulse source src_pt = mp.Vector3(-0.5 * sx + dpml + 0.3 * dsub, 0, 0) sources = [ mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Ez, center=src_pt, size=mp.Vector3(0, sy, 0)), mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Ey, center=src_pt, size=mp.Vector3(0, sy, 0)) ] sim = mp.Simulation(resolution=resolution, cell_size=cell_size, boundary_layers=pml_layers, k_point=k_point, sources=sources, default_material=mp.Medium(index=n_0)) refl_pt = mp.Vector3(-0.5 * sx + dpml + 0.5 * dsub, 0, 0) refl_flux = sim.add_flux( fcen, 0, 1, mp.FluxRegion(center=refl_pt, size=mp.Vector3(0, sy, 0))) sim.run(until_after_sources=100) input_flux = mp.get_fluxes(refl_flux) input_flux_data = sim.get_flux_data(refl_flux) sim.reset_meep() sim = mp.Simulation(resolution=resolution, cell_size=cell_size, boundary_layers=pml_layers, k_point=k_point, sources=sources, geometry=geometry) refl_flux = sim.add_flux( fcen, 0, 1, mp.FluxRegion(center=refl_pt, size=mp.Vector3(0, sy, 0))) sim.load_minus_flux_data(refl_flux, input_flux_data) tran_pt = mp.Vector3(0.5 * sx - dpml - 0.5 * dpad, 0, 0) tran_flux = sim.add_flux( fcen, 0, 1, mp.FluxRegion(center=tran_pt, size=mp.Vector3(0, sy, 0))) sim.run(until_after_sources=300) res1 = sim.get_eigenmode_coefficients(tran_flux, range(1, nmode + 1), eig_parity=mp.ODD_Z + mp.EVEN_Y) res2 = sim.get_eigenmode_coefficients(tran_flux, range(1, nmode + 1), eig_parity=mp.EVEN_Z + mp.ODD_Y) angles = [math.degrees(math.acos(kdom.x / fcen)) for kdom in res1.kdom] return input_flux[0], angles, res1.alpha[:, 0, 0], res2.alpha[:, 0, 0]
sx = 40 sy = 6 cell_size = mp.Vector3(sx + 2 * dpml, sy) v0 = 1.0 # pulse center frequency a = 0.2 # Gaussian envelope half-width b = -0.5 # linear chirp rate (positive: up-chirp, negative: down-chirp) t0 = 15 # peak time def chirp(t): return np.exp(1j * 2 * np.pi * v0 * (t - t0)) * \ np.exp(-a * (t - t0)**2 + 1j * b * (t - t0)**2) sources = [mp.Source(src=mp.CustomSource(src_func=chirp), center=mp.Vector3(-0.5 * sx), size=mp.Vector3(y=sy), component=mp.Ez)] sim = mp.Simulation(cell_size=cell_size, boundary_layers=pml_layers, resolution=resolution, k_point=mp.Vector3(), sources=sources, symmetries=[mp.Mirror(mp.Y)]) sim.run(mp.in_volume(mp.Volume(center=mp.Vector3(), size=mp.Vector3(sx, sy)), mp.at_every(2.7, mp.output_efield_z)), until=t0 + 50)
def wvg_flux(self, res, att_coeff): """ Computes the Poynting flux in a single-mode waveguide at two locations (5 and 10 μm) downstream from the source given the grid resolution res (pixels/μm) and material attenuation coefficient att_coeff (dB/cm). """ cell_size = mp.Vector3(14., 14.) pml_layers = [mp.PML(thickness=2.)] w = 1. # width of waveguide fsrc = 0.15 # frequency (in vacuum) # note: MPB can only compute modes of lossless material systems. # The imaginary part of ε is ignored and the launched # waveguide mode is therefore inaccurate. For small values # of imag(ε) (which is proportional to att_coeff), this # inaccuracy tends to be insignificant. sources = [ mp.EigenModeSource(src=mp.GaussianSource(fsrc, fwidth=0.2 * fsrc), center=mp.Vector3(-5.), size=mp.Vector3(y=10.), eig_parity=mp.EVEN_Y + mp.ODD_Z) ] # ref: https://en.wikipedia.org/wiki/Mathematical_descriptions_of_opacity # Note that this is the loss of a planewave, which is only approximately # the loss of a waveguide mode. In principle, we could compute the latter # semi-analytically if we wanted to run this unit test to greater accuracy # (e.g. to test convergence with resolution). n_eff = np.sqrt(12.) + 1j * (1 / fsrc) * (dB_cm_to_dB_um * att_coeff) / (4 * np.pi) eps_eff = n_eff * n_eff # ref: https://meep.readthedocs.io/en/latest/Materials/#conductivity-and-complex sigma_D = 2 * np.pi * fsrc * np.imag(eps_eff) / np.real(eps_eff) geometry = [ mp.Block(center=mp.Vector3(), size=mp.Vector3(mp.inf, w, mp.inf), material=mp.Medium(epsilon=np.real(eps_eff), D_conductivity=sigma_D)) ] sim = mp.Simulation(cell_size=cell_size, resolution=res, boundary_layers=pml_layers, sources=sources, geometry=geometry, symmetries=[mp.Mirror(mp.Y)]) tran1 = sim.add_flux( fsrc, 0, 1, mp.FluxRegion(center=mp.Vector3(x=0.), size=mp.Vector3(y=10.))) tran2 = sim.add_flux( fsrc, 0, 1, mp.FluxRegion(center=mp.Vector3(x=5.), size=mp.Vector3(y=10.))) sim.run(until_after_sources=20) return mp.get_fluxes(tran1)[0], mp.get_fluxes(tran2)[0]
mp.Source(mp.GaussianSource(fcen, fwidth=0.1 * fcen, is_integrated=True), center=mp.Vector3(-0.5 * s + dpml), size=mp.Vector3(0, s), component=mp.Ez) ] symmetries = [mp.Mirror(mp.Y)] geometry = [ mp.Cylinder(material=SiO2, center=mp.Vector3(), radius=r, height=mp.inf) ] sim = mp.Simulation(resolution=resolution, cell_size=cell_size, boundary_layers=pml_layers, sources=sources, k_point=mp.Vector3(), symmetries=symmetries, geometry=geometry) dft_fields = sim.add_dft_fields([mp.Dz, mp.Ez], fcen, 0, 1, center=mp.Vector3(), size=mp.Vector3(2 * r, 2 * r), yee_grid=True) # closed box surrounding cylinder for computing total incoming flux flux_box = sim.add_flux( fcen, 0, 1,
def test_check_material_frequencies(self): mat = mp.Medium(valid_freq_range=mp.FreqRange(min=10, max=20)) invalid_sources = [ [mp.Source(mp.GaussianSource(5, fwidth=1), mp.Ez, mp.Vector3())], [ mp.Source(mp.ContinuousSource(10, fwidth=1), mp.Ez, mp.Vector3()) ], [mp.Source(mp.GaussianSource(10, width=1), mp.Ez, mp.Vector3())], [mp.Source(mp.GaussianSource(20, width=1), mp.Ez, mp.Vector3())], ] cell_size = mp.Vector3(5, 5) resolution = 5 def check_warnings(sim, should_warn=True): with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") sim.run(until=5) if should_warn: self.assertEqual(len(w), 1) self.assertIn("material", str(w[-1].message)) else: self.assertEqual(len(w), 0) geom = [mp.Sphere(0.2, material=mat)] for s in invalid_sources: # Check for invalid extra_materials sim = mp.Simulation(cell_size=cell_size, resolution=resolution, sources=s, extra_materials=[mat]) check_warnings(sim) # Check for invalid geometry materials sim = mp.Simulation(cell_size=cell_size, resolution=resolution, sources=s, geometry=geom) check_warnings(sim) valid_sources = [[ mp.Source(mp.GaussianSource(15, fwidth=1), mp.Ez, mp.Vector3()) ], [mp.Source(mp.ContinuousSource(15, width=5), mp.Ez, mp.Vector3())]] for s in valid_sources: sim = mp.Simulation(cell_size=cell_size, resolution=resolution, sources=s, extra_materials=[mat]) check_warnings(sim, False) # Check DFT frequencies # Invalid extra_materials sim = mp.Simulation(cell_size=cell_size, resolution=resolution, sources=valid_sources[0], extra_materials=[mat]) fregion = mp.FluxRegion(center=mp.Vector3(0, 1), size=mp.Vector3(2, 2), direction=mp.X) sim.add_flux(15, 6, 2, fregion) check_warnings(sim) # Invalid geometry material sim = mp.Simulation(cell_size=cell_size, resolution=resolution, sources=valid_sources[0], geometry=geom) sim.add_flux(15, 6, 2, fregion) check_warnings(sim)
cell = mp.Vector3(sx, sy, 0) blk = mp.Block(size=mp.Vector3(mp.inf, w, mp.inf), material=mp.Medium(epsilon=eps)) geometry = [blk] for i in range(3): geometry.append(mp.Cylinder(r, center=mp.Vector3(d / 2 + i))) for i in range(3): geometry.append(mp.Cylinder(r, center=mp.Vector3(d / -2 - i))) sim = mp.Simulation(cell_size=cell, geometry=geometry, sources=[], boundary_layers=[mp.PML(dpml)], resolution=20) # add sources sim.sources = [mp.Source(mp.GaussianSource(fcen, fwidth=df), mp.Hz, mp.Vector3())] # run until sources are finished (and no later) sim._run_sources_until(0, []) # get 1D and 2D array slices xMin = -0.25 * sx xMax = +0.25 * sx yMin = -0.15 * sy yMax = +0.15 * sy
mp.Block(material=glass, size=mp.Vector3(sr, 0, dpml + dsub), center=mp.Vector3(0.5 * sr, 0, -0.5 * sz + 0.5 * (dpml + dsub))) ] for n in range(zN - 1, -1, -1): geometry.append( mp.Block(material=glass if n % 2 == 0 else mp.vacuum, size=mp.Vector3(r[n], 0, zh), center=mp.Vector3(0.5 * r[n], 0, -0.5 * sz + dpml + dsub + 0.5 * zh))) sim = mp.Simulation(cell_size=cell_size, boundary_layers=pml_layers, resolution=resolution, sources=sources, geometry=geometry, dimensions=mp.CYLINDRICAL, m=-1) ## near-field monitor n2f_obj = sim.add_near2far( frq_cen, 0, 1, mp.Near2FarRegion(center=mp.Vector3(0.5 * (sr - dpml), 0, 0.5 * sz - dpml), size=mp.Vector3(sr - dpml)), mp.Near2FarRegion(center=mp.Vector3(sr - dpml, 0, 0.5 * sz - 0.5 * (dsub + zh + dpad)), size=mp.Vector3(z=dsub + zh + dpad))) sim.run(until_after_sources=100)
def test_mode_decomposition(self): resolution = 10 w1 = 1 w2 = 2 Lw = 2 dair = 3.0 dpml = 5.0 sy = dpml + dair + w2 + dair + dpml half_w1 = 0.5 * w1 half_w2 = 0.5 * w2 Si = mp.Medium(epsilon=12.0) boundary_layers = [mp.PML(dpml)] lcen = 6.67 fcen = 1 / lcen symmetries = [mp.Mirror(mp.Y)] Lt = 2 sx = dpml + Lw + Lt + Lw + dpml cell_size = mp.Vector3(sx, sy, 0) prism_x = sx + 1 half_Lt = 0.5 * Lt src_pt = mp.Vector3(-0.5 * sx + dpml + 0.2 * Lw, 0, 0) sources = [ mp.EigenModeSource(src=mp.GaussianSource(fcen, fwidth=0.2 * fcen), component=mp.Ez, center=src_pt, size=mp.Vector3(0, sy - 2 * dpml, 0), eig_match_freq=True, eig_parity=mp.ODD_Z + mp.EVEN_Y) ] vertices = [ mp.Vector3(-prism_x, half_w1), mp.Vector3(prism_x, half_w1), mp.Vector3(prism_x, -half_w1), mp.Vector3(-prism_x, -half_w1) ] sim = mp.Simulation( resolution=resolution, cell_size=cell_size, boundary_layers=boundary_layers, geometry=[mp.Prism(vertices, height=mp.inf, material=Si)], sources=sources, symmetries=symmetries) mon_pt = mp.Vector3(-0.5 * sx + dpml + 0.5 * Lw, 0, 0) flux = sim.add_flux( fcen, 0, 1, mp.FluxRegion(center=mon_pt, size=mp.Vector3(0, sy - 2 * dpml, 0))) sim.run(until_after_sources=mp.stop_when_fields_decayed( 50, mp.Ez, src_pt, 1e-9)) incident_coeffs, vgrp, kpoints = sim.get_eigenmode_coefficients( flux, [1], eig_parity=mp.ODD_Z + mp.EVEN_Y) incident_flux = mp.get_fluxes(flux) incident_flux_data = sim.get_flux_data(flux) sim.reset_meep() vertices = [ mp.Vector3(-prism_x, half_w1), mp.Vector3(-half_Lt, half_w1), mp.Vector3(half_Lt, half_w2), mp.Vector3(prism_x, half_w2), mp.Vector3(prism_x, -half_w2), mp.Vector3(half_Lt, -half_w2), mp.Vector3(-half_Lt, -half_w1), mp.Vector3(-prism_x, -half_w1) ] sim = mp.Simulation( resolution=resolution, cell_size=cell_size, boundary_layers=boundary_layers, geometry=[mp.Prism(vertices, height=mp.inf, material=Si)], sources=sources, symmetries=symmetries) refl_flux = sim.add_flux( fcen, 0, 1, mp.FluxRegion(center=mon_pt, size=mp.Vector3(0, sy - 2 * dpml, 0))) sim.load_minus_flux_data(refl_flux, incident_flux_data) sim.run(until_after_sources=mp.stop_when_fields_decayed( 50, mp.Ez, src_pt, 1e-9)) coeffs, vgrp, kpoints = sim.get_eigenmode_coefficients( refl_flux, [1], eig_parity=mp.ODD_Z + mp.EVEN_Y) taper_flux = mp.get_fluxes(refl_flux) self.assertAlmostEqual(abs(coeffs[0, 0, 1])**2 / abs(incident_coeffs[0, 0, 0])**2, -taper_flux[0] / incident_flux[0], places=4)
# glass substrate sources = [ mp.Source(mp.ContinuousSource(wavelength=0.450, end_time=20), component=mp.Ez, center=mp.Vector3(-3, 0)) ] firstfr = mp.FluxRegion(center=mp.Vector3(-2, 0, 0), size=mp.Vector3(0, 30)) secfr = mp.FluxRegion(center=mp.Vector3(4, 0, 0), size=mp.Vector3(0, 30)) sim = mp.Simulation(cell_size=cell, k_point=mp.Vector3(), default_material=mp.Medium(index=1.6), boundary_layers=pml_layers, geometry=[], sources=sources, resolution=resolution) before_block = sim.add_flux(1 / 0.450, 0.5, 5, firstfr) sim.plot2D(eps_parameters={"cmap": "brg"}, boundary_parameters={ 'hatch': 'o', 'linewidth': 1.5, 'facecolor': 'y', 'edgecolor': 'y', 'alpha': 0.7 })
mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Ez, center=mp.Vector3(src_pos, 0, 0), size=mp.Vector3(0, sy, 0)) ] k_point = mp.Vector3(0, 0, 0) glass = mp.Medium(index=1.5) symmetries = [mp.Mirror(mp.Y)] sim = mp.Simulation(resolution=resolution, cell_size=cell_size, boundary_layers=pml_layers, k_point=k_point, default_material=glass, sources=sources, symmetries=symmetries) nfreq = 21 xm = 0.5 * sx - dpml - 0.5 * dpad eig_mon = sim.add_flux( fcen, df, nfreq, mp.FluxRegion(center=mp.Vector3(xm, 0, 0), size=mp.Vector3(0, sy, 0))) sim.run(until_after_sources=mp.stop_when_fields_decayed( 50, mp.Ez, mp.Vector3(xm, 0, 0), 1e-9)) coeffs0, vgrps0, kpoints0 = sim.get_eigenmode_coefficients( eig_mon, [1], eig_parity=mp.ODD_Z + mp.EVEN_Y)
N0 = 37 # initial population density of ground state Rp = 0.0051 # pumping rate of ground to excited state # so for example, these parameters have D_0 (SALT) = 0.0693. # Make the actual medium in MEEP: transitions = [mp.Transition(1, 2, pumping_rate=Rp, frequency=freq_21, gamma=gamma_21, sigma_diag=mp.Vector3(sigma_21,0,0)), mp.Transition(2, 1, transition_rate=rate_21)] ml_atom = mp.MultilevelAtom(sigma=1, transitions=transitions, initial_populations=[N0]) two_level = mp.Medium(index=ncav, E_susceptibilities=[ml_atom]) # Specify the cavity geometry: geometry = [mp.Block(center=mp.Vector3(z=-0.5*sz+0.5*Lcav)), size=mp.Vector3(mp.inf,mp.inf,Lcav), material=two_level)] sim = mp.Simulation(cell_size=cell_size, resolution=resolution, boundary_layers=pml_layers, geometry=geometry, dimensions=dimensions) sim.init_sim() def field_func(p): return 1 if p.z==-0.5*sz + 0.5*Lcav else 0 sim.fields.initialize_field(mp.Ex, field_func) # Specify the end time: endt = 7000 # Note that the total number of time steps run is endt*resolution*2. This is the origin of the extra
def standard(metalens): metalens['run_date'] = int(time()) matter = mp.Medium(epsilon=metalens['epsilon']) pillar_locs = list( product( [-metalens['pillar_separation'], metalens['pillar_separation']], [-metalens['pillar_separation'], metalens['pillar_separation']])) pillar_locs.append((0, 0)) pillars = [ mp.Cylinder(radius=metalens['pillar_radius'], height=metalens['pillar_height'], center=mp.Vector3(x, y, 0), material=matter) for x, y in pillar_locs ] substrate = [ mp.Block(size=mp.Vector3(metalens['sim_cell_width'], metalens['sim_cell_width'], metalens['sim_cell_width'] / 2), center=mp.Vector3(0, 0, -metalens['sim_cell_width'] / 4), material=matter) ] geometry = substrate + pillars cell = mp.Vector3(metalens['sim_cell_width'], metalens['sim_cell_width'], metalens['sim_cell_width']) pml = [mp.PML(metalens['PML_width'])] source = [ mp.Source(src=mp.ContinuousSource(wavelength=metalens['wavelength']), component=mp.Ex, center=mp.Vector3(0, 0, -metalens['sim_cell_width'] / 4), size=mp.Vector3(0, 0, 0)) ] symmetries = [] for symmetry in metalens['symmetries']: if symmetry == 'x': symmetries.append(mp.Mirror(mp.X)) if symmetry == 'y': symmetries.append(mp.Mirror(mp.Y)) sim = mp.Simulation(cell_size=cell, boundary_layers=pml, geometry=geometry, force_complex_fields=metalens['complex_fields'], symmetries=symmetries, sources=source, resolution=metalens['resolution']) start_time = time() mp.quiet(metalens['quiet']) # mp.verbosity(3) sim.init_sim() metalens['time_for_init'] = (time() - start_time) start_time = time() #sim.run(mp.at_end(mp.output_efield(sim)),until=metalens['sim_time']) sim.run(until=metalens['sim_time']) metalens['time_for_running'] = time() - start_time start_time = time() sim.filename_prefix = 'standard_candle-%d' % metalens['run_date'] print(sim.filename_prefix) mp.output_efield(sim) mp.output_hfield(sim) # print("collecting fields...") # h5_fname = 'candle-{run_date}.h5'.format(run_date = metalens['run_date']) # if metalens['save_fields_to_h5'] and rank ==0:#(not os.path.exists(h5_fname)): # metalens['h5_fname'] = h5_fname # h5_file = h5py.File(h5_fname,'w', driver='mpio', comm=MPI.COMM_WORLD) # fields = h5_file.create_group('fields') # Ex = np.transpose(sim.get_array(component=mp.Ex),(2,1,0)) # metalens['voxels'] = Ex.shape[0]**3 # metalens['voxels'] = Ex.shape[0]**3 # metalens['above_pillar_index'] = int(Ex.shape[0]/2. + 3*metalens['pillar_height']*metalens['resolution']/2) # mp.output_efield('test') # fields.create_dataset('Ex', # data=Ex) # del Ex # fields.create_dataset('Ey', # data=np.transpose(sim.get_array(component=mp.Ey),(2,1,0))) # fields.create_dataset('Ez', # data=np.transpose(sim.get_array(component=mp.Ez),(2,1,0))) # fields.create_dataset('Hx', # data=np.transpose(sim.get_array(component=mp.Hx),(2,1,0))) # fields.create_dataset('Hy', # data=np.transpose(sim.get_array(component=mp.Hy),(2,1,0))) # fields.create_dataset('Hz', # data=np.transpose(sim.get_array(component=mp.Hz),(2,1,0))) # h5_file.close() # else: # metalens['fields'] = { # 'Ex': np.transpose(sim.get_array(component=mp.Ex),(2,1,0)), # 'Ey': np.transpose(sim.get_array(component=mp.Ey),(2,1,0)), # 'Ez': np.transpose(sim.get_array(component=mp.Ez),(2,1,0)), # 'Hx': np.transpose(sim.get_array(component=mp.Hx),(2,1,0)), # 'Hy': np.transpose(sim.get_array(component=mp.Hy),(2,1,0)), # 'Hz': np.transpose(sim.get_array(component=mp.Hz),(2,1,0)) # } # metalens['voxels'] = metalens['fields']['Ex'].shape[0]**3 # metalens['above_pillar_index'] = int(metalens['fields']['Ex'].shape[0]/2. + 3*metalens['pillar_height']*metalens['resolution']/2) metalens['voxels'] = int((8 * metalens['resolution'])**3) metalens['time_for_saving_fields'] = round(time() - start_time, 0) metalens['max_mem_usage_in_Gb'] = metalens[ 'num_cores'] * resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1E6 metalens['max_mem_usage_in_Gb'] = round(metalens['max_mem_usage_in_Gb'], 2) metalens['summary'] = '''init time = {time_for_init:.1f} s running simulation = {time_for_running:.1f} s saving fields = {time_for_saving_fields:.1f} s num voxels = {voxels} max memory usage = {max_mem_usage_in_Gb:.2f} Gb'''.format(**metalens) metalens['pkl_fname'] = 'standard-candle-%d.pkl' % metalens['run_date'] return metalens