def test_mv_mult(self): lattice = mp.Lattice(size=mp.Vector3(1, 7), basis1=mp.Vector3(math.sqrt(3) / 2, 0.5), basis2=mp.Vector3(math.sqrt(3) / 2, -0.5)) res = lattice.basis * mp.Vector3(1) exp = mp.Vector3(0.8660254037844388, 0.5000000000000001) self.assertTrue(res.close(exp))
def test_geometric_objects_lattice_duplicates(self): geometry_lattice = mp.Lattice(size=mp.Vector3(1, 7), basis1=mp.Vector3(math.sqrt(3) / 2, 0.5), basis2=mp.Vector3( math.sqrt(3) / 2, -0.5)) eps = 12 r = 0.2 geometry = [mp.Cylinder(r, material=mp.Medium(epsilon=eps))] geometry = mp.geometric_objects_lattice_duplicates( geometry_lattice, geometry) med = mp.Medium(epsilon=12) expected = [ mp.Cylinder(0.2, material=med, center=mp.Vector3(y=3.0)), mp.Cylinder(0.2, material=med, center=mp.Vector3(y=2.0)), mp.Cylinder(0.2, material=med, center=mp.Vector3(y=1.0)), mp.Cylinder(0.2, material=med, center=mp.Vector3(y=0.0)), mp.Cylinder(0.2, material=med, center=mp.Vector3(y=-1.0)), mp.Cylinder(0.2, material=med, center=mp.Vector3(y=-2.0)), mp.Cylinder(0.2, material=med, center=mp.Vector3(y=-3.0)), ] for exp, res in zip(expected, geometry): self.assertEqual(exp.center, res.center) self.assertEqual(exp.radius, res.radius)
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 test_rotate_reciprocal(self): axis = mp.Vector3(1) v = mp.Vector3(2, 2, 2) lattice = mp.Lattice(size=mp.Vector3(1, 1)) res = v.rotate_reciprocal(axis, 3, lattice) self.assertTrue( res.close(mp.Vector3(2.0, -2.262225009320625, -1.6977449770811563)))
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 test_basis(self): lattice = mp.Lattice(size=mp.Vector3(1, 7), basis1=mp.Vector3(math.sqrt(3) / 2, 0.5), basis2=mp.Vector3(math.sqrt(3) / 2, -0.5)) b = lattice.basis exp = mp.Matrix(mp.Vector3(0.8660254037844388, 0.5000000000000001), mp.Vector3(0.8660254037844388, -0.5000000000000001), mp.Vector3(z=1.0)) for e, r in zip([exp.c1, exp.c2, exp.c3], [b.c1, b.c2, b.c3]): self.assertTrue(e.close(r))
def test_point_defect_state(self): ms = self.init_solver() ms.geometry_lattice = mp.Lattice(size=mp.Vector3(5, 5)) ms.geometry = [mp.Cylinder(0.2, material=mp.Medium(epsilon=12))] ms.geometry = mp.geometric_objects_lattice_duplicates( ms.geometry_lattice, ms.geometry) ms.geometry.append(mp.Cylinder(0.2, material=mp.air)) ms.resolution = 16 ms.k_points = [mp.Vector3(0.5, 0.5)] ms.num_bands = 50 ms.run_tm() mpb.fix_efield_phase(ms, 25) mpb.output_efield_z(ms, 25) mpb.fix_dfield_phase(ms, 25) ms.get_dfield(25) ms.compute_field_energy() c = mp.Cylinder(1.0, material=mp.air) e = ms.compute_energy_in_objects([c]) self.assertAlmostEqual(0.6227482574427817, e, places=3) ms.num_bands = 1 ms.target_freq = (0.2812 + 0.4174) / 2 ms.tolerance = 1e-8 ms.run_tm() expected_brd = [ ((0.37730041222979477, mp.Vector3(0.5, 0.5, 0.0)), (0.37730041222979477, mp.Vector3(0.5, 0.5, 0.0))), ] self.check_band_range_data(expected_brd, ms.band_range_data) old_geometry = ms.geometry # save the 5x5 grid with a missing rod def rootfun(eps): ms.geometry = old_geometry + [ mp.Cylinder(0.2, material=mp.Medium(epsilon=eps)) ] ms.run_tm() return ms.get_freqs()[0] - 0.314159 rooteps = ridder(rootfun, 1, 12) rootval = rootfun(rooteps) self.assertAlmostEqual(5.288830111797463, rooteps, places=3) self.assertAlmostEqual(9.300716530269426e-9, rootval, places=3)
def test_inverse(self): self.matrix_eq(self.identity, self.identity.inverse()) lattice = mp.Lattice(size=mp.Vector3(1, 7), basis1=mp.Vector3(math.sqrt(3) / 2, 0.5), basis2=mp.Vector3(math.sqrt(3) / 2, -0.5)) res = lattice.basis.inverse() exp = mp.Matrix(mp.Vector3(0.5773502691896256, 0.5773502691896256, -0.0), mp.Vector3(0.9999999999999998, -0.9999999999999998, -0.0), mp.Vector3(-0.0, -0.0, 1.0)) self.matrix_close(exp, res)
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 test_triangular_lattice(self): expected_brd = [ ((0.0, mp.Vector3(0.0, 0.0, 0.0)), (0.2746902258623623, mp.Vector3(-0.3333333333333333, 0.3333333333333333, 0.0))), ((0.44533108084715683, mp.Vector3(0.0, 0.5, 0.0)), (0.5605181423162835, mp.Vector3(0.0, 0.0, 0.0))), ((0.4902389149027666, mp.Vector3(-0.3333333333333333, 0.3333333333333333, 0.0)), (0.5605607947797747, mp.Vector3(0.0, 0.0, 0.0))), ((0.5932960873585144, mp.Vector3(0.0, 0.0, 0.0)), (0.7907195974443698, mp.Vector3(-0.3333333333333333, 0.3333333333333333, 0.0))), ((0.790832076332758, mp.Vector3(-0.3333333333333333, 0.3333333333333333, 0.0)), (0.8374511167537562, mp.Vector3(0.0, 0.0, 0.0))), ((0.8375948528443267, mp.Vector3(0.0, 0.0, 0.0)), (0.867200926490345, mp.Vector3(-0.2, 0.39999999999999997, 0.0))), ((0.8691349955739203, mp.Vector3(-0.13333333333333336, 0.4333333333333333, 0.0)), (0.9941291022664892, mp.Vector3(0.0, 0.0, 0.0))), ((0.8992499095547049, mp.Vector3(-0.3333333333333333, 0.3333333333333333, 0.0)), (1.098318352915696, mp.Vector3(0.0, 0.0, 0.0))), ] ms = self.init_solver() ms.geometry_lattice = mp.Lattice( size=mp.Vector3(1, 1), basis1=mp.Vector3(math.sqrt(3) / 2, 0.5), basis2=mp.Vector3(math.sqrt(3) / 2, -0.5)) k_points = [ mp.Vector3(), mp.Vector3(y=0.5), mp.Vector3(-1 / 3, 1 / 3), mp.Vector3() ] ms.k_points = mp.interpolate(4, k_points) ms.run_tm() self.check_band_range_data(expected_brd, ms.band_range_data)
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)
import re import subprocess ## Parametres de maille n_lo = 1 n_hi = 3.25 Nbands = 16 ra = 0.20 resolution = 64 ## Definition discretisation traits horizontaux nbr_points_x = 4 nbr_points_y = 4 ## Repere direct carree 45 geometry_lattice = mp.Lattice() geometry_lattice.basis_size = mp.Vector3(1, 1, 1) geometry_lattice.size = mp.Vector3(1, 1, 0) geometry_lattice.basis1 = mp.Vector3(math.sqrt(2) / 2, -math.sqrt(2) / 2) geometry_lattice.basis2 = mp.Vector3(math.sqrt(2) / 2, +math.sqrt(2) / 2) ## Definition motif default_material = mp.Medium(index=n_hi) C_0 = [mp.Cylinder(ra, material=mp.Medium(index=n_lo))] ## Limites IBZ REPERE RECIPROQUE k_point_gamma = mp.Vector3(0, 0) k_point_M_rec = mp.Vector3(1 / 2, 1 / 2) k_point_K_rec = mp.Vector3(1 / 2, 0) k_point_K_cart = mp.Vector3(math.sqrt(2) / 2, 0) k_point_M_cart = mp.Vector3(math.sqrt(2) / 4, math.sqrt(2) / 4)
# -*- coding: utf-8 -*- import meep as mp from meep import mpb import numpy as np import matplotlib.pyplot as plt resolution = 128 # pixels/μm Si = mp.Medium(index=3.45) syz = 10 geometry_lattice = mp.Lattice(size=mp.Vector3(0,syz,syz)) k_points = [mp.Vector3(0.5)] a = 1.0 # waveguide width 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=1,
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
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 test_cartesian_to_lattice(self): lattice = mp.Lattice(size=mp.Vector3(1, 7), basis1=mp.Vector3(math.sqrt(3) / 2, 0.5), basis2=mp.Vector3(math.sqrt(3) / 2, -0.5)) res = mp.cartesian_to_lattice(lattice.basis * mp.Vector3(1), lattice) self.assertEqual(res, mp.Vector3(1))
# The index will vary sinusoidally between index-min and index-max: index_min = 1 index_max = 3 # Define a function of position p (in the lattice basis) that returns # the material at that position. In this case, we use the function: # index-min + 0.5 * (index-max - index-min) # * (1 + cos(2*pi*x)) # 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)
height=mp.inf, material=mp.Medium(epsilon=(0.001 * int(sys.argv[5]))**2)) ] # 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 = [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)
mp.Vector3(0.5, 0, 0), mp.Vector3(0.5, 0.1, 0.0), mp.Vector3(0.5, 0.2, 0.0), mp.Vector3(0.5, 0.3, 0.0), mp.Vector3(0.5, 0.4, 0.0), mp.Vector3(0.5, 0.5, 0), mp.Vector3(0.4, 0.4, 0.0), mp.Vector3(0.3, 0.3, 0.0), mp.Vector3(0.2, 0.2, 0.0), mp.Vector3(0.1, 0.1, 0.0), mp.Vector3(0, 0, 0) ] geometry = [mp.Cylinder(0.2, material=mp.Medium(epsilon=12))] geometry_lattice = mp.Lattice(size=mp.Vector3(1, 1)) resolution = 32 ms = mpb.ModeSolver(num_bands=num_bands, k_points=k_points, geometry=geometry, geometry_lattice=geometry_lattice, resolution=resolution) #import sys #sys.exit(0) #print_heading("Square lattice of rods: TE bands") ms.run_te()
def __init__(self, resolution=10, is_negative_epsilon_ok=False, eigensolver_flops=0, eigensolver_flags=68, use_simple_preconditioner=False, force_mu=False, mu_input_file='', epsilon_input_file='', mesh_size=3, target_freq=0.0, tolerance=1.0e-7, num_bands=1, k_points=[], ensure_periodicity=True, geometry=[], geometry_lattice=mp.Lattice(), geometry_center=mp.Vector3(0, 0, 0), default_material=mp.Medium(epsilon=1), dimensions=3, random_fields=False, filename_prefix='', deterministic=False, verbose=False, optimize_grid_size=True, eigensolver_nwork=3, eigensolver_block_size=-11): self.mode_solver = None self.resolution = resolution self.eigensolver_flags = eigensolver_flags self.k_points = k_points self.geometry = geometry self.geometry_lattice = geometry_lattice self.geometry_center = mp.Vector3(*geometry_center) self.default_material = default_material self.random_fields = random_fields self.filename_prefix = filename_prefix self.optimize_grid_size = optimize_grid_size self.parity = '' self.iterations = 0 self.all_freqs = None self.freqs = [] self.band_range_data = [] self.total_run_time = 0 self.current_k = mp.Vector3() self.k_split_num = 1 self.k_split_index = 0 self.eigensolver_iters = [] grid_size = self._adjust_grid_size() if type(self.default_material) is not mp.Medium and callable( self.default_material): init_do_averaging(self.default_material) self.default_material.eps = False self.mode_solver = mode_solver( num_bands, self.resolution, self.geometry_lattice, tolerance, mesh_size, self.default_material, deterministic, target_freq, dimensions, verbose, ensure_periodicity, eigensolver_flops, is_negative_epsilon_ok, epsilon_input_file, mu_input_file, force_mu, use_simple_preconditioner, grid_size, eigensolver_nwork, eigensolver_block_size, )
hu = min(hu, (H - h) / 2) hl = min(hl, (H - h) / 2) n_m = max(n_x, n_y, n_z) n_c = max(n_l, n_u) fcen = 1 / wavelength df = 0.05 default_material = mp.Medium(epsilon=1) upper_material = mp.Medium(epsilon=n_u**2) core_material = mp.Medium(epsilon_diag=mp.Vector3(n_x**2, n_y**2, n_z**2)) lower_material = mp.Medium(epsilon=n_l**2) geometry_lattice = mp.Lattice(size=mp.Vector3(0, monitorheight, 0)) # bandNum = 4 # geometry = [mp.Block(mp.Vector3(mp.inf, h, mp.inf), center=mp.Vector3(0,0,0), material=core_material), # mp.Block(mp.Vector3(mp.inf, h, mp.inf), center=mp.Vector3(0,0,0), material=core_material), # mp.Block(mp.Vector3(mp.inf, h, mp.inf), center=mp.Vector3(0,0,0), material=core_material), # mp.Block(mp.Vector3(mp.inf, h, mp.inf), center=mp.Vector3(0,0,0), material=core_material)] geometrympb = [ mp.Block(mp.Vector3(mp.inf, monitorheight, mp.inf), 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),
eps0Si = 7.98737492 epsLorentzSi = 3.68799143 omega0Si = 3.93282466e15 epsSi = lambda lam: eps0Si + epsLorentzSi * omega0Si**2 / (omega0Si**2 - ( 2 * np.pi * c * 1e6 / lam)**2) # Silicon Dioxide dispersion relation eps0SiO2 = 2.119881 epsLorentzSiO2 = 49.43721 omega0SiO2 = 3.309238e13 epsSiO2 = lambda lam: eps0SiO2 + epsLorentzSiO2 * omega0SiO2**2 / ( omega0SiO2**2 - (2 * np.pi * c * 1e6 / lam)**2) sc_y = 2 # supercell width (um) sc_z = 2 # supercell height (um) geometry_lattice = mp.Lattice(size=mp.Vector3(0, sc_y, sc_z)) resolution = 32 # pixels/um ms = mpb.ModeSolver(geometry_lattice=geometry_lattice, resolution=resolution, ensure_periodicity=False) # ------------------------------------------------------------------------------ # # Loop through experiment # ------------------------------------------------------------------------------ # # get current frequency and wavelength currentLambda = 1.55 omegaIn = 1 / currentLambda # Update material parameters
# Our First Band Structure print_heading("Square lattice of rods in air") num_bands = 8 k_points = [ mp.Vector3(), # Gamma mp.Vector3(0.5), # X mp.Vector3(0.5, 0.5), # M mp.Vector3() ] # Gamma k_points = mp.interpolate(4, k_points) geometry = [mp.Cylinder(0.2, material=mp.Medium(epsilon=12))] geometry_lattice = mp.Lattice(size=mp.Vector3(1, 1)) resolution = 32 ms = mpb.ModeSolver(num_bands=num_bands, k_points=k_points, geometry=geometry, geometry_lattice=geometry_lattice, resolution=resolution) print_heading("Square lattice of rods: TE bands") ms.run_te() print_heading("Square lattice of rods: TM bands") ms.run_tm() print_heading("Square lattice of rods: TM, w/efield")
def __init__(self, resolution=10, is_negative_epsilon_ok=False, eigensolver_flops=0, is_eigensolver_davidson=False, eigensolver_nwork=3, eigensolver_block_size=-11, eigensolver_flags=68, is_simple_preconditioner=False, is_deterministic=False, force_mu=False, mu_input_file='', epsilon_input_file='', mesh_size=3, target_freq=0.0, tolerance=1.0e-7, num_bands=1, k_points=[], ensure_periodicity=True, geometry=[], geometry_lattice=mp.Lattice(), geometry_center=mp.Vector3(0, 0, 0), default_material=mp.Medium(epsilon=1), dimensions=3, random_fields=False, filename_prefix='', deterministic=False, verbose=False): self.resolution = resolution self.is_negative_epsilon_ok = is_negative_epsilon_ok self.eigensolver_flops = eigensolver_flops self.is_eigensolver_davidson = is_eigensolver_davidson self.eigensolver_nwork = eigensolver_nwork self.eigensolver_block_size = eigensolver_block_size self.eigensolver_flags = eigensolver_flags self.is_simple_preconditioner = is_simple_preconditioner self.is_deterministic = is_deterministic self.force_mu = force_mu self.mu_input_file = mu_input_file self.epsilon_input_file = epsilon_input_file self.mesh_size = mesh_size self.target_freq = target_freq self.tolerance = tolerance self.num_bands = num_bands self.k_points = k_points self.ensure_periodicity = ensure_periodicity self.geometry = geometry self.geometry_lattice = geometry_lattice self.geometry_center = geometry_center self.default_material = default_material self.dimensions = dimensions self.random_fields = random_fields self.filename_prefix = filename_prefix self.deterministic = deterministic self.verbose = verbose self.parity = '' self.iterations = 0 self.all_freqs = None self.freqs = [] self.band_range_data = [] self.eigensolver_flops = 0 self.total_run_time = 0 self.current_k = mp.Vector3() self.k_split_num = 1 self.k_split_index = 0 self.eigensolver_iters = [] self.mode_solver = None
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
import math import meep as mp from meep import mpb # Dielectric spheres in a diamond (fcc) lattice. This file is used in # the "Data Analysis Tutorial" section of the MPB manual. sqrt_half = math.sqrt(0.5) sqrt_third = math.sqrt(1.0 / 3.0) geometry_lattice = mp.Lattice(basis_size=mp.Vector3(sqrt_third, sqrt_third, sqrt_third), basis1=mp.Vector3(-1, 1, 1), basis2=mp.Vector3(1, -1, 1), basis3=mp.Vector3(1, 1, -1)) # Corners of the irreducible Brillouin zone for the "I" lattice, # in order that matches Maldovan2002 Fig 10 vlist = [ mp.Vector3(0, 0, 0.5), # N mp.Vector3(0.25, 0.25, 0.25), # P mp.Vector3(0, 0, 0), # Gamma mp.Vector3(0, 0, 0.5), # N mp.Vector3(0.5, -0.5, 0.5), # H mp.Vector3(0.25, 0.25, 0.25) # P ] k_points = mp.interpolate(4, vlist) # define a couple of parameters (which we can set from the command_line) #eps = 20.00 # the dielectric constant of the spheres #r = 0.25 # the radius of the spheres
dFolder = '/Users/mvchalupnik/Desktop/mympbplots/' dLoc = dFolder + paramstring if not os.path.exists(dFolder): os.makedirs(dFolder) w = w_actual/a_actual a = 1 hx = hx_actual/a_actual hy = hy_actual/a_actual h = w/2/np.tan(theta*np.pi/180) #################################################################### #sets size of lattice to be 3D; 1by1by1 geometry_lattice = mp.Lattice(size=mp.Vector3(a, w*3, h*3)) #https://meep.readthedocs.io/en/latest/Python_User_Interface/#prism beam = mp.Prism([mp.Vector3(0,-w/2, h/2), mp.Vector3(0,w/2, h/2), mp.Vector3(0,0, -h/2)], a, axis=mp.Vector3(1,0,0), center=None, material=mp.Medium(epsilon=n**2)) #Diamond: n = 2.4063; n^2 = ep_r hole = mp.Ellipsoid(size=[hx, hy, mp.inf], material=mp.Medium(epsilon=1)) geometry = [beam, hole] #Symmetry points k_points = [ mp.Vector3(0,0,0), # Gamma mp.Vector3(0.5,0,0), # X (normalized to a?)
import math import meep as mp from meep import mpb # A line_defect waveguide in a 2d triangular lattice of dielectric # rods (c.f. tri_rods.ctl), formed by a row of missing rods along the # "x" direction. (Here, "x" and "y" refer to the first and second # basis directions.) This structure supports a single guided band # within the band gap, much like the analogous waveguide in a square # lattice of rods (see "Photonic Crystals" by Joannopoulos et al.). supercell_y = 7 # the (odd) number of lateral supercell periods geometry_lattice = mp.Lattice(size=mp.Vector3(1, supercell_y), basis1=mp.Vector3(math.sqrt(3) / 2, 0.5), basis2=mp.Vector3(math.sqrt(3) / 2, -0.5)) eps = 12 # the dielectric constant of the rods r = 0.2 # the rod radius in the bulk crystal geometry = [mp.Cylinder(r, material=mp.Medium(epsilon=eps))] # duplicate the bulk crystal rods over the supercell: geometry = mp.geometric_objects_lattice_duplicates(geometry_lattice, geometry) # add a rod of air, to erase a row of rods and form a waveguide: geometry += [mp.Cylinder(r, material=mp.air)] Gamma = mp.Vector3() K_prime = mp.lattice_to_reciprocal(mp.Vector3(0.5),
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