def test_update_band_range_data(self): brd = [] freqs = [ 0.0, 1.0000000001231053, 1.0000000001577114, 1.000000000183077, 1.0000000003647922, 1.4142135627385737, 1.4142135630373556, 1.4142135634172286 ] kpoint = mp.Vector3() expected = [ ((0.0, mp.Vector3()), (0.0, mp.Vector3())), ((1.0000000001231053, mp.Vector3()), (1.0000000001231053, mp.Vector3())), ((1.0000000001577114, mp.Vector3()), (1.0000000001577114, mp.Vector3())), ((1.000000000183077, mp.Vector3()), (1.000000000183077, mp.Vector3())), ((1.0000000003647922, mp.Vector3()), (1.0000000003647922, mp.Vector3())), ((1.4142135627385737, mp.Vector3()), (1.4142135627385737, mp.Vector3())), ((1.4142135630373556, mp.Vector3()), (1.4142135630373556, mp.Vector3())), ((1.4142135634172286, mp.Vector3()), (1.4142135634172286, mp.Vector3())), ] ms = mpb.ModeSolver() res = ms.update_band_range_data(brd, freqs, kpoint) self.check_band_range_data(expected, res)
def parallel_waveguide(s, yodd): geometry = [ mp.Block(center=mp.Vector3(0, -0.5 * (s + a), 0), size=mp.Vector3(mp.inf, a, a), material=Si), mp.Block(center=mp.Vector3(0, 0.5 * (s + a), 0), size=mp.Vector3(mp.inf, a, a), material=Si) ] ms = mpb.ModeSolver(resolution=resolution, k_points=k_points, geometry_lattice=geometry_lattice, geometry=geometry, num_bands=num_bands, tolerance=tolerance) if yodd: ms.run_yodd_zodd() else: ms.run_yeven_zodd() f = ms.get_freqs()[0] vg = ms.compute_group_velocity_component(mp.Vector3(1, 0, 0))[0] return f, vg
def test_list_split(self): k_points = [ mp.Vector3(), mp.Vector3(0.5), mp.Vector3(0.5, 0.5), mp.Vector3() ] k_points = mp.interpolate(4, k_points) ms = mpb.ModeSolver() k_split = ms.list_split(k_points, 1, 0) expected_list = [ mp.Vector3(), mp.Vector3(0.10000000000000003), mp.Vector3(0.20000000000000004), mp.Vector3(0.30000000000000004), mp.Vector3(0.4), mp.Vector3(0.5), mp.Vector3(0.5, 0.10000000000000003), mp.Vector3(0.5, 0.20000000000000004), mp.Vector3(0.5, 0.30000000000000004), mp.Vector3(0.5, 0.4), mp.Vector3(0.5, 0.5), mp.Vector3(0.4, 0.4), mp.Vector3(0.30000000000000004, 0.30000000000000004), mp.Vector3(0.2, 0.2), mp.Vector3(0.1, 0.1), mp.Vector3(0.0, 0.0), ] self.assertEqual(k_split[0], 0) for res, exp in zip(k_split[1], expected_list): self.assertTrue(res.close(exp))
def get_freqs_interpolate(hx=0.24, hy=0.24, a=0.33, wy=0.7, h=0.22): ''' Useless ''' import meep as mp from meep import mpb mode = "zEyO" resolution = 20 # pixels/a, taken from simpetus example a = round(a, 3) # units of um h = round(h, 3) # units of um w = round(wy, 3) # units of um hx = round(hx, 3) hy = round(hy, 3) h = h / a # units of "a" w = w / a # units of "a" hx = hx / a # units of "a" hy = hy / a # units of "a" nSi = 3.45 Si = mp.Medium(index=nSi) geometry_lattice = mp.Lattice(size=mp.Vector3( 1, 4, 4)) # dimensions of lattice taken from simpetus example geometry = [ mp.Block(center=mp.Vector3(), size=mp.Vector3(mp.inf, w, h), material=Si), mp.Ellipsoid(material=mp.air, center=mp.Vector3(), size=mp.Vector3(hx, hy, mp.inf)) ] num_k = 20 # from simpetus example, no. of k_points to evaluate the eigen frequency at k_points = mp.interpolate( num_k, [mp.Vector3(0, 0, 0), mp.Vector3(0.5, 0, 0)]) num_bands = 2 # from simpetus example ms = mpb.ModeSolver(geometry_lattice=geometry_lattice, geometry=geometry, k_points=k_points, resolution=resolution, num_bands=num_bands) if mode == "te": ms.run_te() # running for all modes and extracting parities if mode == "zEyO": ms.run_yodd_zeven() return ms.freqs
def get_ms(geom = None, k_points=[0,1], num_bands=1): if geom is None: geom = get_xs() ms = mpb.ModeSolver(geometry_lattice=geometry_lattice, geometry=geom, k_points=k_points, resolution=resolution, num_bands=num_bands) return ms
def get_freqs(hx=0.24, hy=0.24, a=0.33, w=0.7, h=0.22): ''' Returns tuple of dielectric and air band edge frequencies for input parameters ''' import meep as mp from meep import mpb res = 20 mode = "zEyO" resolution = res # pixels/a, taken from simpetus example a = round(a, 3) # units of um h = round(h, 3) # units of um w = round(w, 3) # units of um hx = round(hx, 3) hy = round(hy, 3) h = h / a # units of "a" w = w / a # units of "a" hx = hx / a # units of "a" hy = hy / a # units of "a" nSi = 3.45 Si = mp.Medium(index=nSi) geometry_lattice = mp.Lattice(size=mp.Vector3( 1, 4, 4)) # dimensions of lattice taken from simpetus example geometry = [ mp.Block(center=mp.Vector3(), size=mp.Vector3(mp.inf, w, h), material=Si), mp.Ellipsoid(material=mp.air, center=mp.Vector3(), size=mp.Vector3(hx, hy, mp.inf)) ] k_points = [mp.Vector3(0.5, 0, 0)] num_bands = 2 # from simpetus example ms = mpb.ModeSolver(geometry_lattice=geometry_lattice, geometry=geometry, k_points=k_points, resolution=resolution, num_bands=num_bands) if mode == "te": ms.run_te() # running for all modes and extracting parities if mode == "zEyO": ms.run_yodd_zeven() return ms.freqs
def get_freqs(hx, hy, a, w): wz = 0.22 res = 20 mode = "zEyO" resolution = res # pixels/a, taken from simpetus example # a = round(a,3) # units of um # h = round(wz, 3) # units of um # w = round(wy, 3) # units of um # hx = round(hx, 3) # hy = round(hy, 3) h = wz h = h / a # units of "a" w = w / a # units of "a" hx = hx / a # units of "a" hy = hy / a # units of "a" nSi = 3.45 Si = mp.Medium(index=nSi) geometry_lattice = mp.Lattice(size=mp.Vector3( 1, 4, 4)) # dimensions of lattice taken from simpetus example geometry = [ mp.Block(center=mp.Vector3(), size=mp.Vector3(mp.inf, w, h), material=Si), mp.Ellipsoid(material=mp.air, center=mp.Vector3(), size=mp.Vector3(hx, hy, mp.inf)) ] k_points = [mp.Vector3(0.5, 0, 0)] num_bands = 2 # from simpetus example ms = mpb.ModeSolver(geometry_lattice=geometry_lattice, geometry=geometry, k_points=k_points, resolution=resolution, num_bands=num_bands) if mode == "te": ms.run_te() # running for all modes and extracting parities if mode == "zEyO": ms.run_yodd_zeven() return ms.freqs
def example_case(): num_bands = 3 resolution = 32 k_point = [ mp.Vector3(), mp.Vector3(0.5), mp.Vector3(0.5, 0.5), mp.Vector3() ] k_points = mp.interpolate(40, k_point) geometry = [mp.Cylinder(0.2, material=mp.Medium(epsilon=12))] geometry_lattice = mp.Lattice(size=mp.Vector3(1, 1)) ms = mpb.ModeSolver(num_bands=num_bands, k_points=k_points, geometry=geometry, geometry_lattice=geometry_lattice, resolution=resolution) ms.run_te() return ms
def init_solver(self, geom=True): num_bands = 8 k_points = [ mp.Vector3(), mp.Vector3(0.5), mp.Vector3(0.5, 0.5), mp.Vector3() ] geometry = [mp.Cylinder(0.2, material=mp.Medium( epsilon=12))] if geom else [] k_points = mp.interpolate(4, k_points) geometry_lattice = mp.Lattice(size=mp.Vector3(1, 1)) resolution = 32 return mpb.ModeSolver(num_bands=num_bands, k_points=k_points, geometry=geometry, geometry_lattice=geometry_lattice, resolution=resolution, filename_prefix=self.filename_prefix, deterministic=True, tolerance=1e-12)
# geometry = [mp.Cylinder(, center = mp.Vector3( 1/3, 1/3), material=mp.Medium(epsilon=1)), # mp.Cylinder(radius = 0.001*int(sys.argv[1]), center = mp.Vector3( 1/3, 0), material=mp.Medium(epsilon=1)), # mp.Cylinder(radius = 0.001*int(sys.argv[1]), center = mp.Vector3( 0,-1/3), material=mp.Medium(epsilon=1)), # mp.Cylinder(radius = 0.001*int(sys.argv[1]), center = mp.Vector3(-1/3,-1/3), material=mp.Medium(epsilon=1)), # mp.Cylinder(radius = 0.001*int(sys.argv[1]), center = mp.Vector3(-1/3, 0), material=mp.Medium(epsilon=1)), # mp.Cylinder(radius = 0.001*int(sys.argv[1]), center = mp.Vector3( 0, 1/3), material=mp.Medium(epsilon=1)), # mp.Cylinder(radius = 0.001*int(sys.argv[2]), center = mp.Vector3( 0, 0), material=mp.Medium(epsilon=(0.001*int(sys.argv[4]))**2))] geometry_lattice = mp.Lattice(size=mp.Vector3(1, 1), basis1=mp.Vector3(0.5, 3**0.5 / 2), basis2=mp.Vector3(0.5, -3**0.5 / 2)) ms = mpb.ModeSolver(num_bands=num_bands, k_points=k_points, geometry_lattice=geometry_lattice, geometry=geometry, resolution=resolution, default_material=mp.Medium(epsilon=(0.001 * int(sys.argv[3]))**2)) ms.run_te() md = mpb.MPBData(rectify=True, periods=2, resolution=128) eps = ms.get_epsilon() converted_eps = md.convert(eps) plt.figure() plt.imshow(converted_eps, interpolation='spline36', cmap='binary') plt.colorbar() # try: # os.mkdir('./figures/super_cell/'+'r_air_'+str(0.001*int(sys.argv[1]))[:5]+'r_center_'+str(0.001*int(sys.argv[2]))[:5]+'n_center_'+str(0.001*int(sys.argv[4]))[:5]+'n_back_'+str(0.001*int(sys.argv[3]))[:5])
# This is periodic, and also has inversion symmetry. def eps_func(p): return mp.Medium(index=index_min + 0.5 * (index_max - index_min) * (1 + math.cos(2 * math.pi * p.x))) geometry_lattice = mp.Lattice(size=mp.Vector3(1)) # 1d cell # We'll just make it the default material, so that it goes everywhere. default_material = eps_func k_points = mp.interpolate(9, [mp.Vector3(), mp.Vector3(x=0.5)]) resolution = 32 num_bands = 8 ms = mpb.ModeSolver(num_bands=num_bands, k_points=k_points, geometry_lattice=geometry_lattice, resolution=resolution, default_material=default_material) def main(): # the TM and TE bands are degenerate, so we only need TM: ms.run_tm() if __name__ == '__main__': main()
def get_mode_solver_coupler( wg_width: float = 0.5, gap: float = 0.2, wg_widths: Optional[Floats] = None, gaps: Optional[Floats] = None, wg_thickness: float = 0.22, slab_thickness: float = 0.0, ncore: float = 3.47, nclad: float = 1.44, nslab: Optional[float] = None, ymargin: float = 2.0, sz: float = 2.0, resolution: int = 32, nmodes: int = 4, sidewall_angles: Union[Tuple[float, ...], float] = None, # sidewall_taper: int = 1, ) -> mpb.ModeSolver: """Returns a mode_solver simulation. Args: wg_width: wg_width (um) gap: wg_widths: list or tuple of waveguide widths. gaps: list or tuple of waveguide gaps. wg_thickness: wg height (um) slab_thickness: thickness for the waveguide slab ncore: core material refractive index nclad: clad material refractive index nslab: Optional slab material refractive index. Defaults to ncore. ymargin: margin in y. sz: simulation region thickness (um) resolution: resolution (pixels/um) nmodes: number of modes sidewall_angles: waveguide sidewall angle (radians), tapers from wg_width at top of slab, upwards, to top of waveguide :: _____________________________________________________ | | | widths[0] widths[1] | <----------> gaps[0] <----------> | ___________ <-------------> ___________ _ | | | | | | sz|_____| |_______________| |_____| | | wg_thickness |slab_thickness | |___________________________________________________| | |<---> <---> |ymargin ymargin |____________________________________________________ <---------------------------------------------------> sy """ wg_widths = wg_widths or (wg_width, wg_width) gaps = gaps or (gap, ) material_core = mp.Medium(index=ncore) material_clad = mp.Medium(index=nclad) material_slab = mp.Medium(index=nslab or ncore) # Define the computational cell. We'll make x the propagation direction. # the other cell sizes should be big enough so that the boundaries are # far away from the mode field. sy = np.sum(wg_widths) + np.sum(gaps) + 2 * ymargin geometry_lattice = mp.Lattice(size=mp.Vector3(0, sy, sz)) geometry = [] y = -sy / 2 + ymargin gaps = list(gaps) + [0] for i, wg_width in enumerate(wg_widths): if sidewall_angles: geometry.append( mp.Prism( vertices=[ mp.Vector3(y=y, z=slab_thickness), mp.Vector3(y=y + wg_width, z=slab_thickness), mp.Vector3(x=1, y=y + wg_width, z=slab_thickness), mp.Vector3(x=1, y=y, z=slab_thickness), ], height=wg_thickness - slab_thickness, center=mp.Vector3( y=y + wg_width / 2, z=slab_thickness + (wg_thickness - slab_thickness) / 2, ), # If only 1 angle is specified, use it for all waveguides sidewall_angle=sidewall_angles if len( np.unique(sidewall_angles)) == 1 else sidewall_angles[i], # axis=mp.Vector3(z=sidewall_taper), material=material_core, )) else: geometry.append( mp.Block( size=mp.Vector3(mp.inf, wg_width, wg_thickness), material=material_core, center=mp.Vector3(y=y + wg_width / 2, z=wg_thickness / 2), )) y += gaps[i] + wg_width # define the 2D blocks for the strip and substrate geometry += [ mp.Block( size=mp.Vector3(mp.inf, mp.inf, slab_thickness), material=material_slab, center=mp.Vector3(z=slab_thickness / 2), ), ] # The k (i.e. beta, i.e. propagation constant) points to look at, in # units of 2*pi/um. We'll look at num_k points from k_min to k_max. num_k = 9 k_min = 0.1 k_max = 3.0 k_points = mp.interpolate(num_k, [mp.Vector3(k_min), mp.Vector3(k_max)]) # Increase this to see more modes. (The guided ones are the ones below the # light line, i.e. those with frequencies < kmag / 1.45, where kmag # is the corresponding column in the output if you grep for "freqs:".) # use this prefix for output files wg_widths_str = "_".join([str(i) for i in wg_widths]) gaps_str = "_".join([str(i) for i in gaps]) filename_prefix = ( tmp / f"coupler_{wg_widths_str}_{gaps_str}_{wg_thickness}_{slab_thickness}") mode_solver = mpb.ModeSolver( geometry_lattice=geometry_lattice, geometry=geometry, k_points=k_points, resolution=resolution, num_bands=nmodes, filename_prefix=str(filename_prefix), default_material=material_clad, ) mode_solver.nmodes = nmodes mode_solver.info = dict( wg_widths=wg_widths, gaps=gaps, wg_thickness=wg_thickness, slab_thickness=slab_thickness, ncore=ncore, nclad=nclad, sy=sy, sz=sz, resolution=resolution, nmodes=nmodes, ) return mode_solver
def get_freqs(hx, hy, a, w, h=0.22, substrate=False, output_epsilon=False, mode="zEyO", num_bands=2): # h = 0.23 # for manually setting waveguide height res = 20 #mode = "zEyO" resolution = res # pixels/a, taken from simpetus example print(" h = " + str(h) + ", SUBSTRATE = " + str(substrate) + ", mode = " + str(mode)) a = round(a, 3) # units of um h = round(h, 3) # units of um w = round(w, 3) # units of um hx = round(hx, 3) hy = round(hy, 3) h = h / a # units of "a" w = w / a # units of "a" hx = hx / a # units of "a" hy = hy / a # units of "a" cell_x = 1 cell_y = 4 cell_z = 4 nSi = 3.45 Si = mp.Medium(index=nSi) geometry_lattice = mp.Lattice(size=mp.Vector3( cell_x, cell_y, cell_z)) # dimensions of lattice taken from simpetus example geometry = [ mp.Block(center=mp.Vector3(), size=mp.Vector3(mp.inf, w, h), material=Si), mp.Ellipsoid(material=mp.air, center=mp.Vector3(), size=mp.Vector3(hx, hy, mp.inf)) ] if substrate: geometry = add_substrate(geom=geometry, waveguide_height=h, substrate_height=cell_z / 2 - h / 2) # substrate height normalized with a k_points = [mp.Vector3(0.5, 0, 0)] num_bands = num_bands ms = mpb.ModeSolver(geometry_lattice=geometry_lattice, geometry=geometry, k_points=k_points, resolution=resolution, num_bands=num_bands) if mode == "te": ms.run_te() # running for all modes and extracting parities if mode == "zEyO": ms.run_yodd_zeven() if mode == "yO": ms.run_yodd() if mode == "yE": ms.run_yeven() # if output_epsilon: # visualise_geometry(ms = ms, x = None , y = None, z = (4 * res)/ 2, value = None) if output_epsilon: return ms.get_epsilon() # with h5py.File('epsilon.hdf5', 'w') as f: # arr = ms.get_epsilon # dset = f.create_dataset("epsilon", data = arr) return ms.freqs
for j in range(0, nbr_points_y + 2): k_point_gamma_dk_cart = k_point_gamma + mp.Vector3(0, j * dk_y) k_point_K_dk_cart = k_point_K_cart + mp.Vector3(0, j * dk_y) k_point_gamma_dk_rec = mp.cartesian_to_reciprocal(k_point_gamma_dk_cart, geometry_lattice) k_point_K_dk_rec = mp.cartesian_to_reciprocal(k_point_K_dk_cart, geometry_lattice) seg_temp = mp.interpolate(nbr_points_x, [k_point_gamma_dk_rec, k_point_K_dk_rec]) seg = seg + seg_temp def outputgv(ms): global gv gv.append(ms.compute_group_velocities()) gv = [] ms = mpb.ModeSolver() ms.geometry = C_0 ms.geometry_lattice = geometry_lattice ms.resolution = resolution ms.num_bands = Nbands ms.k_points = seg ms.default_material = default_material ms.run_te(outputgv) ms.output_epsilon() te_freqs = ms.all_freqs
k_max = 3.0 k_points = mp.interpolate(num_k, [mp.Vector3(k_min), mp.Vector3(k_max)]) resolution = 32 # pixels/um # Increase this to see more modes. (The guided ones are the ones below the # light line, i.e. those with frequencies < kmag / 1.45, where kmag # is the corresponding column in the output if you grep for "freqs:".) num_bands = 4 filename_prefix = 'strip-' # use this prefix for output files ms = mpb.ModeSolver( geometry_lattice=geometry_lattice, geometry=geometry, k_points=k_points, resolution=resolution, num_bands=num_bands, filename_prefix=filename_prefix ) def main(): # compute num_bands lowest frequencies as a function of k. Also display # "parities", i.e. whether the mode is symmetric or anti_symmetric # through the y=0 and z=0 planes. ms.run(mpb.display_yparities, mpb.display_zparities) ########################################################################### # Above, we outputted the dispersion relation: frequency (omega) as a # function of wavevector kx (beta). Alternatively, you can compute
print("Target frequency = ", str(target) + " THz") print() change = input("Do you want to change any of the parameters? Type 'y' or 'n': ") while change != 'y' and change != 'n': change = input("Do you want to change any of the parameters? Type 'y' or 'n': ") freqss = [] gapss = [] for index in integer_list: # Loop over kz_list theta_list = [] theta2_list = [] geometry = [] geometry_lattice = mp.Lattice(size=mp.Vector3(1, 1)) ms = mpb.ModeSolver(num_bands=num_bands, k_points=k_vectors[index], geometry=geometry, geometry_lattice=geometry_lattice, resolution=resolution) # Create ModeSolver object ms.default_material = mp.Medium(epsilon = pc_epsilon) # Define background material to be that of the photonic crystal if question == 'y': ms.target_freq = omega_prime ms.geometry_lattice = mp.Lattice(size=mp.Vector3(L, L)) # Creates an L x L lattice ms.geometry = [mp.Block(material=mp.air, size=mp.Vector3(r,r,mp.inf))] # One hole at each lattice point ms.geometry = mp.geometric_objects_lattice_duplicates(ms.geometry_lattice, ms.geometry) # Duplicate geometry all over the lattice if block == 'y': ms.geometry.append(mp.Block(material=mp.Medium(epsilon=core_epsilon), size=mp.Vector3(l_core, l_core, mp.inf))) # Inserts core into the center of the photonic crystal ms.run() freqs = ms.all_freqs freqss.append(freqs)
def get_mode_solver_rib( wg_width: float = 0.45, wg_thickness: float = 0.22, slab_thickness: int = 0.0, ncore: float = 3.47, nclad: float = 1.44, sy: float = 2.0, sz: float = 2.0, res: int = 32, nmodes: int = 4, ) -> mpb.ModeSolver: """Returns a mode_solver simulation. Args: wg_width: wg_width (um) wg_thickness: wg height (um) slab_thickness: thickness for the waveguide slab ncore: core material refractive index nclad: clad material refractive index sy: simulation region width (um) sz: simulation region height (um) res: resolution (pixels/um) nmodes: number of modes """ material_core = mp.Medium(index=ncore) material_clad = mp.Medium(index=nclad) # Define the computational cell. We'll make x the propagation direction. # the other cell sizes should be big enough so that the boundaries are # far away from the mode field. geometry_lattice = mp.Lattice(size=mp.Vector3(0, sy, sz)) # define the 2d blocks for the strip and substrate geometry = [ mp.Block( size=mp.Vector3(mp.inf, mp.inf, mp.inf), material=material_clad, ), # uncomment this for air cladded waveguides # mp.Block( # size=mp.Vector3(mp.inf, mp.inf, 0.5 * (sz - wg_thickness)), # center=mp.Vector3(z=0.25 * (sz + wg_thickness)), # material=material_clad, # ), mp.Block( size=mp.Vector3(mp.inf, mp.inf, slab_thickness), material=material_core, center=mp.Vector3(z=-0.5 * slab_thickness), ), mp.Block( size=mp.Vector3(mp.inf, wg_width, wg_thickness), material=material_core, center=mp.Vector3(z=0), ), ] # The k (i.e. beta, i.e. propagation constant) points to look at, in # units of 2*pi/um. We'll look at num_k points from k_min to k_max. num_k = 9 k_min = 0.1 k_max = 3.0 k_points = mp.interpolate(num_k, [mp.Vector3(k_min), mp.Vector3(k_max)]) # Increase this to see more modes. (The guided ones are the ones below the # light line, i.e. those with frequencies < kmag / 1.45, where kmag # is the corresponding column in the output if you grep for "freqs:".) # use this prefix for output files filename_prefix = tmp / f"rib_{wg_width}_{wg_thickness}_{slab_thickness}" mode_solver = mpb.ModeSolver( geometry_lattice=geometry_lattice, geometry=geometry, k_points=k_points, resolution=res, num_bands=nmodes, filename_prefix=str(filename_prefix), ) mode_solver.nmodes = nmodes return mode_solver
diel = mp.Medium(epsilon=eps) # A diamond lattice has two "atoms" per unit cell: geometry = [ mp.Sphere(r, center=mp.Vector3(0.125, 0.125, 0.125), material=diel), mp.Sphere(r, center=mp.Vector3(-0.125, -0.125, -0.125), material=diel) ] # (A simple fcc lattice would have only one sphere/object at the origin.) resolution = 16 # use a 16x16x16 grid mesh_size = 5 num_bands = 5 ms = mpb.ModeSolver(geometry_lattice=geometry_lattice, k_points=k_points, geometry=geometry, resolution=resolution, num_bands=num_bands, mesh_size=mesh_size) def main(): # run calculation, outputting electric_field energy density at the U point: ms.run(mpb.output_at_kpoint(mp.Vector3(0, 0.625, 0.375), mpb.output_dpwr)) if __name__ == '__main__': main()
k_max = 3.0 k_points = mp.interpolate(num_k, [mp.Vector3(k_min), mp.Vector3(k_max)]) k_points = [mp.Vector3(1 / 1.55)] resolution = 64 # pixels/um # Increase this to see more modes. (The guided ones are the ones below the # light line, i.e. those with frequencies < kmag / 1.45, where kmag # is the corresponding column in the output if you grep for "freqs:".) filename_prefix = 'strip-' # use this prefix for output files ms = mpb.ModeSolver( geometry_lattice=geometry_lattice, geometry=geometry, resolution=resolution, filename_prefix=filename_prefix, default_material=SiO2, ) # compute num_bands lowest frequencies as a function of k. Also display # "parities", i.e. whether the mode is symmetric or anti_symmetric # through the y=0 and z=0 planes. #ms.run() # Output the x component of the Poynting vector for num_bands bands at omega num_bands = 1 efields = [] def addField(tr_ms, band):
#diel = mp.Medium(epsilon=eps) # A diamond lattice has two "atoms" per unit cell: #geometry = [mp.Sphere(r, center=mp.Vector3(0.125, 0.125, 0.125), material=diel), # mp.Sphere(r, center=mp.Vector3(-0.125, -0.125, -0.125), material=diel)] # (A simple fcc lattice would have only one sphere/object at the origin.) resolution = 16 # use a 16x16x16 grid mesh_size = 5 num_bands = 6 ms = mpb.ModeSolver( geometry_lattice=geometry_lattice, k_points=k_points, # geometry=geometry, resolution=resolution, num_bands=num_bands, mesh_size=mesh_size, epsilon_input_file='epsilon.h5') def main(): # run calculation, outputting electric_field energy density at the U point: #ms.run(mpb.output_at_kpoint(mp.Vector3(0, 0.625, 0.375), mpb.output_dpwr)) ms.run() ## get epsilon #md = mpb.MPBData(rectify=True, periods=3, resolution=32) #eps = ms.get_epsilon() #converted_eps = md.convert(eps) import matplotlib
def main(args): """ Args: * **res** (int): Resolution of the simulation [pixels/um] (default=10) * **wavelength** (float): Wavelength in microns (default=1.55) * **sx** (float): Size of the simulation region in the x-direction (default=4.0) * **sy** (float): Size of the simulation region in the y-direction (default=4.0) * **plot_mode_number** (int): Which mode to plot (only plots one mode at a time). Must be a number equal to or less than num_mode (default=1) * **polarization** (string): If true, outputs the fields at the relevant waveguide cross-sections (top-down and side-view) * **epsilon_file** (string): Filename with the dielectric "block" objects (default=None) * **output_directory** (string): If true, outputs the fields at the relevant waveguide cross-sections (top-down and side-view) * **save_mode_data** (boolean): Save the mode image and data to a separate file (default=None) * **suppress_window** (boolean): Suppress the matplotlib window (default=False) """ #Boolean inputs save_mode_data = args.save_mode_data suppress_window = args.suppress_window #String inputs polarization = args.polarization epsilon_file = args.epsilon_file output_directory = args.output_directory if not os.path.exists(output_directory): os.makedirs(output_directory) #Int inputs res = args.res # num_modes = args.num_modes plot_mode_number = args.plot_mode_number #Float inputs wavelength = args.wavelength sx = args.sx sy = args.sy geometry_lattice = mp.Lattice(size=mp.Vector3(0, sy, sx)) with h5py.File(epsilon_file, 'r') as hf: data = np.array([ np.array(hf.get("CX")), np.array(hf.get("CY")), np.array(hf.get("width_list")), np.array(hf.get("height_list")), np.array(hf.get("eps_list")) ]) geometry = [] for i in range(len(data[0])): geometry.append( mp.Block(size=mp.Vector3(mp.inf, data[3][i], data[2][i]), center=mp.Vector3(0, data[1][i], data[0][i]), material=mp.Medium(epsilon=data[4][i]))) ms = mpb.ModeSolver(geometry_lattice=geometry_lattice, geometry=geometry, resolution=res, default_material=mp.Medium(epsilon=1.0), num_bands=plot_mode_number) freq = 1 / wavelength kdir = mp.Vector3(1, 0, 0) tol = 1e-6 kmag_guess = freq * 2.02 kmag_min = freq * 0.01 kmag_max = freq * 10.0 if polarization == "TE": parity = mp.ODD_Z elif polarization == "TM": parity = mp.EVEN_Z elif polarization == "None": parity = mp.NO_PARITY k = ms.find_k(parity, freq, plot_mode_number, plot_mode_number, kdir, tol, kmag_guess, kmag_min, kmag_max) vg = ms.compute_group_velocities() print('k=' + str(k)) print('v_g=' + str(vg)) k = k[0] vg = vg[0][0] """ Plot modes """ eps = ms.get_epsilon() ms.get_dfield(plot_mode_number) E = ms.get_efield(plot_mode_number) Eabs = np.sqrt( np.multiply(E[:, :, 0, 2], E[:, :, 0, 2]) + np.multiply(E[:, :, 0, 1], E[:, :, 0, 1]) + np.multiply(E[:, :, 0, 0], E[:, :, 0, 0])) H = ms.get_hfield(plot_mode_number) Habs = np.sqrt( np.multiply(H[:, :, 0, 2], H[:, :, 0, 2]) + np.multiply(H[:, :, 0, 1], H[:, :, 0, 1]) + np.multiply(H[:, :, 0, 0], H[:, :, 0, 0])) plt_extent = [-sy / 2.0, +sy / 2.0, -sx / 2.0, +sx / 2.0] cmap_fields = 'hot_r' cmap_geom = 'viridis' if not suppress_window: """ First plot electric field """ plt.figure(figsize=(14, 8)) plt.subplot(2, 3, 1) plt.imshow(abs(E[:, :, 0, 2]), cmap=cmap_fields, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide mode $|E_x|$") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.subplot(2, 3, 2) plt.imshow(abs(E[:, :, 0, 1]), cmap=cmap_fields, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide mode $|E_y|$") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.subplot(2, 3, 3) plt.imshow(abs(E[:, :, 0, 0]), cmap=cmap_fields, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide mode $|E_z|$") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.subplot(2, 3, 4) plt.imshow(abs(Eabs), cmap=cmap_fields, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide mode $|E|$") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.subplot(2, 3, 5) plt.imshow(eps, cmap=cmap_geom, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide dielectric") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.tight_layout() plt.show() """ Then plot magnetic field """ plt.figure(figsize=(14, 8)) plt.subplot(2, 3, 1) plt.imshow(abs(H[:, :, 0, 2]), cmap=cmap_fields, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide mode $|H_x|$") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.subplot(2, 3, 2) plt.imshow(abs(H[:, :, 0, 1]), cmap=cmap_fields, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide mode $|H_y|$") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.subplot(2, 3, 3) plt.imshow(abs(H[:, :, 0, 0]), cmap=cmap_fields, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide mode $|H_z|$") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.subplot(2, 3, 4) plt.imshow(abs(Habs), cmap=cmap_fields, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide mode $|H|$") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.subplot(2, 3, 5) plt.imshow(eps, cmap=cmap_geom, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide dielectric") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.tight_layout() plt.show() if save_mode_data: """ First plot electric field """ plt.figure(figsize=(14, 8)) plt.subplot(2, 3, 1) plt.imshow(abs(E[:, :, 0, 2]), cmap=cmap_fields, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide mode $|E_x|$") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.subplot(2, 3, 2) plt.imshow(abs(E[:, :, 0, 1]), cmap=cmap_fields, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide mode $|E_y|$") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.subplot(2, 3, 3) plt.imshow(abs(E[:, :, 0, 0]), cmap=cmap_fields, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide mode $|E_z|$") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.subplot(2, 3, 4) plt.imshow(abs(Eabs), cmap=cmap_fields, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide mode $|E|$") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.subplot(2, 3, 5) plt.imshow(eps, cmap=cmap_geom, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide dielectric") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.tight_layout() if polarization == "TE": savetxt = '%s/TE_mode%d_Efield.png' % (output_directory, plot_mode_number) elif polarization == "TM": savetxt = '%s/TM_mode%d_Efield.png' % (output_directory, plot_mode_number) elif polarization == "None": savetxt = '%s/mode%d_Efield.png' % (output_directory, plot_mode_number) plt.savefig(savetxt) """ Then plot magnetic field """ plt.figure(figsize=(14, 8)) plt.subplot(2, 3, 1) plt.imshow(abs(H[:, :, 0, 2]), cmap=cmap_fields, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide mode $|H_x|$") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.subplot(2, 3, 2) plt.imshow(abs(H[:, :, 0, 1]), cmap=cmap_fields, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide mode $|H_y|$") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.subplot(2, 3, 3) plt.imshow(abs(H[:, :, 0, 0]), cmap=cmap_fields, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide mode $|H_z|$") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.subplot(2, 3, 4) plt.imshow(abs(Habs), cmap=cmap_fields, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide mode $|H|$") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.subplot(2, 3, 5) plt.imshow(eps, cmap=cmap_geom, origin='lower', aspect='auto', extent=plt_extent) plt.title("Waveguide dielectric") plt.ylabel("y-axis") plt.xlabel("x-axis") plt.colorbar() plt.tight_layout() if polarization == "TE": savetxt = '%s/TE_mode%d_Hfield.png' % (output_directory, plot_mode_number) elif polarization == "TM": savetxt = '%s/TM_mode%d_Hfield.png' % (output_directory, plot_mode_number) elif polarization == "None": savetxt = '%s/mode%d_Hfield.png' % (output_directory, plot_mode_number) plt.savefig(savetxt) """ Save the mode data to a .txt file """ if polarization == "TE": datafilename = '%s/TE_mode%d_data.txt' % (output_directory, plot_mode_number) elif polarization == "TM": datafilename = '%s/TM_mode%d_data.txt' % (output_directory, plot_mode_number) elif polarization == "None": datafilename = '%s/mode%d_data.txt' % (output_directory, plot_mode_number) f = open(datafilename, 'w') f.write( '#################################################################\n' ) f.write('Mode %d with %s polarization \n' % (plot_mode_number, polarization)) f.write( '#################################################################\n' ) f.write('\n') f.write('k \t\t %0.6f \n' % (k)) f.write('n_eff \t\t %0.6f \n' % (wavelength * k)) f.write('vg \t\t %0.6f \n' % (vg)) f.write('ng \t\t %0.6f \n' % (1 / vg))
def get_mode_solver_rib( wg_width: float = 0.45, wg_thickness: float = 0.22, slab_thickness: float = 0.0, ncore: float = 3.47, nclad: float = 1.44, nslab: Optional[float] = None, sy: float = 2.0, sz: float = 2.0, resolution: int = 32, nmodes: int = 4, sidewall_angle: float = None, # sidewall_taper: int = 1, ) -> mpb.ModeSolver: """Returns a mode_solver simulation. Args: wg_width: wg_width (um) wg_thickness: wg height (um) slab_thickness: thickness for the waveguide slab ncore: core material refractive index nclad: clad material refractive index nslab: Optional slab material refractive index. Defaults to ncore. sy: simulation region width (um) sz: simulation region height (um) resolution: resolution (pixels/um) nmodes: number of modes sidewall_angle: waveguide sidewall angle (radians), tapers from wg_width at top of slab, upwards, to top of waveguide :: . = origin __________________________ | | | width | <----------> | ___________ _ _ _ | | | | sz|_____| |_______| | | wg_thickness |slab_thickness | |___________._____________| | | |__________________________ <------------------------> sy """ material_core = mp.Medium(index=ncore) material_clad = mp.Medium(index=nclad) material_slab = mp.Medium(index=nslab or ncore) # Define the computational cell. We'll make x the propagation direction. # the other cell sizes should be big enough so that the boundaries are # far away from the mode field. geometry_lattice = mp.Lattice(size=mp.Vector3(0, sy, sz)) geometry = [] # define the 2d blocks for the strip and substrate if sidewall_angle: geometry.append( mp.Prism( vertices=[ mp.Vector3(y=-wg_width / 2, z=slab_thickness), mp.Vector3(y=wg_width / 2, z=slab_thickness), mp.Vector3(x=1, y=wg_width / 2, z=slab_thickness), mp.Vector3(x=1, y=-wg_width / 2, z=slab_thickness), ], height=wg_thickness - slab_thickness, center=mp.Vector3(z=slab_thickness + (wg_thickness - slab_thickness) / 2, ), # If only 1 angle is specified, use it for all waveguides sidewall_angle=sidewall_angle, # axis=mp.Vector3(z=sidewall_taper), material=material_core, )) else: geometry.append( mp.Block( size=mp.Vector3(mp.inf, wg_width, wg_thickness), material=material_core, center=mp.Vector3(z=wg_thickness / 2), )) # uncomment this for not oxide cladded waveguides # geometry.append( # mp.Block( # size=mp.Vector3(mp.inf, mp.inf, 0.5 * (sz - wg_thickness)), # center=mp.Vector3(z=0.25 * (sz + wg_thickness)), # material=material_clad, # ), # ) geometry += [ mp.Block( size=mp.Vector3(mp.inf, mp.inf, slab_thickness), material=material_slab, center=mp.Vector3(z=slab_thickness / 2), ), ] # The k (i.e. beta, i.e. propagation constant) points to look at, in # units of 2*pi/um. We'll look at num_k points from k_min to k_max. num_k = 9 k_min = 0.1 k_max = 3.0 k_points = mp.interpolate(num_k, [mp.Vector3(k_min), mp.Vector3(k_max)]) # Increase this to see more modes. (The guided ones are the ones below the # light line, i.e. those with frequencies < kmag / 1.45, where kmag # is the corresponding column in the output if you grep for "freqs:".) # use this prefix for output files filename_prefix = tmp / f"rib_{wg_width}_{wg_thickness}_{slab_thickness}" mode_solver = mpb.ModeSolver( geometry_lattice=geometry_lattice, geometry=geometry, k_points=k_points, resolution=resolution, num_bands=nmodes, default_material=material_clad, filename_prefix=str(filename_prefix), ) mode_solver.nmodes = nmodes mode_solver.info = dict( wg_width=wg_width, wg_thickness=wg_thickness, slab_thickness=slab_thickness, ncore=ncore, nclad=nclad, sy=sy, sz=sz, resolution=resolution, nmodes=nmodes, ) return mode_solver
b1 = f1[0, :, 1] # Backward propogating wave on port 1 a2 = f2[0, :, 0] # Forward propogating wave on port 2 b2 = f2[0, :, 1] # Backward propogating wave on port 2 S11 = b1 / a1 S12 = a2 / a1 # Pull corresponding frequency data for plots freqSim = np.array(mp.get_flux_freqs(mflux1)) freqSimAdjust = freqSim * 1e6 * c0 * 1e-12 # Pull effective indices and k vector for each omega point geometry_lattice = mp.Lattice(size=mp.Vector3(0, sy, 0)) # computational grid ms = mpb.ModeSolver(geometry_lattice=geometry_lattice, geometry=geometry, resolution=resolution) findOmega = freqSim # omegas for which we wish to find corresponding k's k_meep = np.zeros(nfreq) # preallocate k list for iter in range(0, nfreq): values = ms.find_k( mp.NO_PARITY, # polarization of interest findOmega[iter], # omega corresponding to k 1, # number of bands (min) 1, # number of bands (max) mp.Vector3(1), # direction in K space 1e-3, # convergence tolerance findOmega[iter] * nSi, # Guess for K findOmega[iter] * 0.1, # Min magnitude for K findOmega[iter] * (nSi + 2) # Max magnitude for K
center=mp.Vector3(0, 0), material=default_material), mp.Block(mp.Vector3(mp.inf, hu + h / 2, mp.inf), center=mp.Vector3(0, (hu + h / 2) / 2), material=upper_material), mp.Block(mp.Vector3(mp.inf, hl + h / 2, mp.inf), center=mp.Vector3(0, -(hl + h / 2) / 2), material=lower_material), mp.Block(mp.Vector3(mp.inf, h, mp.inf), center=mp.Vector3(0, 0), material=core_material) ] ms = mpb.ModeSolver( geometry_lattice=geometry_lattice, resolution=resolution, # ensure_periodicity=False, geometry=geometrympb) band = 1 k = ms.find_k( # p = mp.EVEN_Z, # Polarization p=mp.ODD_Z, # Polarization omega=fcen, # Omega to find corresponding k band_min=band, # Minimum band index band_max=band, # Max band index korig_and_kdir=mp.Vector3(1, 0, 0), # K vector orientation tol=1e-7, # solver tolerance kmag_guess=fcen * n_m, # initial guess kmag_min=fcen * n_c, # Minimum
mp.Prism(vertices_lr, center=mp.Vector3( center[0] + 1 / 2 - 1 / 3**0.5 * r_air * 3**0.5 / 2, center[1] + 3**.5 / 6 - 1 / 3**0.5 * r_air / 2), height=mp.inf, material=mp.Medium(epsilon=eps_back_2)) ] geometry_lattice = mp.Lattice(size=mp.Vector3(1, N * 3**0.5), basis1=mp.Vector3(1, 0), basis2=mp.Vector3(0, N * 3**0.5)) ms = mpb.ModeSolver( num_bands=num_bands, # target_freq=0.7, tolerance=1e-5, k_points=k_points, geometry_lattice=geometry_lattice, geometry=geometry, resolution=resolution) # kxm = 0.5 # kym = 0.5 # interp = 4; # kxm = 2 # kym = 2 # interp = 49 # N = interp+2 # step = kym/(interp+1) # ms.k_points = [] # for i in range(N): # ms.k_points += mp.interpolate(interp,[mp.Vector3(0,step*i), # Gamma
Gamma = mp.Vector3() K_prime = mp.lattice_to_reciprocal(mp.Vector3(0.5), geometry_lattice) # edge of Brillouin zone. k_points = mp.interpolate(4, [Gamma, K_prime]) # the bigger the supercell, the more bands you need to compute to get # to the defect modes (the lowest band is "folded" supercell_y times): extra_bands = 5 # number of extra bands to compute above the gap num_bands = supercell_y + extra_bands resolution = 32 ms = mpb.ModeSolver(geometry_lattice=geometry_lattice, geometry=geometry, k_points=k_points, num_bands=num_bands, resolution=resolution) def main(): # Compute the TM modes, outputting the Ez field in the *middle* of the # band. (In general, the guided mode in such an air defect may have # exited the gap by the time it reaches the edge of the Brillouin # zone at K_prime.) ms.run_tm(mpb.output_at_kpoint(k_points[len(k_points) // 2]), ms.fix_efield_phase, mpb.output_efield_z) if __name__ == '__main__': main()
mp.Prism(vertices_air, center=mp.Vector3( center[0]-1/6,center[1]+3**.5/6), height = mp.inf, material=mp.Medium(epsilon=1)), mp.Prism(vertices_air, center=mp.Vector3( center[0]+1/6,center[1]-3**.5/6), height = mp.inf, material=mp.Medium(epsilon=1)), mp.Prism(vertices_air, center=mp.Vector3( center[0]-1/6,center[1]-3**.5/6), height = mp.inf, material=mp.Medium(epsilon=1)), mp.Prism(vertices_cen1,center=mp.Vector3( center[0] + 0,center[1]+ 0), height = mp.inf, material=mp.Medium(epsilon=eps_outer_2)), mp.Prism(vertices_cen2,center=mp.Vector3( center[0] + 0,center[1]+ 0), height = mp.inf, material=mp.Medium(epsilon=eps_inner_2))] geometry_lattice = mp.Lattice(size=mp.Vector3(1, N*3**0.5), basis1=mp.Vector3(1,0), basis2=mp.Vector3(0,N*3**0.5)) ms = mpb.ModeSolver(num_bands=num_bands, # target_freq=0.7, tolerance = 1e-5, k_points=k_points, geometry_lattice = geometry_lattice, geometry=geometry, resolution=resolution, default_material=mp.Medium(epsilon=eps_back) ) # kxm = 0.5 # kym = 0.5 # interp = 4; # kxm = 2 # kym = 2 # interp = 49 # N = interp+2 # step = kym/(interp+1) # ms.k_points = [] # for i in range(N):