def test_fields_at_kx(self): self.sim.k_point = mp.Vector3(3.5) h = mp.Harminv(mp.Hz, mp.Vector3(0.1234), self.fcen, self.df) self.sim.run(mp.after_sources(h), until_after_sources=300) expected = [ (0.19990240131986522, 3.8522735413802275e-8), (0.3050067740183294, 4.720168254531566e-7), (0.4396104226078593, 1.6233300291010948e-6), (0.4582004346509184, 4.7150006592976396e-7), (0.5006556112859917, -0.0014396635723422887), (0.7405953267896378, -4.553109069353934e-5), (0.7627621012715363, -0.006700351645723407), (0.8243404528365005, -5.174379068176951e-4), (0.8255990399390389, -0.0016256261502000271), (0.9494859645499801, -0.005325208458639275), (0.9726561278186849, -0.0031192234222098274), (0.9855957702101914, -0.003945157134867143), ] self.assertTrue(h.modes) places = 4 if mp.is_single_precision() else 7 for (r, i), m in zip(expected, h.modes): self.assertAlmostEqual(m.freq, r, places=places) self.assertAlmostEqual(m.decay, i, places=places)
def main(args): n = 3.4 # index of waveguide w = 1 # width of waveguide r = 1 # inner radius of ring pad = 4 # padding between waveguide and edge of PML dpml = 32 # thickness of PML sr = r + w + pad + dpml # radial size (cell is from 0 to sr) dimensions = mp.CYLINDRICAL cell = mp.Vector3(sr, 0, 0) # in cylindrical coordinates, the phi (angular) dependence of the fields # is given by exp(i m phi), where m is given by: m = args.m geometry = [ mp.Block(center=mp.Vector3(r + (w / 2)), size=mp.Vector3(w, 1e20, 1e20), material=mp.Medium(index=n)) ] pml_layers = [mp.PML(dpml)] resolution = 20 # If we don't want to excite a specific mode symmetry, we can just # put a single point source at some arbitrary place, pointing in some # arbitrary direction. We will only look for TM modes (E out of the plane). fcen = args.fcen # pulse center frequency df = args.df # pulse frequency width sources = [ mp.Source(src=mp.GaussianSource(fcen, fwidth=df), component=mp.Ez, center=mp.Vector3(r + 0.1)) ] # note that the r -> -r mirror symmetry is exploited automatically sim = mp.Simulation(cell_size=cell, geometry=geometry, boundary_layers=pml_layers, resolution=resolution, sources=sources, dimensions=dimensions, m=m) sim.run(mp.after_sources(mp.Harminv(mp.Ez, mp.Vector3(r + 0.1), fcen, df)), until_after_sources=200) # Output fields for one period at the end. (If we output # at a single time, we might accidentally catch the Ez field when it is # almost zero and get a distorted view.) We'll append the fields # to a file to get an r-by-t picture. We'll also output from -sr to -sr # instead of from 0 to sr. sim.run(mp.in_volume( mp.Volume(center=mp.Vector3(), size=mp.Vector3(2 * sr)), mp.at_beginning(mp.output_epsilon), mp.to_appended("ez", mp.at_every(1 / fcen / 20, mp.output_efield_z))), until=1 / fcen)
def test_resonant_modes(self): self.sim.sources = [mp.Source(mp.GaussianSource(self.fcen, fwidth=self.df), mp.Hz, mp.Vector3())] self.sim.symmetries = [mp.Mirror(mp.Y, phase=-1), mp.Mirror(mp.X, phase=-1)] h = mp.Harminv(mp.Hz, mp.Vector3(), self.fcen, self.df) self.sim.run(mp.at_beginning(mp.output_epsilon), mp.after_sources(h), until_after_sources=400) expected = [ 0.23445415346009466, -3.147812367338531e-4, 372.40808234438254, 5.8121430334347135, -3.763107485715599, -4.429450156854109, ] m = h.modes[0] res = [m.freq, m.decay, m.Q, abs(m.amp), m.amp.real, m.amp.imag] np.testing.assert_allclose(expected, res)
def example_cavity_harminv(): from gdshelpers.parts.waveguide import Waveguide from shapely.geometry import Point wg = Waveguide((-6, 0), 0, 1.2) start_port = wg.current_port wg.add_straight_segment(6) center_port = wg.current_port wg.add_straight_segment(6) wgs = [Waveguide.make_at_port(port).add_straight_segment(4) for port in [start_port.inverted_direction, wg.current_port]] holes = geometric_union( [Point(x * sign, 0).buffer(.36) for x in [1.4 / 2 + x * 1 for x in range(3)] for sign in [-1, 1]]) sim = Simulation(resolution=20, reduce_to_2d=True, padding=2, pml_thickness=1) sim.add_structure([wg.get_shapely_object().difference(holes)], wgs, mp.Medium(epsilon=13), z_min=0, z_max=.33) sim.add_source(mp.GaussianSource(wavelength=1 / .25, fwidth=.2), mp.Hz, center_port, z=0) sim.init_sim() sim.plot(fields=mp.Hz) mp.simulation.display_run_data = lambda *args, **kwargs: None harminv = mp.Harminv(mp.Hz, mp.Vector3(), .25, .2) sim.run(mp.after_sources(harminv._collect_harminv()(harminv.c, harminv.pt)), until_after_sources=300) sim.plot(fields=mp.Hz) print(harminv._analyze_harminv(sim.sim, 100))
def main(): geom = a_tapered_cavity() boundary_layers = get_boundary_layer(sim2d=False) fcen = 1/1.54 df = 0.1 sources = [mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Hz, center=mp.Vector3())] symmetries = [mp.Mirror(mp.X,+1), mp.Mirror(mp.Y,-1), mp.Mirror(mp.Z,+1)] sim = mp.Simulation(resolution=30, cell_size=mp.Vector3(20, 8, 8), geometry=geom, boundary_layers=boundary_layers, sources=sources, symmetries=symmetries, progress_interval=100,) h = mp.Harminv(mp.Hz, mp.Vector3(0, 0, 0), fcen, df) time_after_source = 500 # Don't output eps anymore to save disk space sim.run(mp.after_sources(h), until_after_sources=time_after_source) visualize_sim_cell(sim) print("Modal Volume: {}".format(sim.modal_volume_in_box()))
def test_resonant_modes(self): self.sim.sources = [ mp.Source(mp.GaussianSource(self.fcen, fwidth=self.df), mp.Hz, mp.Vector3()) ] self.sim.symmetries = [ mp.Mirror(mp.Y, phase=-1), mp.Mirror(mp.X, phase=-1) ] h = mp.Harminv(mp.Hz, mp.Vector3(), self.fcen, self.df) self.sim.run(mp.at_beginning(mp.output_epsilon), mp.after_sources(h), until_after_sources=400) expected = [ 0.23445415346009466, -3.147812367338531e-4, 372.40808234438254, 5.8121430334347135, -3.763107485715599, -4.429450156854109, ] m = h.modes[0] res = [m.freq, m.decay, m.Q, abs(m.amp), m.amp.real, m.amp.imag] np.testing.assert_allclose(expected, res)
def run_all(self, time_after_sources=150, nfreq_ldos=200): self.time_after_sources = time_after_sources self.nfreq_ldos = nfreq_ldos self.harminv_instance = mp.Harminv( mp.Er, mp.Vector3(0, 0, self.source_position + self.shift), self.fcen, self.df) self.ldos_instance = mp.Ldos(self.fcen, self.df, self.nfreq_ldos) self._sim.run(mp.after_sources(self.harminv_instance), mp.dft_ldos(ldos=self.ldos_instance), until_after_sources=self.time_after_sources) self.ldos_results = np.transpose( np.array([self.ldos_instance.freqs(), self._sim.ldos_data])) self.q_results = [] for mode in self.harminv_instance.modes: self.q_results.append( [1000 / mode.freq, mode.decay, mode.Q, abs(mode.amp)]) self.q_results = np.array(self.q_results) self.print_qs() self.plot_power() self.plot_ldos() self.plot_er_field()
def compute_resonant_mode(res): cell_size = mp.Vector3(1, 1, 0) rad = 0.301943 fcen = 0.3 df = 0.2 * fcen sources = [ mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Hz, center=mp.Vector3(-0.1057, 0.2094, 0)) ] k_point = mp.Vector3(0.3892, 0.1597, 0) design_shape = mp.Vector3(1, 1, 0) design_region_resolution = 50 Nx = int(design_region_resolution * design_shape.x) Ny = int(design_region_resolution * design_shape.y) x = np.linspace(-0.5 * design_shape.x, 0.5 * design_shape.x, Nx) y = np.linspace(-0.5 * design_shape.y, 0.5 * design_shape.y, Ny) xv, yv = np.meshgrid(x, y) design_params = np.sqrt(np.square(xv) + np.square(yv)) < rad filtered_design_params = gaussian_filter(design_params, sigma=3.0, output=np.double) matgrid = mp.MaterialGrid(mp.Vector3(Nx, Ny), mp.air, mp.Medium(index=3.5), weights=filtered_design_params, do_averaging=True, beta=1000, eta=0.5) geometry = [ mp.Block(center=mp.Vector3(), size=mp.Vector3(design_shape.x, design_shape.y, 0), material=matgrid) ] sim = mp.Simulation(resolution=res, cell_size=cell_size, geometry=geometry, sources=sources, k_point=k_point) h = mp.Harminv(mp.Hz, mp.Vector3(0.3718, -0.2076), fcen, df) sim.run(mp.after_sources(h), until_after_sources=200) try: for m in h.modes: print("harminv:, {}, {}, {}".format(res, m.freq, m.Q)) freq = h.modes[0].freq except: print("No resonant modes found.") sim.reset_meep() return freq
def check_warnings(sim, h, should_warn=True): with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") sim.run(mp.after_sources(h), until_after_sources=5) if should_warn: self.assertEqual(len(w), 1) self.assertIn("Harminv", str(w[-1].message)) else: self.assertEqual(len(w), 0)
def main(args): resolution = 200 sxy = 2 dpml = 1 sxy = sxy + 2 * dpml cell = mp.Vector3(sxy, sxy, 0) pml_layers = [mp.PML(dpml)] a = 1 t = 0.1 geometry = [ mp.Block(mp.Vector3(a + 2 * t, a + 2 * t, 1e20), material=mp.Medium(epsilon=-1e20)), mp.Block(mp.Vector3(a, a, 1e20), material=mp.Medium(epsilon=1.0)) ] w = args.w if w > 0: geometry.append( mp.Block(center=mp.Vector3(a / 2), size=mp.Vector3(2 * t, w, 1e20), material=mp.Medium(epsilon=1.0))) fcen = math.sqrt(0.5) / a df = 0.2 sources = [ mp.Source(src=mp.GaussianSource(fcen, fwidth=df), component=mp.Ez, center=mp.Vector3()) ] symmetries = [mp.Mirror(mp.Y)] Th = args.Th sim = mp.Simulation(cell_size=cell, geometry=geometry, boundary_layers=pml_layers, sources=sources, symmetries=symmetries, resolution=resolution) h = mp.Harminv(mp.Ez, mp.Vector3(), fcen, df) sim.run(mp.after_sources(h), until_after_sources=Th) m = h.modes[0] f = m.freq Q = m.Q Vmode = 0.25 * a * a print("ldos0:, {}".format(Q / Vmode / (2 * math.pi * f * math.pi * 0.5))) sim.reset_meep() T = 2 * Q * (1 / f) sim.run(mp.dft_ldos(f, 0, 1), until_after_sources=T)
def main(args): n = 3.4 # index of waveguide w = 1 # width of waveguide r = 1 # inner radius of ring pad = 4 # padding between waveguide and edge of PML dpml = 32 # thickness of PML sr = r + w + pad + dpml # radial size (cell is from 0 to sr) dimensions = mp.CYLINDRICAL cell = mp.Vector3(sr, 0, 0) # in cylindrical coordinates, the phi (angular) dependence of the fields # is given by exp(i m phi), where m is given by: m = args.m geometry = [mp.Block(center=mp.Vector3(r + (w / 2)), size=mp.Vector3(w, mp.inf, mp.inf), material=mp.Medium(index=n))] pml_layers = [mp.PML(dpml)] resolution = 20 # If we don't want to excite a specific mode symmetry, we can just # put a single point source at some arbitrary place, pointing in some # arbitrary direction. We will only look for Ez-polarized modes. fcen = args.fcen # pulse center frequency df = args.df # pulse frequency width sources = [mp.Source(src=mp.GaussianSource(fcen, fwidth=df), component=mp.Ez, center=mp.Vector3(r + 0.1))] # note that the r -> -r mirror symmetry is exploited automatically sim = mp.Simulation(cell_size=cell, geometry=geometry, boundary_layers=pml_layers, resolution=resolution, sources=sources, dimensions=dimensions, m=m) sim.run(mp.after_sources(mp.Harminv(mp.Ez, mp.Vector3(r + 0.1), fcen, df)), until_after_sources=200) # Output fields for one period at the end. (If we output # at a single time, we might accidentally catch the Ez field when it is # almost zero and get a distorted view.) We'll append the fields # to a file to get an r-by-t picture. We'll also output from -sr to -sr # instead of from 0 to sr. sim.run(mp.in_volume(mp.Volume(center=mp.Vector3(), size=mp.Vector3(2 * sr)), mp.at_beginning(mp.output_epsilon), mp.to_appended("ez", mp.at_every(1 / fcen / 20, mp.output_efield_z))), until=1 / fcen)
def metal_cavity(w): resolution = 50 sxy = 2 dpml = 1 sxy = sxy + 2 * dpml cell = mp.Vector3(sxy, sxy) pml_layers = [mp.PML(dpml)] a = 1 t = 0.1 geometry = [ mp.Block(mp.Vector3(a + 2 * t, a + 2 * t, mp.inf), material=mp.metal), mp.Block(mp.Vector3(a, a, mp.inf), material=mp.air) ] geometry.append( mp.Block(center=mp.Vector3(a / 2), size=mp.Vector3(2 * t, w, mp.inf), material=mp.air)) fcen = math.sqrt(0.5) / a df = 0.2 sources = [ mp.Source(src=mp.GaussianSource(fcen, fwidth=df), component=mp.Ez, center=mp.Vector3()) ] symmetries = [mp.Mirror(mp.Y)] sim = mp.Simulation(cell_size=cell, geometry=geometry, boundary_layers=pml_layers, sources=sources, symmetries=symmetries, resolution=resolution) h = mp.Harminv(mp.Ez, mp.Vector3(), fcen, df) sim.run(mp.after_sources(h), until_after_sources=500) m = h.modes[0] f = m.freq Q = m.Q Vmode = 0.25 * a * a ldos_1 = Q / Vmode / (2 * math.pi * f * math.pi * 0.5) sim.reset_meep() T = 2 * Q * (1 / f) sim.run(mp.dft_ldos(f, 0, 1), until_after_sources=T) ldos_2 = sim.ldos_data[0] return ldos_1, ldos_2
def main(): n = 3.4 # index of waveguide r = 1 a = r # inner radius of ring w = 1 # width of waveguide b = a + w # outer radius of ring pad = 4 # padding between waveguide and edge of PML dpml = 2 # thickness of PML pml_layers = [mp.PML(dpml)] resolution = 100 sr = b + pad + dpml # radial size (cell is from 0 to sr) dimensions = mp.CYLINDRICAL # coordinate system is (r,phi,z) instead of (x,y,z) cell = mp.Vector3(sr, 0, 0) m = 4 geometry = [ mp.Block(center=mp.Vector3(a + (w / 2)), size=mp.Vector3(w, 1e20, 1e20), material=mp.Medium(index=n)) ] # Finding a resonance mode with a high Q-value (calculated with Harminv) fcen = 0.15 # pulse center frequency df = 0.1 # pulse width (in frequency) sources = [ mp.Source(mp.GaussianSource(fcen, fwidth=df), mp.Hz, mp.Vector3(r + 0.1), amplitude=1) ] sim = mp.Simulation(cell_size=cell, geometry=geometry, boundary_layers=pml_layers, resolution=resolution, sources=sources, dimensions=dimensions, m=m) h = mp.Harminv(mp.Hz, mp.Vector3(r + 0.1), fcen, df) sim.run(mp.after_sources(h), until_after_sources=200) print(f'Harminv found {len(h.modes)} resonant modes(s).') for mode in h.modes: print(f'The resonant mode with f={mode.freq} has Q={mode.Q}')
def main(): # Some parameters to describe the geometry: eps = 13 # dielectric constant of waveguide w = 1.2 # width of waveguide r = 0.36 # radius of holes # The cell dimensions sy = 12 # size of cell in y direction (perpendicular to wvg.) dpml = 1 # PML thickness (y direction only!) cell = mp.Vector3(1, sy) b = mp.Block(size=mp.Vector3(mp.inf, w, mp.inf), material=mp.Medium(epsilon=eps)) c = mp.Cylinder(radius=r) fcen = 0.25 # pulse center frequency df = 1.5 # pulse freq. width: large df = short impulse s = mp.Source(src=mp.GaussianSource(fcen, fwidth=df), component=mp.Hz, center=mp.Vector3(0.1234)) sym = mp.Mirror(direction=mp.Y, phase=-1) sim = mp.Simulation(cell_size=cell, geometry=[b, c], sources=[s], symmetries=[sym], boundary_layers=[mp.PML(dpml, direction=mp.Y)], resolution=20) kx = False # if true, do run at specified kx and get fields k_interp = 19 # # k-points to interpolate, otherwise if kx: sim.k_point = mp.Vector3(kx) sim.run(mp.at_beginning(mp.output_epsilon), mp.after_sources( mp.Harminv(mp.Hz, mp.Vector3(0.1234), fcen, df)), until_after_sources=300) sim.run(mp.at_every(1 / fcen / 20, mp.output_hfield_z), until=1 / fcen) else: sim.run_k_points( 300, mp.interpolate(k_interp, [mp.Vector3(), mp.Vector3(0.5)]))
def main(args): resolution = 200 sxy = 2 dpml = 1 sxy = sxy + 2 * dpml cell = mp.Vector3(sxy, sxy, 0) pml_layers = [mp.PML(dpml)] a = 1 t = 0.1 geometry = [mp.Block(mp.Vector3(a + 2 * t, a + 2 * t, mp.inf), material=mp.metal), mp.Block(mp.Vector3(a, a, mp.inf), material=mp.air)] w = args.w if w > 0: geometry.append(mp.Block(center=mp.Vector3(a / 2), size=mp.Vector3(2 * t, w, mp.inf), material=mp.air)) fcen = math.sqrt(0.5) / a df = 0.2 sources = [mp.Source(src=mp.GaussianSource(fcen, fwidth=df), component=mp.Ez, center=mp.Vector3())] symmetries = [mp.Mirror(mp.Y)] Th = args.Th sim = mp.Simulation(cell_size=cell, geometry=geometry, boundary_layers=pml_layers, sources=sources, symmetries=symmetries, resolution=resolution) h = mp.Harminv(mp.Ez, mp.Vector3(), fcen, df) sim.run(mp.after_sources(h), until_after_sources=Th) m = h.modes[0] f = m.freq Q = m.Q Vmode = 0.25 * a * a print("ldos0:, {}".format(Q / Vmode / (2 * math.pi * f * math.pi * 0.5))) sim.reset_meep() T = 2 * Q * (1 / f) sim.run(mp.dft_ldos(f, 0, 1), until_after_sources=T)
def test_custom_source(self): n = 3.4 w = 1 r = 1 pad = 4 dpml = 2 sxy = 2 * (r + w + pad + dpml) cell = mp.Vector3(sxy, sxy) geometry = [ mp.Cylinder(r + w, material=mp.Medium(index=n)), mp.Cylinder(r, material=mp.air) ] boundary_layers = [mp.PML(dpml)] resolution = 10 fcen = 0.15 df = 0.1 # Bump function def my_src_func(t): if t > 0 and t < 2: return math.exp(-1 / (1 - ((t - 1)**2))) return 0j sources = [ mp.Source(src=mp.CustomSource(src_func=my_src_func, end_time=100), component=mp.Ez, center=mp.Vector3(r + 0.1)) ] symmetries = [mp.Mirror(mp.Y)] sim = mp.Simulation(cell_size=cell, resolution=resolution, geometry=geometry, boundary_layers=boundary_layers, sources=sources, symmetries=symmetries) h = mp.Harminv(mp.Ez, mp.Vector3(r + 0.1), fcen, df) sim.run(mp.after_sources(h), until_after_sources=200) fp = sim.get_field_point(mp.Ez, mp.Vector3(1)) self.assertAlmostEqual(fp, -0.021997617628500023 + 0j)
def test_ring_cyl(self): expected = [ 0.11835455441250553, -6.907792691629741e-4, 85.66741917133473, 0.025701906263451237, -0.024027038833537524, -0.009126302124459489, ] h = mp.Harminv(mp.Ez, mp.Vector3(self.r + 0.1), self.fcen, self.df) self.sim.run(mp.after_sources(h), until_after_sources=200) m = h.modes[0] res = [m.freq, m.decay, m.Q, abs(m.amp), m.amp.real, m.amp.imag] np.testing.assert_allclose(expected, res)
def find_modes(filename, wvl=1.55, bw=0.05): # Read in the ring structure geometry = mp.get_GDSII_prisms(Si, filename, RING_LAYER, -100, 100) cell = mp.GDSII_vol(filename, SIMULATION_LAYER, zmin, zmax) src_vol0 = mp.GDSII_vol(filename, SOURCE0_LAYER, zmin, zmax) src_vol1 = mp.GDSII_vol(filename, SOURCE1_LAYER, zmin, zmax) mon_vol = mp.GDSII_vol(filename, MONITOR_LAYER, zmin, zmax) fcen = 1 / wvl df = bw * fcen src = [ mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Hz, volume=src_vol0), mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Hz, volume=src_vol1, amplitude=-1) ] sim = mp.Simulation(cell_size=cell.size, geometry=geometry, sources=src, resolution=resolution, boundary_layers=[mp.PML(dpml)], default_material=SiO2) h = mp.Harminv(mp.Hz, mon_vol.center, fcen, df) sim.run(mp.after_sources(h), until_after_sources=100) plt.figure() sim.plot2D(fields=mp.Hz) plt.savefig('ring_resonator_Hz.png') wvl = np.array([1 / m.freq for m in h.modes]) Q = np.array([m.Q for m in h.modes]) sim.reset_meep() return wvl, Q
def test_harminv(self): self.init() self.sim.run( mp.at_beginning(mp.output_epsilon), mp.after_sources(self.h), until_after_sources=300 ) m1, m2, m3 = self.h.modes self.assertAlmostEqual(m1.freq, 0.118101315147, places=4) self.assertAlmostEqual(m1.decay, -0.000731513241623, places=4) self.assertAlmostEqual(abs(m1.amp), 0.00341267634436, places=4) self.assertAlmostEqual(m1.amp.real, -0.00304951667301, places=4) self.assertAlmostEqual(m1.amp.imag, -0.00153192946717, places=4) fp = self.sim.get_field_point(mp.Ez, mp.Vector3(1, 1)) self.assertAlmostEqual(fp, -0.08185972142450348)
def get_q_values(self, time_after_sources=150): self.time_after_sources = time_after_sources # get q values at sources harminv_instance = mp.Harminv( mp.Er, mp.Vector3(0, 0, self.source_position + self.shift), self.fcen, self.df) self._sim.run(mp.after_sources(harminv_instance), until_after_sources=self.time_after_sources) self.q_results = [] for mode in harminv_instance.modes: self.q_results.append( [1000 / mode.freq, mode.decay, mode.Q, abs(mode.amp)]) self.q_results = np.array(self.q_results) self.print_qs()
def test_custom_source(self): n = 3.4 w = 1 r = 1 pad = 4 dpml = 2 sxy = 2 * (r + w + pad + dpml) cell = mp.Vector3(sxy, sxy) geometry = [ mp.Cylinder(r + w, material=mp.Medium(index=n)), mp.Cylinder(r, material=mp.air) ] boundary_layers = [mp.PML(dpml)] resolution = 10 fcen = 0.15 df = 0.1 # Bump function def my_src_func(t): if t > 0 and t < 2: return math.exp(-1 / (1 - ((t - 1)**2))) return 0j sources = [mp.Source(src=mp.CustomSource(src_func=my_src_func, end_time=100), component=mp.Ez, center=mp.Vector3(r + 0.1))] symmetries = [mp.Mirror(mp.Y)] sim = mp.Simulation(cell_size=cell, resolution=resolution, geometry=geometry, boundary_layers=boundary_layers, sources=sources, symmetries=symmetries) h = mp.Harminv(mp.Ez, mp.Vector3(r + 0.1), fcen, df) sim.run(mp.after_sources(h), until_after_sources=200) fp = sim.get_field_point(mp.Ez, mp.Vector3(1)) self.assertAlmostEqual(fp, -0.021997617628500023 + 0j)
def main(): n = 3.4 # index of waveguide w = 1 # width of waveguide r = 1 # inner radius of ring pad = 4 # padding between waveguide and edge of PML dpml = 2 # thickness of PML sxy = 2 * (r + w + pad + dpml) # cell size # Create a ring waveguide by two overlapping cylinders - later objects # take precedence over earlier objects, so we put the outer cylinder first. # and the inner (air) cylinder second. c1 = mp.Cylinder(radius=r + w, material=mp.Medium(index=n)) c2 = mp.Cylinder(radius=r) # If we don't want to excite a specific mode symmetry, we can just # put a single point source at some arbitrary place, pointing in some # arbitrary direction. We will only look for Ez-polarized modes. fcen = 0.15 # pulse center frequency df = 0.1 # pulse width (in frequency) src = mp.Source(mp.GaussianSource(fcen, fwidth=df), mp.Hz, mp.Vector3(r + 0.1)) sim = mp.Simulation(cell_size=mp.Vector3(sxy, sxy), geometry=[c1, c2], sources=[src], resolution=10, symmetries=[mp.Mirror(mp.Y)], boundary_layers=[mp.PML(dpml)]) h = mp.Harminv(mp.Ex, mp.Vector3(r + 0.1), fcen, df) sim.run(mp.after_sources(h), until_after_sources=200) print(f'Harminv found {len(h.modes)} resonant modes(s).') for mode in h.modes: print(f'The resonant mode with f={mode.freq} has Q={mode.Q}') sim.plot2D(fields=mp.Ex, field_parameters={'alpha':0.8, 'cmap':'RdBu', 'interpolation':'none'}, boundary_parameters={'hatch':'o', 'linewidth':1.5, 'facecolor':'y', 'edgecolor':'b', 'alpha':0.3}) plt.show()
def main(): n = 3.4 # index of waveguide w = 1 # width of waveguide r = 1 # inner radius of ring pad = 4 # padding between waveguide and edge of PML dpml = 2 # thickness of PML sxy = 2 * (r + w + pad + dpml) # cell size # Create a ring waveguide by two overlapping cylinders - later objects # take precedence over earlier objects, so we put the outer cylinder first. # and the inner (air) cylinder second. c1 = mp.Cylinder(radius=r + w, material=mp.Medium(index=n)) c2 = mp.Cylinder(radius=r) # If we don't want to excite a specific mode symmetry, we can just # put a single point source at some arbitrary place, pointing in some # arbitrary direction. We will only look for Ez-polarized modes. fcen = 0.15 # pulse center frequency df = 0.1 # pulse width (in frequency) src = mp.Source(mp.GaussianSource(fcen, fwidth=df), mp.Ez, mp.Vector3(r + 0.1)) sim = mp.Simulation(cell_size=mp.Vector3(sxy, sxy), geometry=[c1, c2], sources=[src], resolution=10, symmetries=[mp.Mirror(mp.Y)], boundary_layers=[mp.PML(dpml)]) sim.run( mp.at_beginning(mp.output_epsilon), mp.after_sources(mp.Harminv(mp.Ez, mp.Vector3(r + 0.1), fcen, df)), until_after_sources=300 ) # Output fields for one period at the end. (If we output # at a single time, we might accidentally catch the Ez field when it is # almost zero and get a distorted view.) sim.run(mp.at_every((1 / fcen / 20), mp.output_efield_z), until=(1 / fcen))
def main(): n = 3.4 # index of waveguide w = 1 # width of waveguide r = 1 # inner radius of ring pad = 4 # padding between waveguide and edge of PML dpml = 2 # thickness of PML sxy = 2*(r+w+pad+dpml) # cell size # Create a ring waveguide by two overlapping cylinders - later objects # take precedence over earlier objects, so we put the outer cylinder first. # and the inner (air) cylinder second. c1 = mp.Cylinder(radius=r+w, material=mp.Medium(index=n)) c2 = mp.Cylinder(radius=r) # If we don't want to excite a specific mode symmetry, we can just # put a single point source at some arbitrary place, pointing in some # arbitrary direction. We will only look for Ez-polarized modes. fcen = 0.15 # pulse center frequency df = 0.1 # pulse width (in frequency) src = mp.Source(mp.GaussianSource(fcen, fwidth=df), mp.Ez, mp.Vector3(r+0.1)) sim = mp.Simulation(cell_size=mp.Vector3(sxy, sxy), geometry=[c1, c2], sources=[src], resolution=10, symmetries=[mp.Mirror(mp.Y)], boundary_layers=[mp.PML(dpml)]) sim.run(mp.at_beginning(mp.output_epsilon), mp.after_sources(mp.Harminv(mp.Ez, mp.Vector3(r+0.1), fcen, df)), until_after_sources=300) # Output fields for one period at the end. (If we output # at a single time, we might accidentally catch the Ez field when it is # almost zero and get a distorted view.) sim.run(mp.at_every(1/fcen/20, mp.output_efield_z), until=1/fcen)
def test_harminv(self): self.init() self.sim.run(mp.at_beginning(mp.output_epsilon), mp.after_sources(self.h), until_after_sources=300) m1 = self.h.modes[0] self.assertAlmostEqual(m1.freq, 0.118101315147, places=4) self.assertAlmostEqual(m1.decay, -0.000731513241623, places=4) self.assertAlmostEqual(abs(m1.amp), 0.00341267634436, places=4) self.assertAlmostEqual(m1.amp.real, -0.00304951667301, places=4) self.assertAlmostEqual(m1.amp.imag, -0.00153192946717, places=3) v = mp.Vector3(1, 1) fp = self.sim.get_field_point(mp.Ez, v) ep = self.sim.get_epsilon_point(v) places = 5 if mp.is_single_precision() else 7 self.assertAlmostEqual(ep, 11.559999999999999, places=places) self.assertAlmostEqual(fp, -0.08185972142450348, places=places)
def main(args): resolution = 20 # 20 pixels per unit 1 um eps = 80 # epsilon of cylinder medium Mat1 = mp.Medium(epsilon=eps) # definition of the material dimensions = mp.CYLINDRICAL r = args.r # the value of cylinder radius rl = args.rl # the r/l ration is given, to obtain the l value l=r/rl x = args.x dpml = args.dpml dair = args.dair m=args.m w=1*x h = r/rl # the height of the cylinder sr = r + dair + dpml sz = h + 2*dair + 2*dpml w_max=1.8 w_min=0.2 dw=w_max-w_min boundary_layers = [mp.PML(dpml)] Cyl = mp.Cylinder(material=Mat1, radius=r, height=h, center=mp.Vector3(0,0,0)) # make a cylinder with given parameters geometry = [Cyl] cell_size = mp.Vector3(sr,0,sz) #sources = [ mp.Source(mp.ContinuousSource(frequency = w), component=mp.Hz, center=mp.Vector3(r+dair,0,0)) ] sources = [mp.Source(mp.GaussianSource(w, fwidth=dw), component=mp.Hz, center=mp.Vector3(r+dair,0,0))] sim = mp.Simulation(resolution=resolution, cell_size=cell_size, boundary_layers=boundary_layers, geometry=geometry, sources=sources, dimensions=dimensions, m=m) sim.run(mp.in_volume(mp.Volume(center=mp.Vector3(), size=mp.Vector3(sr,0,sz)), mp.at_end(mp.output_epsilon, mp.output_efield_z)), mp.after_sources(mp.Harminv(mp.Hz, mp.Vector3(), w, dw)), until_after_sources=100)
component=mp.Ez, center=mp.Vector3(r + 0.1)) ] # exploit the mirror symmetry in structure+source: symmetries = [mp.Mirror(mp.Y)] sim = mp.Simulation(cell_size=cell, resolution=resolution, geometry=geometry, boundary_layers=pml_layers, sources=sources, symmetries=symmetries) h1 = mp.Harminv(mp.Ez, mp.Vector3(r + 0.1), fcen, df) sim.run(mp.after_sources(h1), until_after_sources=300) fields2 = sim.fields sim.reset_meep() fcen = 0.236 h2 = mp.Harminv(mp.Ez, mp.Vector3(r + 0.1), fcen, df) sim.run(mp.after_sources(h2), until_after_sources=300) def overlap_integral(r, ez1, ez2): return ez1.conjugate() * ez2 res = sim.integrate2_field_function(fields2, [mp.Ez], [mp.Ez], overlap_integral)
sim = mp.Simulation(cell_size=cell, geometry=geometry, sources=[], boundary_layers=[mp.PML(dpml)], resolution=20) if args.resonant_modes: sim.sources.append(mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Hz, center=mp.Vector3())) sim.symmetries.append(mp.Mirror(mp.Y, phase=-1)) sim.symmetries.append(mp.Mirror(mp.X, phase=-1)) sim.run(mp.at_beginning(mp.output_epsilon), mp.after_sources(mp.Harminv(mp.Hz, mp.Vector3(), fcen, df)), until_after_sources=400) sim.run(mp.at_every(1 / fcen / 20, mp.output_hfield_z), until=1 / fcen) else: sim.sources.append(mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Ey, center=mp.Vector3(-0.5 * sx + dpml), size=mp.Vector3(0, w))) sim.symmetries.append(mp.Mirror(mp.Y, phase=-1)) freg = mp.FluxRegion(center=mp.Vector3(0.5 * sx - dpml - 0.5), size=mp.Vector3(0, 2 * w)) # transmitted flux
def main(args): # Some parameters to describe the geometry: eps = 13 # dielectric constant of waveguide w = 1.2 # width of waveguide r = 0.36 # radius of holes d = 1.4 # defect spacing (ordinary spacing = 1) N = args.N # number of holes on either side of defect # The cell dimensions sy = args.sy # size of cell in y direction (perpendicular to wvg.) pad = 2 # padding between last hole and PML edge dpml = 1 # PML thickness sx = 2 * (pad + dpml + N) + d - 1 # size of cell in x direction 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(N): geometry.append(mp.Cylinder(r, center=mp.Vector3(d / 2 + i))) geometry.append(mp.Cylinder(r, center=mp.Vector3(-(d / 2 + i)))) fcen = args.fcen # pulse center frequency df = args.df # pulse frequency width nfreq = 500 # number of frequencies at which to compute flux sim = mp.Simulation(cell_size=cell, geometry=geometry, sources=[], boundary_layers=[mp.PML(dpml)], resolution=20) if args.resonant_modes: sim.sources.append( mp.Source(mp.GaussianSource(fcen, fwidth=df), mp.Hz, mp.Vector3())) sim.symmetries.append(mp.Mirror(mp.Y, phase=-1)) sim.symmetries.append(mp.Mirror(mp.X, phase=-1)) sim.run( # mp.at_beginning(mp.output_epsilon), mp.after_sources(mp.Harminv(mp.Hz, mp.Vector3(), fcen, df)), until_after_sources=400) # sim.run(mp.at_every(1 / fcen / 20, mp.output_hfield_z), until=1 / fcen) else: sim.sources.append( mp.Source(mp.GaussianSource(fcen, fwidth=df), mp.Ey, mp.Vector3(dpml + (-0.5 * sx)), size=mp.Vector3(0, w))) sim.symmetries.append(mp.Mirror(mp.Y, phase=-1)) freg = mp.FluxRegion(center=mp.Vector3((0.5 * sx) - dpml - 0.5), size=mp.Vector3(0, 2 * w)) # transmitted flux trans = sim.add_flux(fcen, df, nfreq, freg) vol = mp.Volume(mp.Vector3(), size=mp.Vector3(sx)) sim.run(mp.at_beginning(mp.output_epsilon), mp.during_sources( mp.in_volume( vol, mp.to_appended("hz-slice", mp.at_every(0.4, mp.output_hfield_z)))), until_after_sources=mp.stop_when_fields_decayed( 50, mp.Ey, mp.Vector3((0.5 * sx) - dpml - 0.5, 0), 1e-3)) sim.display_fluxes(trans) # print out the flux spectrum
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)), 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)), 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=5000) flux = mp.get_fluxes(wvg_flux)[0] force = mp.get_forces(wvg_force)[0] sim.reset_meep() return flux, force
def main(args): resolution = 20 # pixels/um eps = 13 # dielectric constant of waveguide w = 1.2 # width of waveguide r = 0.36 # radius of holes d = 1.4 # defect spacing (ordinary spacing = 1) N = args.N # number of holes on either side of defect sy = args.sy # size of cell in y direction (perpendicular to wvg.) pad = 2 # padding between last hole and PML edge dpml = 1 # PML thickness sx = 2*(pad+dpml+N)+d-1 # size of cell in x direction 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(N): geometry.append(mp.Cylinder(r, center=mp.Vector3(d/2+i))) geometry.append(mp.Cylinder(r, center=mp.Vector3(-(d/2+i)))) fcen = args.fcen # pulse center frequency df = args.df # pulse frequency width nfreq = 500 # number of frequencies at which to compute flux sim = mp.Simulation(cell_size=cell, geometry=geometry, sources=[], boundary_layers=[mp.PML(dpml)], resolution=20) if args.resonant_modes: sim.sources.append(mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Hz, center=mp.Vector3())) sim.symmetries.append(mp.Mirror(mp.Y, phase=-1)) sim.symmetries.append(mp.Mirror(mp.X, phase=-1)) sim.run(mp.at_beginning(mp.output_epsilon), mp.after_sources(mp.Harminv(mp.Hz, mp.Vector3(), fcen, df)), until_after_sources=400) sim.run(mp.at_every(1/fcen/20, mp.output_hfield_z), until=1/fcen) else: sim.sources.append(mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Ey, center=mp.Vector3(-0.5*sx+dpml), size=mp.Vector3(0,w))) sim.symmetries.append(mp.Mirror(mp.Y, phase=-1)) freg = mp.FluxRegion(center=mp.Vector3(0.5*sx-dpml-0.5), size=mp.Vector3(0,2*w)) # transmitted flux trans = sim.add_flux(fcen, df, nfreq, freg) vol = mp.Volume(mp.Vector3(), size=mp.Vector3(sx)) sim.run(mp.at_beginning(mp.output_epsilon), mp.during_sources(mp.in_volume(vol, mp.to_appended("hz-slice", mp.at_every(0.4, mp.output_hfield_z)))), until_after_sources=mp.stop_when_fields_decayed(50, mp.Ey, mp.Vector3(0.5*sx-dpml-0.5), 1e-3)) sim.display_fluxes(trans) # print out the flux spectrum
def main(args): resolution = 30 # pixels/μm Si = mp.Medium(index=3.45) dpml = 1.0 pml_layers = [mp.PML(dpml)] sx = 5 sy = 3 cell = mp.Vector3(sx+2*dpml,sy+2*dpml,0) a = 1.0 # waveguide width s = args.s # waveguide separation distance 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)] xodd = args.xodd symmetries = [mp.Mirror(mp.X, phase=-1.0 if xodd else 1.0), mp.Mirror(mp.Y, phase=-1.0)] k_point = mp.Vector3(z=0.5) fcen = 0.22 df = 0.06 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)), 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)), 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=5000) sim.display_fluxes(wvg_flux) sim.display_forces(wvg_force)
fcen = 0.15 # pulse center frequency df = 0.1 # pulse frequency width src = mp.Source(mp.GaussianSource(fcen, fwidth=df), mp.Ez, mp.Vector3(r + 0.1)) sim = mp.Simulation(cell_size=mp.Vector3(sxy, sxy), geometry=[c1, c2], sources=[src], resolution=10, boundary_layers=[mp.PML(dpml)]) plt.figure(dpi=150) sim.plot2D() plt.savefig('structureBox.png') sim.run(mp.at_beginning(mp.output_epsilon), mp.after_sources(mp.Harminv(mp.Ez, mp.Vector3(r + 0.1), fcen, df)), until_after_sources=300) sim.reset_meep() fcen = 0.118 df = 0.1 sim.sources = [ mp.Source(mp.GaussianSource(fcen, fwidth=df), mp.Ez, mp.Vector3(r + 0.1)) ] # Start the simulation and get into steady state sim.run(until=600) # Prepare the animator and record the steady state response f = plt.figure(dpi=150) Animate = mp.Animate2D(sim, fields=mp.Ez, f=f, realtime=False, normalize=True)
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=5000) flux = mp.get_fluxes(wvg_flux)[0] force = mp.get_forces(wvg_force)[0] sim.reset_meep() return flux, force
def main(): n = 3.4 # index of waveguide r = 1 a = r # inner radius of ring w = 1 # width of waveguide b = a + w # outer radius of ring pad = 4 # padding between waveguide and edge of PML dpml = 2 # thickness of PML pml_layers = [mp.PML(dpml)] resolution = 100 sr = b + pad + dpml # radial size (cell is from 0 to sr) dimensions = mp.CYLINDRICAL # coordinate system is (r,phi,z) instead of (x,y,z) cell = mp.Vector3(sr, 0, 0) m = 4 geometry = [ mp.Block(center=mp.Vector3(a + (w / 2)), size=mp.Vector3(w, 1e20, 1e20), material=mp.Medium(index=n)) ] # Finding a resonance mode with a high Q-value (calculated with Harminv) fcen = 0.15 # pulse center frequency df = 0.1 # pulse width (in frequency) sources = [ mp.Source(mp.GaussianSource(fcen, fwidth=df), mp.Hz, mp.Vector3(r + 0.1), amplitude=1) ] sim = mp.Simulation(cell_size=cell, geometry=geometry, boundary_layers=pml_layers, resolution=resolution, sources=sources, dimensions=dimensions, m=m) h = mp.Harminv(mp.Hz, mp.Vector3(r + 0.1), fcen, df) sim.run(mp.after_sources(h), until_after_sources=200) Harminv_freq_at_R = h.modes[0].freq sim.reset_meep() # now running the simulation that will be used with perturbation theory to calculate dw/dR fcen = Harminv_freq_at_R df = 0.01 sources = [ mp.Source(mp.GaussianSource(fcen, fwidth=df), mp.Hz, mp.Vector3(r + 0.1), amplitude=1) ] sim = mp.Simulation(cell_size=cell, geometry=geometry, boundary_layers=pml_layers, resolution=resolution, sources=sources, dimensions=dimensions, m=m) sim.run(until_after_sources=200) # now need to calculate the surface integrals that go into dw/dR. Fields parallel and perpendicular to the interface # AND at the inner and outer surfaces are treated differently, so each will be calculated separately. # section for fields at inner surface npts_inner = 10 angles_inner = 2 * np.pi / npts_inner * np.arange(npts_inner) deps_inner = 1 - n**2 deps_inv_inner = 1 - 1 / (n**2) # section for fields parallel to interface (Ez and Ep) parallel_fields_inner = [] for angle in angles_inner: point = mp.Vector3(a, angle) e_z_field = abs(sim.get_field_point(mp.Ez, point))**2 e_p_field = abs(sim.get_field_point(mp.Ep, point))**2 e_parallel_field = e_z_field + e_p_field # fields have to be multiplied by Δε e_parallel_field = deps_inner * e_parallel_field parallel_fields_inner.append(e_parallel_field) # section for fields perpendicular to interface (Er) perpendicular_fields_inner = [] for angle in angles_inner: point = mp.Vector3(a, angle) e_r_field = abs(sim.get_field_point(mp.Er, point))**2 e_perpendicular_field = e_r_field # fields have to be multiplied by Δ(1/ε) and ε**2 e_perpendicular_field = deps_inv_inner * (abs( sim.get_epsilon_point(point, Harminv_freq_at_R))** 2) * e_perpendicular_field perpendicular_fields_inner.append(e_perpendicular_field) # section for fields at outer surface npts_outer = npts_inner angles_outer = 2 * np.pi / npts_outer * np.arange(npts_outer) deps_outer = n**2 - 1 deps_inv_outer = -1 + 1 / (n**2) # section for fields parallel to interface (Ez and Ep) parallel_fields_outer = [] parallel_fields_outer = [] for angle in angles_outer: point = mp.Vector3(b, angle) e_z_field = abs(sim.get_field_point(mp.Ez, point))**2 e_p_field = abs(sim.get_field_point(mp.Ep, point))**2 e_parallel_field = e_z_field + e_p_field # fields have to be multiplied by Δε e_parallel_field = deps_outer * e_parallel_field parallel_fields_outer.append(e_parallel_field) # section for fields perpendicular to interface (Er) perpendicular_fields_outer = [] for angle in angles_inner: point = mp.Vector3(b, angle) e_r_field = abs(sim.get_field_point(mp.Er, point)) e_perpendicular_field = e_r_field**2 # fields have to be multiplied by Δ(1/ε) and ε**2 e_perpendicular_field = deps_inv_outer * (abs( sim.get_epsilon_point(point, Harminv_freq_at_R))** 2) * e_perpendicular_field perpendicular_fields_outer.append(e_perpendicular_field) numerator_surface_integral = 2 * np.pi * b * ( mean([mean(parallel_fields_inner), mean(parallel_fields_outer)]) - mean([ mean(perpendicular_fields_inner), mean(perpendicular_fields_outer) ])) denominator_surface_integral = sim.electric_energy_in_box( center=mp.Vector3((b + pad / 2) / 2), size=mp.Vector3(b + pad / 2)) perturb_theory_dw_dR = -Harminv_freq_at_R * numerator_surface_integral / ( 4 * denominator_surface_integral) center_diff_dw_dR = [] Harminv_freqs_at_R_plus_dR = [] drs = np.logspace(start=-3, stop=-1, num=10) for dr in drs: sim.reset_meep() w = 1 + dr # width of waveguide b = a + w print(f'The current dr is dr={dr}') if len(Harminv_freqs_at_R_plus_dR) == 0: fcen = Harminv_freq_at_R else: fcen = Harminv_freqs_at_R_plus_dR[-1] df = 0.01 sources = [ mp.Source(mp.GaussianSource(fcen, fwidth=df), mp.Hz, mp.Vector3(r + 0.1)) ] geometry = [ mp.Block(center=mp.Vector3(a + (w / 2)), size=mp.Vector3(w, 1e20, 1e20), material=mp.Medium(index=n)) ] sim = mp.Simulation(cell_size=cell, geometry=geometry, boundary_layers=pml_layers, resolution=resolution, sources=sources, dimensions=dimensions, m=m) h = mp.Harminv(mp.Hz, mp.Vector3(r + 0.1), fcen, df) sim.run(mp.after_sources(h), until_after_sources=200) Harminv_freq_at_R_plus_dR = h.modes[0].freq Harminv_freqs_at_R_plus_dR.append(Harminv_freq_at_R_plus_dR) dw_dR = (Harminv_freq_at_R_plus_dR - Harminv_freq_at_R) / dr center_diff_dw_dR.append(dw_dR) relative_errors_dw_dR = [ abs((dw_dR - perturb_theory_dw_dR) / dw_dR) for dw_dR in center_diff_dw_dR ] perturb_predicted_freqs_at_R_plus_dR = [ dr * perturb_theory_dw_dR + Harminv_freq_at_R for dr in drs ] relative_errors_freqs_at_R_plus_dR = [ abs((perturb_predicted_freqs_at_R_plus_dR[i] - Harminv_freqs_at_R_plus_dR[i]) / Harminv_freqs_at_R_plus_dR[i]) for i in range(len(Harminv_freqs_at_R_plus_dR)) ] if mp.am_master(): plt.figure(dpi=150) plt.loglog(drs, relative_errors_dw_dR, 'bo-', label='relative error') plt.grid(True, which='both', ls='-') plt.xlabel('perturbation amount $dr$') plt.ylabel('relative error between $dω/dR$') plt.legend(loc='upper right') plt.title( 'Comparison of Perturbation Theory and \nCenter-Difference Calculations in Finding $dω/dR$' ) plt.tight_layout() # plt.show() plt.savefig('ring_Hz_perturbation_theory.dw_dR_error.png') plt.clf() plt.figure(dpi=150) plt.loglog(drs, relative_errors_freqs_at_R_plus_dR, 'bo-', label='relative error') plt.grid(True, which='both', ls='-') plt.xlabel('perturbation amount $dr$') plt.ylabel('relative error between $ω(R+dR)$') plt.legend(loc='upper left') plt.title( 'Comparison of resonance frequencies at $R+dR$ predicted by\nperturbation theory and found with Harminv' ) plt.tight_layout() # plt.show() plt.savefig('ring_Hz_perturbation_theory.freqs_error.png') plt.clf()
def main(args): resolution = 30 # pixels/μm Si = mp.Medium(index=3.45) dpml = 1.0 pml_layers = [mp.PML(dpml)] sx = 5 sy = 3 cell = mp.Vector3(sx + 2 * dpml, sy + 2 * dpml, 0) a = 1.0 # waveguide width s = args.s # waveguide separation distance 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) ] xodd = args.xodd symmetries = [ mp.Mirror(mp.X, phase=-1.0 if xodd else 1.0), mp.Mirror(mp.Y, phase=-1.0) ] k_point = mp.Vector3(z=0.5) fcen = 0.22 df = 0.06 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)), 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)), 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=5000) sim.display_fluxes(wvg_flux) sim.display_forces(wvg_force)
resolution=10, symmetries=[mp.Mirror(mp.Y)], boundary_layers=[mp.PML(dpml)], filename_prefix=prefix) h = mp.Harminv(mp.Ez, mp.Vector3(r + 0.1), fcen, df) if not os.path.isdir(path): sav.new_dir(path) os.chdir(path) #%% SIMULATION: FREQUENCY start = time() sim.run(mp.at_beginning(mp.output_epsilon), mp.after_sources(h), until_after_sources=300) end = time() print("Enlapsed time: {:.2f}".format(end - start)) #%% SIMULATION: FIELDS freqs = [h.modes[i][0] for i in range(len(h.modes))] label = lambda w: "Freq-{:.3f}".format(w) path_freqs = [] start = [start, time()] for i, w in enumerate(freqs): sim.reset_meep()
simulation.load_minus_flux_data(reflectionFluxMonitor, incidentFluxToSubtract) def updateField(sim): global fieldData fieldEx = np.real( sim.get_array(center=mp.Vector3(0, 0, 0), size=cellSize, component=mp.Ex)) fieldData = np.vstack((fieldData, fieldEx)) simulation.run( #mp.at_every(animationTimestepDuration, updateField), mp.after_sources( mp.Harminv(mp.Ex, mp.Vector3(0, 0, layerCenters[10]), frequency, frequencyWidth)), until_after_sources=400) incidentFlux = np.array(mp.get_fluxes(incidentFluxMonitor)) transmittedFlux = np.array(mp.get_fluxes(transmissionFluxMonitor)) reflectedFlux = np.array(mp.get_fluxes(reflectionFluxMonitor)) R = -reflectedFlux / incidentFlux T = transmittedFlux / incidentFlux #print(T) #print(R) #print(R + T) #frequencies = np.array(mp.get_flux_freqs(reflectionFluxMonitor)) #reflectionSpectraFigure = plt.figure() #reflectionSpectraAxes = plt.axes(xlim=(frequency-frequencyWidth/2, frequency+frequencyWidth/2),ylim=(0, 1))
df = 0.010 # pulse width (in frequency) sources = [mp.Source(src=mp.GaussianSource(fcen, fwidth=df), component=mp.Ez, center=mp.Vector3(r + 0.1))] # exploit the mirror symmetry in structure+source: symmetries = [mp.Mirror(mp.Y)] sim = mp.Simulation(cell_size=cell, resolution=resolution, geometry=geometry, boundary_layers=pml_layers, sources=sources, symmetries=symmetries) h1 = mp.Harminv(mp.Ez, mp.Vector3(r + 0.1), fcen, df) sim.run(mp.after_sources(h1), until_after_sources=300) fields2 = sim.fields sim.reset_meep() fcen = 0.236 h2 = mp.Harminv(mp.Ez, mp.Vector3(r + 0.1), fcen, df) sim.run(mp.after_sources(h2), until_after_sources=300) def overlap_integral(r, ez1, ez2): return ez1.conjugate() * ez2 res = sim.integrate2_field_function(fields2, [mp.Ez], [mp.Ez], overlap_integral) print("overlap integral of mode at w and 2w: {}".format(abs(res)))