def init_and_run(self, test_type): cell = mp.Vector3(1, 1) resolution = 60 fcen = 0.8 df = 0.02 cen = mp.Vector3(0.1, 0.2) sz = mp.Vector3(0.3, 0.2) data_dir = os.path.join(os.path.realpath(os.path.dirname(__file__)), 'data') amp_file = os.path.join(data_dir, 'amp_func_file') amp_file += ':amp_data' if test_type == 'file': sources = [mp.Source(mp.ContinuousSource(fcen, fwidth=df), component=mp.Ez, center=cen, size=sz, amp_func_file=amp_file)] elif test_type == 'func': sources = [mp.Source(mp.ContinuousSource(fcen, fwidth=df), component=mp.Ez, center=cen, size=sz, amp_func=amp_fun)] elif test_type == 'arr': sources = [mp.Source(mp.ContinuousSource(fcen, fwidth=df), component=mp.Ez, center=cen, size=sz, amp_data=self.amp_data)] sim = mp.Simulation(cell_size=cell, resolution=resolution, sources=sources) sim.run(until=200) return sim.get_field_point(mp.Ez, mp.Vector3())
def get_flux_on_metalens(metalens): # Setup the MEEP objects cell = mp.Vector3(metalens['sim_cell_width'], metalens['sim_cell_height']) # All around the simulation cell pml_layers = [mp.PML(metalens['pml_width'])] # Set up the sources # sources = [mp.Source(src=mp.ContinuousSource( # wavelength=metalens['wavelength'], # width=metalens['source_width'] # ), # component=mp.Ez, # center=mp.Vector3(0, metalens['source_coord']), # size=mp.Vector3(2 * metalens['ws'], 0), # amp_func=far_ez_source_amp_func(metalens))] sources = [ mp.Source(src=mp.ContinuousSource(wavelength=metalens['wavelength'], width=metalens['source_width']), component=mp.Ex, amp_func=in_plane_dip_amp_func_Ex(metalens), center=mp.Vector3(0, metalens['source_coord']), size=mp.Vector3(metalens['sim_cell_width'], 0)), mp.Source(src=mp.ContinuousSource(wavelength=metalens['wavelength'], width=metalens['source_width']), component=mp.Hz, amp_func=in_plane_dip_amp_func_Hz(metalens), center=mp.Vector3(0, metalens['source_coord']), size=mp.Vector3(metalens['sim_cell_width'], 0)) ] # Set up the symmetries syms = [] if metalens['x_mirror_symmetry']: syms.append(mp.Mirror(mp.X)) sim = mp.Simulation(cell_size=cell, boundary_layers=pml_layers, geometry=metalens['flux_geometry'], force_complex_fields=metalens['complex_fields'], symmetries=syms, sources=sources, resolution=metalens['resolution']) mp.quiet(metalens['quiet']) sim.init_sim() sim.run(until=metalens['simulation_time']) fields = { 'Ex': sim.get_array(component=mp.Ex).transpose(), 'Ey': sim.get_array(component=mp.Ey).transpose(), 'Hz': sim.get_array(component=mp.Hz).transpose() } transverse_axis = (np.linspace(-metalens['sim_cell_width'] / 2, metalens['sim_cell_width'] / 2, fields['Hz'].shape[1])) optical_axis = np.linspace(-metalens['sim_cell_height'] / 2, metalens['sim_cell_height'] / 2, fields['Hz'].shape[0]) interface_index = np.argmin( np.abs(optical_axis - metalens['interface_coord'])) Sy = (np.real(-np.conjugate(fields['Ex']) * fields['Hz'])[interface_index] )[np.abs(transverse_axis) <= metalens['R']] return np.sum(Sy)
def test_check_material_frequencies(self): mat = mp.Medium(valid_freq_range=mp.FreqRange(min=10, max=20)) invalid_sources = [ [mp.Source(mp.GaussianSource(5, fwidth=1), mp.Ez, mp.Vector3())], [mp.Source(mp.ContinuousSource(10, fwidth=1), mp.Ez, mp.Vector3())], [mp.Source(mp.GaussianSource(10, width=1), mp.Ez, mp.Vector3())], [mp.Source(mp.GaussianSource(20, width=1), mp.Ez, mp.Vector3())], ] cell_size = mp.Vector3(5, 5) resolution = 5 def check_warnings(sim, should_warn=True): with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") sim.run(until=5) if should_warn: self.assertEqual(len(w), 1) self.assertIn("material", str(w[-1].message)) else: self.assertEqual(len(w), 0) geom = [mp.Sphere(0.2, material=mat)] for s in invalid_sources: # Check for invalid extra_materials sim = mp.Simulation(cell_size=cell_size, resolution=resolution, sources=s, extra_materials=[mat]) check_warnings(sim) # Check for invalid geometry materials sim = mp.Simulation(cell_size=cell_size, resolution=resolution, sources=s, geometry=geom) check_warnings(sim) valid_sources = [ [mp.Source(mp.GaussianSource(15, fwidth=1), mp.Ez, mp.Vector3())], [mp.Source(mp.ContinuousSource(15, width=5), mp.Ez, mp.Vector3())] ] for s in valid_sources: sim = mp.Simulation(cell_size=cell_size, resolution=resolution, sources=s, extra_materials=[mat]) check_warnings(sim, False) # Check DFT frequencies # Invalid extra_materials sim = mp.Simulation(cell_size=cell_size, resolution=resolution, sources=valid_sources[0], extra_materials=[mat]) fregion = mp.FluxRegion(center=mp.Vector3(0, 1), size=mp.Vector3(2, 2), direction=mp.X) sim.add_flux(18, 6, 2, fregion) check_warnings(sim) # Invalid geometry material sim = mp.Simulation(cell_size=cell_size, resolution=resolution, sources=valid_sources[0], geometry=geom) sim.add_flux(18, 6, 2, fregion) check_warnings(sim)
def runSimulation(cell, geometry, pml_layers, frequency): print("We are running at:", frequency) resolution = simulation.resolution sim = mp.Simulation(cell_size=cell, boundary_layers=pml_layers, geometry=geometry, resolution=resolution, progress_interval=10000, sources=[ mp.Source(mp.ContinuousSource(frequency=frequency), center=mp.Vector3(source.x, source.y, 0), component=mp.Ex) ]) sim.use_output_directory() if (simulation.generatePNG == True): sim.run(mp.to_appended("ez", mp.at_every(1.0, mp.output_efield_z)), until=simulation.simulationTimeSteps) print("After Simulation") # createPNG() # pngToGIF() #deleteH5Files() else: sim.run(until=simulation.simulationTimeSteps) upperPortVolume = mp.Volume(center=mp.Vector3(upperPort.x, upperPort.y, 0), size=mp.Vector3(1, 1, 0)) lowerPortVolume = mp.Volume(center=mp.Vector3(lowerPort.x, lowerPort.y, 0), size=mp.Vector3(1, 1, 0)) lowerPortEnergy = sim.field_energy_in_box(box=lowerPortVolume, d=mp.Ex) upperPortEnergy = sim.field_energy_in_box(box=upperPortVolume, d=mp.Ex) print(lowerPortEnergy, "lowerPortEnergy") print(upperPortEnergy, "upperPortEnergy") return lowerPortEnergy, upperPortEnergy
def setUp(self): cell = mp.Vector3(16, 8) geometry = [ mp.Block(center=mp.Vector3(), size=mp.Vector3(mp.inf, 1, mp.inf), material=mp.Medium(epsilon=12)), mp.Block(center=mp.Vector3(y=0.3), size=mp.Vector3(mp.inf, 0.1, mp.inf), material=mp.Medium()) ] sources = [ mp.EigenModeSource(src=mp.ContinuousSource(0.15), size=mp.Vector3(y=6), center=mp.Vector3(x=-5), component=mp.Dielectric, eig_parity=mp.ODD_Z) ] pml_layers = [mp.PML(1.0)] self.sim = mp.Simulation(cell_size=cell, geometry=geometry, sources=sources, boundary_layers=pml_layers, force_complex_fields=True, resolution=10)
def test_synchronized_magnetic(self): # Issue 309 cell = mp.Vector3(16, 8, 0) geometry = [ mp.Block(mp.Vector3(1e20, 1, 1e20), center=mp.Vector3(0, 0), material=mp.Medium(epsilon=12)) ] sources = [ mp.Source(mp.ContinuousSource(frequency=0.15), component=mp.Ez, center=mp.Vector3(-7, 0)) ] pml_layers = [mp.PML(1.0)] resolution = 10 sim = mp.Simulation(cell_size=cell, boundary_layers=pml_layers, geometry=geometry, sources=sources, resolution=resolution) sim.run(mp.synchronized_magnetic(mp.output_bfield_y), until=10)
def test_physical(self): a = 10.0 ymax = 3.0 xmax = 8.0 dx = 2.0 w = 0.30 cell_size = mp.Vector3(xmax, ymax) pml_layers = [mp.PML(ymax / 3.0)] sources = [mp.Source(src=mp.ContinuousSource(w), component=mp.Ez, center=mp.Vector3(-dx), size=mp.Vector3())] sim = mp.Simulation(cell_size=cell_size, resolution=a, boundary_layers=pml_layers, sources=sources, force_complex_fields=True) sim.init_sim() sim.solve_cw(tol=1e-6) p1 = mp.Vector3() p2 = mp.Vector3(dx) amp1 = sim.get_field_point(mp.Ez, p1) amp2 = sim.get_field_point(mp.Ez, p2) ratio = abs(amp1) / abs(amp2) ratio = ratio ** 2 # in 2d, decay is ~1/sqrt(r), so square to get 1/r fail_fmt = "Failed: amp1 = ({}, {}), amp2 = ({}, {})\nabs(amp1/amp2){} = {}, too far from 2.0" fail_msg = fail_fmt.format(amp1.real, amp1, amp2.real, amp2, "^2", ratio) self.assertTrue(ratio <= 2.12 and ratio >= 1.88, fail_msg)
def check_rotation(self, mat, L, fsrc, zsrc, resolution, tmax, zout, kpred, tol=1.5): cell = mp.Vector3(0, 0, L) pml_layers = [mp.PML(thickness=1.0, direction=mp.Z)] sources = [mp.Source(mp.ContinuousSource(frequency=fsrc), component=mp.Ex, center=mp.Vector3(0, 0, zsrc))] self.sim = mp.Simulation(cell_size=cell, geometry=[], sources=sources, boundary_layers=pml_layers, default_material=mat, resolution=resolution) record_vol = mp.Volume(center=mp.Vector3(0, 0, zout)) record_Ex, record_Ey, record_t = [], [], [] def record_ex_ey(sim): record_Ex.append(sim.get_array(vol=record_vol, component=mp.Ex)) record_Ey.append(sim.get_array(vol=record_vol, component=mp.Ey)) record_t.append(sim.meep_time()) self.sim.run(mp.after_time(0.5*tmax, mp.at_every(1e-6, record_ex_ey)), until=tmax) ex_rel = np.amax(abs(np.fft.fft(record_Ex))) ey_rel = np.amax(abs(np.fft.fft(record_Ey))) result = np.arctan2(ey_rel, ex_rel) * 180/np.pi Ex_theory = np.abs(np.cos(kpred * (zout - zsrc)).real) Ey_theory = np.abs(np.sin(kpred * (zout - zsrc)).real) expected = np.arctan2(Ey_theory, Ex_theory) * 180/np.pi print("Rotation angle (in degrees): {}, expected {}\n".format(result, expected)) np.testing.assert_allclose(expected, result, atol=tol)
def create_waveguide_source(self, wavelength, pos, width, direction='+x', comp='y'): # parity parity = mp.ODD_Z if comp == 'z' else mp.EVEN_Z # size size = mp.Vector3(y=width) if 'x' in direction else mp.Vector3(x=width) # kpoints angles = {'+x': 0, '+y': 90, '-x': 180, '-y': 270} if direction in angles: angle = np.radians(angles[direction]) direction = mp.Vector3(0.4).rotate(mp.Vector3(z=1), angle) s = mp.EigenModeSource(src=mp.ContinuousSource(wavelength=wavelength), center=mp.Vector3(*pos), size=size, direction=mp.NO_DIRECTION, eig_kpoint=direction, eig_band=1, eig_parity=parity, eig_match_freq=True, component=mp.ALL_COMPONENTS) self.sources.append(s)
def __init__(self, fq, pos, size, component): self.pos = pos self.size = size self.comp = component mp.Source.__init__(self, mp.ContinuousSource(fq), component=self._get_meep_comp(self.comp), center=mp.Vector3(*self.pos), size=mp.Vector3(*self.size))
def setUp(self): s = 11 dpml = 1 sxy = s + 2 * dpml cell = mp.Vector3(sxy, sxy, 0) pml_layers = [mp.PML(dpml)] resolution = 10 def pw_amp(k, x0): def _pw_amp(x): return cmath.exp(1j * k.dot(x + x0)) return _pw_amp fcen = 0.8 df = 0.02 kdir = mp.Vector3(1, 1) self.k = kdir.unit().scale(2 * math.pi * fcen) sources = [ mp.Source( mp.ContinuousSource(fcen, fwidth=df), component=mp.Ez, center=mp.Vector3(-0.5 * s, 0), size=mp.Vector3(0, s), amp_func=pw_amp(self.k, mp.Vector3(x=-0.5 * s)) ), mp.Source( mp.ContinuousSource(fcen, fwidth=df), component=mp.Ez, center=mp.Vector3(0, -0.5 * s), size=mp.Vector3(s, 0), amp_func=pw_amp(self.k, mp.Vector3(y=-0.5 * s)) ) ] self.sim = mp.Simulation( cell_size=cell, sources=sources, boundary_layers=pml_layers, resolution=resolution ) self.s = s
def __init__(self, dir_name, wavelength, cyt_absorb): self.base_directory = base_directory + str(dir_name) self.wavelength = wavelength self.cyt_absorb = cyt_absorb self.frequency = 1 / wavelength # Calculate wavelengths dependent on RI self.wavelength_in_media = wavelength / ri_media self.wavelength_in_cytoplasm = wavelength / ri_cytoplasm max_freq = self.frequency - 0.01 min_freq = self.frequency + 0.01 self.pulse_width = abs(max_freq - min_freq) cell = mp.Vector3(sxx, sxy, 0) pml_layers = [mp.PML(dpml)] cytoplasm_material = mp.Medium(index=ri_cytoplasm, D_conductivity=2 * math.pi * self.frequency * (cyt_absorb / (ri_cytoplasm ** 2))) cytoplasm_region = mp.Sphere(radius=cell_radius, center=mp.Vector3(0, 0), material=cytoplasm_material) geometry = [cytoplasm_region] # Sources kdir = mp.Vector3(1, 0, 0) # direction of k (length is irrelevant) n = ri_media # refractive index of material containing the source k = kdir.unit().scale(2 * math.pi * self.frequency * n) # k with correct length def pw_amp(k, x0): def _pw_amp(x): return cmath.exp(1j * k.dot(x + x0)) return _pw_amp source = [ mp.Source( mp.ContinuousSource(frequency=self.frequency, fwidth=self.pulse_width), # along x axis component=mp.Ez, center=mp.Vector3(-0.5 * simulation_size, 0), # x, ,y ,z size=mp.Vector3(0, sxy, 0), amp_func=pw_amp(k, mp.Vector3(x=-0.5 * simulation_size)) ) ] sim = mp.Simulation( cell_size=cell, sources=source, boundary_layers=pml_layers, resolution=resolution, geometry=geometry, default_material=mp.Medium(index=ri_media), force_complex_fields=complex_f, eps_averaging=eps_av, ) sim.use_output_directory(self.base_directory) sim.run(mp.at_every(0.6, mp.output_png(mp.Ez, "-Zc/data/home/bt16268/simInput/customColour.txt")), until=t)
def build_src(sx, sy, f, alpha): width = 1000 df = 1 / width #use plane waves as the incident beam spot is large relative to structure #both a Ez and Hz source are used here to generate all fields (unpolarized) src = [ mp.Source(mp.ContinuousSource(f), component=mp.Hz, center=mp.Vector3(y=-sy / 2), size=mp.Vector3(sx), amplitude=1), mp.Source(mp.ContinuousSource(f), component=mp.Ez, center=mp.Vector3(y=-sy / 2), size=mp.Vector3(sx), amplitude=1) ] return src
def set_sources(self, args: dict): if not args: args['frequency'] = 0.15 args['center'] = {"x": -7, "y": 0} self.sim_data['sources'] = [ mp.Source(mp.ContinuousSource(frequency=args['frequency']), component=mp.Ez, center=mp.Vector3(args['center']['x'], args['center']['y'])) ]
def example_bend_coupling(): from gdshelpers.parts.waveguide import Waveguide waveguide_straight = Waveguide((0, 0), 0, width=1) waveguide_straight.add_straight_segment(5) bend_port = waveguide_straight.current_port.parallel_offset(1.1) waveguides_bend_1 = Waveguide.make_at_port(bend_port) waveguides_bend_1.add_bend(angle=np.pi / 2, radius=15, n_points=30) waveguides_bend_2 = Waveguide.make_at_port(bend_port.inverted_direction) waveguides_bend_2.add_bend(angle=-np.pi / 5, radius=15, n_points=20) waveguide_straight.add_straight_segment(5) wgs = [ Waveguide.make_at_port(port).add_straight_segment(40) for port in [ waveguide_straight.in_port, waveguide_straight.current_port, waveguides_bend_1.current_port, waveguides_bend_2.current_port ] ] sim = Simulation(resolution=20, reduce_to_2d=True, padding=2, pml_thickness=.5) sim.add_structure([waveguide_straight, waveguides_bend_1], wgs + [waveguides_bend_2], mp.Medium(index=1.666), z_min=0, z_max=.33) # GaussianSource or ContinousSource source = sim.add_eigenmode_source( mp.ContinuousSource(wavelength=1.55, width=2), waveguide_straight.in_port.longitudinal_offset(1), z=0.33 / 2, height=1, eig_band=2) sim.init_sim(subpixel_maxeval=0) # subpixel_maxeval=0 for quick testing monitors_out = [ sim.add_eigenmode_monitor(port, 1.55, 2, 1, z=0.33 / 2, height=1) for port in [waveguide_straight.current_port, waveguides_bend_1.current_port] ] # sim.plot(mp.Hz) sim.run(until=150) sim.plot(mp.Hz) transmissions = [ np.abs( sim.get_eigenmode_coefficients(monitors_out[i], [2]).alpha[0, 0, 0])**2 / source.eig_power(1 / 1.55) for i in range(2) ] print('transmission in bus waveguide: {:.3f}'.format(transmissions[0])) print('transmission to bent waveguide: {:.3f}'.format(transmissions[1]))
def init_and_run(self, file_func): cell = mp.Vector3(1, 1) resolution = 10 fcen = 0.8 df = 0.02 def ones(p): return 1 + 1j if file_func: fname = os.path.join(data_dir, 'amp_func_file.h5') dset = 'amp_data' sources = [mp.Source(mp.ContinuousSource(fcen, fwidth=df), component=mp.Ez, center=mp.Vector3(), amp_func_file=fname, amp_func_dataset=dset)] else: sources = [mp.Source(mp.ContinuousSource(fcen, fwidth=df), component=mp.Ez, center=mp.Vector3(), amp_func=ones)] sim = mp.Simulation(cell_size=cell, resolution=resolution, sources=sources) sim.run(until=200) return sim.get_field_point(mp.Ez, mp.Vector3())
def simulate_metalens(metalens): # Setup the MEEP objects cell = mp.Vector3(metalens['sim_cell_width'], metalens['sim_cell_height']) # All around the simulation cell pml_layers = [mp.PML(metalens['pml_width'])] # Set up the sources sources = [ mp.Source(src=mp.ContinuousSource(wavelength=metalens['wavelength'], width=metalens['source_width']), component=mp.Ez, center=mp.Vector3(0, metalens['source_coordinate']), size=mp.Vector3(2 * metalens['ws'], 0), amp_func=far_ez_source_amp_func(metalens)) ] # Set up the symmetries syms = [] if metalens['x_mirror_symmetry']: syms.append(mp.Mirror(mp.X)) sim = mp.Simulation(cell_size=cell, boundary_layers=pml_layers, geometry=metalens['geometry'], force_complex_fields=metalens['complex_fields'], symmetries=syms, sources=sources, resolution=metalens['resolution']) start_time = time.time() metalens['run_date'] = ( datetime.datetime.now().strftime("%b %d %Y at %H:%M:%S")) sim.init_sim() # Branch if saving for making an animation if metalens['save_output']: sim.run(mp.to_appended( "ez-{sim_id}".format(**metalens), mp.at_every(metalens['simulation_time'] / 1000., mp.output_efield_z)), until=metalens['simulation_time']) else: sim.run(until=metalens['simulation_time']) # Compute the clock run time and grab the fields metalens['run_time_in_s'] = time.time() - start_time metalens['fields'] = { 'Ez': sim.get_array(component=mp.Ez).transpose(), 'Bx': sim.get_array(component=mp.Bx).transpose(), 'By': sim.get_array(component=mp.By).transpose() } # Dump the result to disk pickle.dump( metalens, open('%smetalens-%s.pkl' % (datadir, metalens['sim_id']), 'wb')) return metalens
def __init__(self, dir_name, wavelength, cyt_absorb): self.base_directory = base_directory + str(dir_name) self.wavelength = wavelength self.cyt_absorb = cyt_absorb self.frequency = 1 / wavelength # Calculate wavelengths dependent on RI self.wavelength_in_media = wavelength / ri_media self.wavelength_in_cytoplasm = wavelength / ri_cytoplasm max_freq = self.frequency - 0.01 min_freq = self.frequency + 0.01 self.pulse_width = abs(max_freq - min_freq) cell = mp.Vector3(sxx, sxy, 0) pml_layers = [mp.PML(dpml)] cytoplasm_material = mp.Medium(index=ri_cytoplasm, D_conductivity=2 * math.pi * self.frequency * (cyt_absorb / (ri_cytoplasm**2))) cytoplasm_region = mp.Sphere(radius=cell_radius, center=mp.Vector3(0, 0), material=cytoplasm_material) geometry = [] source = [ mp.Source(mp.ContinuousSource(frequency=self.frequency, fwidth=self.pulse_width), compone=mp.Ez, center=(mp.Vector3(-0.5 * simulation_size, 0)), size=mp.Vector3(0, 10)) ] sim = mp.Simulation( cell_size=cell, sources=source, boundary_layers=pml_layers, resolution=resolution, geometry=geometry, default_material=mp.Medium(index=ri_media), force_complex_fields=complex_f, eps_averaging=eps_av, ) sim.use_output_directory(self.base_directory) sim.run(mp.at_every( 0.6, mp.output_png(mp.Ez, "-Zc/data/home/bt16268/simInput/customColour.txt")), until=t)
def createDiffractionSlit(): cell = mp.Vector3(globalVariables.waveguideXSize, globalVariables.waveguideYSize, 0) geometry = [mp.Block(mp.Vector3(1e20, 1, 1e20), center=mp.Vector3(0, 0), material=mp.Medium(epsilon=globalVariables.epsilonOfMaterial)), mp.Block(mp.Vector3(globalVariables.blockXSize,globalVariables.blockYSize,0), center=mp.Vector3(0,(globalVariables.blockYSize-globalVariables.waveguideYSize)/2.0,0), material=mp.Medium(epsilon=globalVariables.epsilonOfBoundary)), mp.Block(mp.Vector3(globalVariables.blockXSize,globalVariables.blockYSize,0), center=mp.Vector3(0,(globalVariables.waveguideYSize-globalVariables.blockYSize)/2.0,0), material=mp.Medium(epsilon=globalVariables.epsilonOfBoundary))] sources = [mp.Source(mp.ContinuousSource(frequency=0.15), component=mp.Ez, center=mp.Vector3(-globalVariables.waveguideXSize/2+1,0,0))] pml_layers = [mp.PML(1.0)] return cell,geometry,sources,pml_layers
def run_sim(rot_angle=0): resolution = 50 # pixels/μm cell_size = mp.Vector3(14, 10, 0) pml_layers = [mp.PML(thickness=2, direction=mp.X)] fsrc = 1.0 # frequency of planewave (wavelength = 1/fsrc) n = 1.5 # refractive index of homogeneous material default_material = mp.Medium(index=n) k_point = mp.Vector3(fsrc * n).rotate(mp.Vector3(z=1), rot_angle) sources = [ mp.EigenModeSource( src=mp.ContinuousSource(fsrc), center=mp.Vector3(), size=mp.Vector3(y=10), direction=mp.AUTOMATIC if rot_angle == 0 else mp.NO_DIRECTION, eig_kpoint=k_point, eig_band=1, eig_parity=mp.EVEN_Y + mp.ODD_Z if rot_angle == 0 else mp.ODD_Z, eig_match_freq=True) ] sim = mp.Simulation(cell_size=cell_size, resolution=resolution, boundary_layers=pml_layers, sources=sources, k_point=k_point, default_material=default_material, symmetries=[mp.Mirror(mp.Y)] if rot_angle == 0 else []) sim.run(until=100) plt.figure(dpi=100) sim.plot2D(fields=mp.Ez) plt.show()
def test_integrated_source(self): sources = [ mp.Source(mp.ContinuousSource(1, is_integrated=True), center=mp.Vector3(-2), size=mp.Vector3(y=6), component=mp.Ez) ] sim = mp.Simulation(resolution=20, cell_size=(6, 6), boundary_layers=[mp.PML(thickness=1)], sources=sources, k_point=mp.Vector3()) sim.run(until=30) # field in mid-plane should be nearly constant, # so compute its normalized std. dev. and check << 1 ez = sim.get_array(mp.Ez, center=mp.Vector3(2), size=mp.Vector3(y=6)) std = np.std(ez) / np.sqrt(np.mean(ez**2)) print("std = ", std) self.assertAlmostEqual(std, 0.0, places=4 if mp.is_single_precision() else 8)
def createDiffractionGrating(): cell = mp.Vector3(globalVariables.waveguideXSize, globalVariables.waveguideYSize, 0) geometry = [mp.Block(mp.Vector3(1e20, 1, 1e20), center=mp.Vector3(0, 0), material=mp.Medium(epsilon=globalVariables.epsilonOfMaterial))] for i in range(globalVariables.numberOfSlitsForDiffractionGrating+1): centerXValue , centerYValue = diffractionGratingBlockCenter(i) #centerXValue = np.round(centerXValue) #centerYValue = np.round(centerYValue) blockXSize , blockYSize = diffractionGratingBlockSize() #blockXSize = np.round(blockXSize) #blockYSize = np.round(blockYSize) geometry.append(mp.Block(mp.Vector3(blockXSize,blockYSize,0), center=mp.Vector3(centerXValue,centerYValue,0), material=mp.Medium(epsilon=globalVariables.epsilonOfBoundary))) print(len(geometry),"THIS IS LEN GEOMEETRY") sources = [mp.Source(mp.ContinuousSource(frequency=0.15), component=mp.Ez, center=mp.Vector3(-globalVariables.waveguideXSize/2+1,0,0))] pml_layers = [mp.PML(1.0)] return cell,geometry,sources,pml_layers
cell = mp.Vector3(16, 16, 0) geometry = [ mp.Block(mp.Vector3(12, 1, mp.inf), center=mp.Vector3(-2.5, -3.5), material=mp.Medium(epsilon=12)), mp.Block(mp.Vector3(1, 12, mp.inf), center=mp.Vector3(3.5, 2), material=mp.Medium(epsilon=12)) ] pml_layers = [mp.PML(1.0)] sources = [ mp.Source(mp.ContinuousSource(wavelength=2 * (11 * 0.5), width=20), component=mp.Ez, center=mp.Vector3(-7, -3.5), size=mp.Vector3(0, 1)) ] resolution = 10 sim = mp.Simulation(cell_size=cell, boundary_layers=pml_layers, geometry=geometry, sources=sources, resolution=resolution) sim.run(mp.at_beginning(mp.output_epsilon), mp.at_beginning(mp.output_mu),
def setup_sim(zDim=0): cell = mp.Vector3(16, 8, zDim) # A simple waveguide geometry = [ mp.Block(mp.Vector3(mp.inf, 1, 1), center=mp.Vector3(), material=mp.Medium(epsilon=12)) ] # Add point sources sources = [ mp.Source(mp.ContinuousSource(frequency=0.15), component=mp.Ez, center=mp.Vector3(-5, 0), size=mp.Vector3(0, 0, 2)), mp.Source(mp.ContinuousSource(frequency=0.15), component=mp.Ez, center=mp.Vector3(0, 2), size=mp.Vector3(0, 0, 2)), mp.Source(mp.ContinuousSource(frequency=0.15), component=mp.Ez, center=mp.Vector3(-1, 1), size=mp.Vector3(0, 0, 2)), mp.Source(mp.ContinuousSource(frequency=0.15), component=mp.Ez, center=mp.Vector3(-2, -2, 1), size=mp.Vector3(0, 0, 0)), ] # Add line sources sources += [ mp.Source(mp.ContinuousSource(frequency=0.15), component=mp.Ez, size=mp.Vector3(0, 2, 2), center=mp.Vector3(-6, 0)), mp.Source(mp.ContinuousSource(frequency=0.15), component=mp.Ez, size=mp.Vector3(0, 2, 2), center=mp.Vector3(0, 1)) ] # Add plane sources sources += [ mp.Source(mp.ContinuousSource(frequency=0.15), component=mp.Ez, size=mp.Vector3(2, 2, 2), center=mp.Vector3(-3, 0)), mp.Source(mp.ContinuousSource(frequency=0.15), component=mp.Ez, size=mp.Vector3(2, 2, 2), center=mp.Vector3(0, -2)) ] # Different pml layers pml_layers = [ mp.PML(2.0, mp.X), mp.PML(1.0, mp.Y, mp.Low), mp.PML(1.5, mp.Y, mp.High) ] if zDim > 0: pml_layers += [mp.PML(1.5, mp.Z)] resolution = 10 sim = mp.Simulation(cell_size=cell, boundary_layers=pml_layers, geometry=geometry, sources=sources, resolution=resolution) # Line monitor sim.add_flux( 1, 0, 1, mp.FluxRegion(center=mp.Vector3(5, 0, 0), size=mp.Vector3(0, 4, 4), direction=mp.X)) # Plane monitor sim.add_flux( 1, 0, 1, mp.FluxRegion(center=mp.Vector3(2, 0, 0), size=mp.Vector3(4, 4, 4), direction=mp.X)) return sim
n = 3.4 w = 1 r = 1 pad = 4 dpml = 2 sxy = 2 * (r + w + pad + dpml) vol = mp.Volume(mp.Vector3(), size=mp.Vector3(sxy - 2 * dpml, sxy - 2 * dpml)) c1 = mp.Cylinder(radius=r + w, material=mp.Medium(index=n)) c2 = mp.Cylinder(radius=r) fcen = 0.118 df = 0.08 src = [ mp.Source(mp.ContinuousSource(fcen, fwidth=df), component=mp.Ez, center=mp.Vector3(r + 0.1)) ] sim = mp.Simulation(cell_size=mp.Vector3(sxy, sxy), geometry=[c1, c2], sources=src, resolution=10, force_complex_fields=True, symmetries=[mp.Mirror(mp.Y)], boundary_layers=[mp.PML(dpml)]) num_tols = 5 tols = np.power(10, np.arange(-8.0, -8.0 - num_tols, -1.0)) ez_dat = np.zeros((122, 122, num_tols), dtype=np.complex_)
mp.GyrotropicLorentzianSusceptibility(frequency=f0, gamma=gamma, sigma=sn, bias=mp.Vector3(0, 0, b0)) ] mat = mp.Medium(epsilon=epsn, mu=1, E_susceptibilities=susc) # Set up and run the Meep simulation: tmax = 100 L = 20.0 cell = mp.Vector3(0, 0, L) fsrc, src_z = 0.8, -8.5 pml_layers = [mp.PML(thickness=1.0, direction=mp.Z)] sources = [ mp.Source(mp.ContinuousSource(frequency=fsrc), component=mp.Ex, center=mp.Vector3(0, 0, src_z)) ] sim = mp.Simulation(cell_size=cell, geometry=[], sources=sources, boundary_layers=pml_layers, default_material=mat, resolution=50) sim.run(until=tmax) # Plot results: import numpy as np import matplotlib.pyplot as plt
sigma = 1.5 def gaussian_beam(sigma, k, x0): def _gaussian_beam(x): return cmath.exp(1j * 2 * np.pi * k.dot(x - x0) - (x - x0).dot(x - x0) / (2 * sigma**2)) return _gaussian_beam src_center = mp.Vector3(0, 0, 0.5 * cell_size.z - 2 * dpml) sources = [ mp.Source(src=mp.ContinuousSource(fcen, fwidth=0.2 * fcen, start_time=10, end_time=15), component=mp.Ez, center=src_center, size=mp.Vector3(cell_size.x, cell_size.y), amp_func=gaussian_beam(sigma, k, src_center)) ] sim = mp.Simulation(cell_size=cell_size, sources=sources, boundary_layers=pml_layers, resolution=resolution) sim.run(until=20) x_plane = mp.Volume(center=mp.Vector3(0, 0, 0),
def notch(w): print("#----------------------------------------") print("NOTCH WIDTH: %s nanometers" % (w * 1000)) print("#----------------------------------------") # w is the width of the notch in the waveguide angrad = ang * pi / 180 bottomoffset = e * h / tan(angrad) vertices = [ mp.Vector3(w / 2 + bottomoffset, (.5 + e) * h), mp.Vector3(-w / 2 - bottomoffset, (.5 + e) * h), mp.Vector3(-w / 2 + bottomoffset, (.5 - e) * h), mp.Vector3(w / 2 - bottomoffset, (.5 - e) * h) ] if bottomoffset > w / 2: ratio = (w / 2) / bottomoffset vertices = [ mp.Vector3(w / 2, h / 2), mp.Vector3(-w / 2, h / 2), mp.Vector3(0, (.5 - e * ratio) * h) ] print(vertices) #Waveguide Geometry cell = mp.Vector3(a, H) geometry = [ mp.Block(cell, center=mp.Vector3(0, 0), material=default_material), mp.Block(mp.Vector3(a, hu + h / 2), center=mp.Vector3(0, (hu + h / 2) / 2), material=upper_material), mp.Block(mp.Vector3(a, hl + h / 2), center=mp.Vector3(0, -(hl + h / 2) / 2), material=lower_material), mp.Block(mp.Vector3(a, h), center=mp.Vector3(0, 0), material=core_material) ] if w > 0: geometry.append(mp.Prism(vertices, height=1, material=upper_material)) pml_layers = [mp.Absorber(thickness=dpml)] r00 = None r01 = None r10 = None r11 = None t00 = None t01 = None t10 = None t11 = None su0 = None sd0 = None su1 = None sd1 = None modes = [0, 1] if only_fund: modes = [0] # eig_parity_fund = mp.EVEN_Z+mp.EVEN_Y; # eig_parity_first = mp.EVEN_Z+mp.ODD_Y; eig_parity_fund = mp.EVEN_Y eig_parity_first = mp.ODD_Y # for mode in [0, 1]: for mode in modes: if mode == 0: eig_parity = eig_parity_fund # Fundamental print("-----------") print("MODE TYPE: FUNDAMENTAL") else: eig_parity = eig_parity_first # First Order print("-----------") print("MODE TYPE: FIRST ORDER") sources = [ mp.EigenModeSource(mp.ContinuousSource(frequency=fcen), size=mp.Vector3(0, H), center=mp.Vector3(Ls, 0), eig_parity=eig_parity) ] sim = mp.Simulation(cell_size=cell, boundary_layers=pml_layers, geometry=geometry, sources=sources, resolution=resolution, force_complex_fields=True) ''' #-------------------------------------------------- #FOR DISPLAYING THE GEOMETRY sim.run(until = 200) eps_data = sim.get_array(center=mp.Vector3(), size=cell, component=mp.Dielectric) plt.figure(dpi=100) plt.imshow(eps_data.transpose(), interpolation='spline36', cmap='binary') #plt.axis('off') plt.show() quit() #---------------------------------------------------- ''' ''' #------------------------------------------------------ #FOR GENERATING THE ELECTRIC FIELD GIF #Note: After running this program, write the following commands in Terminal: # $ source deactivate mp # $ cd notch-out/ # $ python ../NotchIP.py sim.use_output_directory() sim.run(mp.at_beginning(mp.output_epsilon), mp.to_appended("ez", mp.at_every(0.6, mp.output_efield_z)), until = 200) #sim.run(mp.at_every(0.6 , mp.output_png(mp.Ez, "-Zc dkbluered")), until=200) #--------------------------------------------------------- ''' #--------------------------------------------------------- # FOR GENERATING THE TRANSMITTANCE SPECTRUM nfreq = 1 # number of frequencies at which to compute flux refl_fr1 = mp.FluxRegion(center=mp.Vector3(Lr1, 0), size=mp.Vector3( 0, monitorheight)) # Reflected flux 1 refl_fr2 = mp.FluxRegion(center=mp.Vector3(Lr2, 0), size=mp.Vector3( 0, monitorheight)) # Reflected flux 2 tran_fr = mp.FluxRegion(center=mp.Vector3(Lt, 0), size=mp.Vector3( 0, monitorheight)) # Transmitted flux su_fr = mp.FluxRegion(center=mp.Vector3(0, monitorheight / 2), size=mp.Vector3( a, 0)) # Flux loss above the waveguide sd_fr = mp.FluxRegion(center=mp.Vector3(0, -monitorheight / 2), size=mp.Vector3( a, 0)) # Flux loss below the waveguide # refl1 = sim.add_flux(fcen, df, nfreq, refl_fr1) # refl2 = sim.add_flux(fcen, df, nfreq, refl_fr2) # tran = sim.add_flux(fcen, df, nfreq, tran_fr) # su = sim.add_flux(fcen, df, nfreq, su_fr) # sd = sim.add_flux(fcen, df, nfreq, sd_fr) # ------------------------ CODE FOR SEPARATING FUND AND FIRST ORDER MODE STARTS HERE ------------------------ refl_vals = [] tran_vals = [] def get_refl_slice(sim): # print(sim.get_array(center=mp.Vector3(Lr1,0), size=mp.Vector3(0,H), component=mp.Ez, cmplx=True)) # refl_val = sim.get_array(center=mp.Vector3(Lr1,0), size=mp.Vector3(0,H), component=mp.Ez, cmplx=True) refl_vals.append( sim.get_array(center=mp.Vector3(Lr1, 0), size=mp.Vector3(0, monitorheight - 2 / resolution), component=mp.Ez, cmplx=True)) def get_tran_slice(sim): # print(sim.get_array(center=mp.Vector3(Lt, 0), size=mp.Vector3(0,H), component=mp.Ez, cmplx=True)) # tran_val = sim.get_array(center=mp.Vector3(Lt, 0), size=mp.Vector3(0,H), component=mp.Ez, cmplx=True) tran_vals.append( sim.get_array(center=mp.Vector3(Lt, 0), size=mp.Vector3(0, monitorheight - 2 / resolution), component=mp.Ez, cmplx=True)) gif = True if gif: # and w == 0.1: sim.use_output_directory() sim.run(mp.at_beginning(mp.output_epsilon), mp.at_end(get_refl_slice), mp.at_end(get_tran_slice), until=100) refl1 = sim.add_flux(fcen, df, nfreq, refl_fr1) refl2 = sim.add_flux(fcen, df, nfreq, refl_fr2) tran = sim.add_flux(fcen, df, nfreq, tran_fr) su = sim.add_flux(fcen, df, nfreq, su_fr) sd = sim.add_flux(fcen, df, nfreq, sd_fr) # sim.run(mp.at_every(wavelength / 20, mp.output_efield_z), until=wavelength) # sim.run(mp.at_every(wavelength/20 , mp.output_png(mp.Ez, "-RZc bluered -A notch-out/notch-eps-000000000.h5 -a gray:.2")), until=19*wavelength/20) sim.run(mp.at_every( wavelength / 20, mp.output_png( mp.Ez, "-RZc bluered -A notch-out/notch-eps-000000.00.h5 -a gray:.2" )), until=19 * wavelength / 20) sim.run(until=50) else: sim.run(mp.at_end(get_refl_slice), mp.at_end(get_tran_slice), until=100) sim.run(until_after_sources=mp.stop_when_fields_decayed( 50, mp.Ez, mp.Vector3(), 1e-5)) os.system( "h5topng notch-out/notch-eps-000000.00.h5; mv notch-out/notch-eps-000000.00.png " + case + "-" + str(int(w * 1000)) + "-" + str(mode) + "-eps.png") os.system("cp notch-out/notch-ez-000100.00.png " + case + "-" + str(int(w * 1000)) + "-" + str(mode) + ".png") os.system("convert notch-out/notch-ez-*.png " + case + "-" + str(int(w * 1000)) + "-" + str(mode) + ".gif") # get_eigenmode(fcen, mp., refl_fr1, 1, kpoint) # v = mp.volume(mp.vec(Lr1, -monitorheight/2), mp.vec(Lr1, monitorheight/2)) # mode = get_eigenmode(fcen, mp.X, v, v, 1, mp.vec(0, 0, 0), True, 0, 0, 1e-7, True) # print(mode.amplitude) # coef_refl_fund = mp.get_eigenmode_coefficients_and_kpoints(refl_fr1, 1, eig_parity=eig_parity_fund, eig_resolution=resolution, eig_tolerance=1e-7) # coef_refl_first = mp.get_eigenmode_coefficients_and_kpoints(refl_fr1, 1, eig_parity=eig_parity_first, eig_resolution=resolution, eig_tolerance=1e-7) # # coef_tran_fund = mp.get_eigenmode_coefficients_and_kpoints(tran_fr, 1, eig_parity=eig_parity_fund, eig_resolution=resolution, eig_tolerance=1e-7) # coef_tran_first = mp.get_eigenmode_coefficients_and_kpoints(tran_fr, 1, eig_parity=eig_parity_first, eig_resolution=resolution, eig_tolerance=1e-7) ep = mp.ODD_Z #coef_refl_fund, vgrp, kpoints_fund = sim.get_eigenmode_coefficients(refl1, [1], eig_parity=ep, eig_resolution=resolution, eig_tolerance=1e-7) #coef_refl_first, vgrp, kpoints_first = sim.get_eigenmode_coefficients(refl1, [2], eig_parity=ep, eig_resolution=resolution, eig_tolerance=1e-7) #coef_tran_fund, vgrp, kpoints_fund = sim.get_eigenmode_coefficients(tran, [1], eig_parity=ep, eig_resolution=resolution, eig_tolerance=1e-7) #coef_tran_first, vgrp, kpoints_first = sim.get_eigenmode_coefficients(tran, [2], eig_parity=ep, eig_resolution=resolution, eig_tolerance=1e-7) # print(kpoints_fund) # print(kpoints_first) # print(kpoints_fund[0]) # print(type(kpoints_fund[0])) # print(dir(kpoints_fund[0])) # n_eff_fund = wavelength*kpoints_fund[0].x # n_eff_first = wavelength*kpoints_first[0].x n_eff_fund = neff n_eff_first = 1 print(n_eff_fund) print(n_eff_first) # print(coef_refl_fund) # print(type(coef_refl_fund)) # print(dir(coef_refl_fund)) # print(coef_refl_fund[0]) # print(coef_refl_fund[0][0,0,:]) # # fund_refl_amp = coef_refl_fund[0][0,0,1]; # first_order_refl_amp = coef_refl_first[0][0,0,1]; # fund_tran_amp = coef_tran_fund[0][0,0,0]; # first_order_tran_amp = coef_tran_first[0][0,0,0]; print("get_eigenmode_coefficients:\n") #print(coef_refl_fund) #print(coef_refl_first) #print(coef_tran_fund) #print(coef_tran_first) print("\n") # print(coef_refl_fund[0,0,:]) #fund_refl_amp = coef_refl_fund[0,0,1]; #first_order_refl_amp = coef_refl_first[0,0,1]; #fund_tran_amp = coef_tran_fund[0,0,0]; #first_order_tran_amp = coef_tran_first[0,0,0]; refl_val = refl_vals[0] tran_val = tran_vals[0] # n_eff must satisfy n_e <= n_eff <= n_c for the mode to be bound. def fund_func(n_eff): if n_eff >= n_c and n_eff <= n_e: return sqrt(n_eff**2 - n_c**2) - sqrt(n_e**2 - n_eff**2) * tan( pi * h / wavelength * sqrt(n_e**2 - n_eff**2)) def first_order_func(n_eff): if n_eff >= n_c and n_eff <= n_e: return sqrt(n_eff**2 - n_c**2) - sqrt(n_e**2 - n_eff**2) * tan( pi * h / wavelength * sqrt(n_e**2 - n_eff**2) - pi / 2) initial_guess = (n_c + n_e) / 2 # n_eff_fund = fsolve(fund_func, initial_guess) # n_eff_first = fsolve(first_order_func, n_c) print(n_eff_fund, n_eff_first) assert (n_eff_fund > n_eff_first) if len(n_eff_funds) == 0: n_eff_funds.append(n_eff_fund) if len(n_eff_firsts) == 0: n_eff_firsts.append(n_eff_first) ky0_fund = np.abs(2 * pi / wavelength * sqrt(n_e**2 - n_eff_fund**2)) ky0_first = np.abs(2 * pi / wavelength * sqrt(n_e**2 - n_eff_first**2)) ky1_fund = ky0_fund # np.abs(2 * pi / wavelength * sqrt(n_eff_fund **2 - n_c**2)) ky1_first = ky0_first # np.abs(2 * pi / wavelength * sqrt(n_eff_first**2 - n_c**2)) E_fund = lambda y: cos(ky0_fund * y) if np.abs(y) < h / 2 else cos( ky0_fund * h / 2) * np.exp(-ky1_fund * (np.abs(y) - h / 2)) E_first_order = lambda y: sin(ky0_first * y) if np.abs( y) < h / 2 else sin(ky0_first * h / 2) * np.exp(-ky1_first * ( np.abs(y) - h / 2)) * np.sign(y) # y_list = np.arange(-H/2+.5/resolution, H/2-.5/resolution, 1/resolution) #print("Y LIST: ", y_list) #print("SIZE OF Y LIST: ", y_list.size) E_fund_vec = np.zeros(y_list.size) E_first_order_vec = np.zeros(y_list.size) for index in range(y_list.size): y = y_list[index] E_fund_vec[index] = E_fund(y) E_first_order_vec[index] = E_first_order(y) # print(dir(sim)) # print(type(sim.get_eigenmode_coefficients)) # print(dir(sim.get_eigenmode_coefficients)) # print(type(sim.get_eigenmode)) # print(dir(sim.get_eigenmode)) # print(sim.get_eigenmode.__code__.co_varnames) # print(sim.get_eigenmode.__defaults__) # E1 = sim.get_eigenmode(fcen, mp.X, refl1.where, 1, None) # E2 = sim.get_eigenmode(fcen, mp.X, refl1.where, 2, None) # E3 = sim.get_eigenmode(fcen, mp.X, refl1.where, 3, None) # E4 = sim.get_eigenmode(fcen, mp.X, refl1.where, 4, None) # E1 = sim.get_eigenmode(fcen, mp.X, refl1.where, 1, mp.Vector3(0, 0, 0)) # E2 = sim.get_eigenmode(fcen, mp.X, refl1.where, 2, mp.Vector3(0, 0, 0)) # E3 = sim.get_eigenmode(fcen, mp.X, refl1.where, 3, mp.Vector3(0, 0, 0)) # E4 = sim.get_eigenmode(fcen, mp.X, refl1.where, 4, mp.Vector3(0, 0, 0)) # print(refl1.where) # numEA = 0 # E1 = sim.fields.get_eigenmode(fcen, mp.X, refl1.where, refl1.where, 1, mp.vec(0,0,0), True, 0, numEA, 1e-7, True) # print(type(E1)) # print(dir(E1)) # # print(refl1.where) # # print(E1, E2, E3, E4) # print(E1.amplitude, E1.band_num, E1.group_velocity, E1.k) # print(type(E1.amplitude)) # print(dir(E1.amplitude)) # print(doc(E1.amplitude)) # print(self(E1.amplitude)) # print(E1.amplitude(y_list)) # print(type(E1.amplitude(y_list))) # print(dir(E1.amplitude(y_list))) # print(E1.amplitude, E2.amplitude, E3.amplitude, E4.amplitude) # E1 = sim.get_eigenmode(fcen, mp.X, refl1.where, refl1.where, 1, mp.vec(0, 0, 0)) # E2 = sim.get_eigenmode(fcen, mp.X, refl1.where, refl1.where, 2, mp.vec(0, 0, 0)) # E3 = sim.get_eigenmode(fcen, mp.X, refl1.where, refl1.where, 3, mp.vec(0, 0, 0)) # E4 = sim.get_eigenmode(fcen, mp.X, refl1.where, refl1.where, 4, mp.vec(0, 0, 0)) # print(y_list) # # E1a = np.zeros(y_list.size, dtype='Complex128'); # E2a = np.zeros(y_list.size, dtype='Complex128'); # E3a = np.zeros(y_list.size, dtype='Complex128'); # E4a = np.zeros(y_list.size, dtype='Complex128'); # # # print(mp.eigenmode_amplitude.__code__.co_varnames) # # print(mp.eigenmode_amplitude.__defaults__) # # for i in range(y_list.size): # # print(E1) # # print(E1.swigobj) # # print(E1.amplitude) # # print(mp.vec(Lr1, y_list[i], 0)) # # print(mp.Vector3(Lr1, y_list[i], 0)) # # print(mp.Ez) # # E1a[i] = mp.eigenmode_amplitude(E1.swigobj, mp.vec(Lr1, y_list[i], 0), mp.Ez); # eval_point = mp.vec(Lr1, y_list[i], 0) # # print(eval_point) # E1a[i] = mp.eigenmode_amplitude(E1.swigobj, eval_point, mp.Ex) # E2a[i] = mp.eigenmode_amplitude(E2.swigobj, eval_point, mp.Ex) # E3a[i] = mp.eigenmode_amplitude(E3.swigobj, eval_point, mp.Ex) # E4a[i] = mp.eigenmode_amplitude(E4.swigobj, eval_point, mp.Ex) # # E1a[i] = mp.eigenmode_amplitude(E1.amplitude, mp.Vector3(Lr1, y_list[i], 0), mp.Ez); # # plt.plot(y_list, np.abs(E1a)**2, 'bo-', label='E1') # plt.plot(y_list, np.abs(E2a)**2, 'ro-', label='E2') # plt.plot(y_list, np.abs(E3a)**2, 'go-', label='E3') # plt.plot(y_list, np.abs(E4a)**2, 'co-', label='E4') # # plt.axis([40.0, 300.0, 0.0, 100.0]) # plt.xlabel("y (um)") # plt.ylabel("Field (a.u.)") # plt.legend(loc="center right") # plt.show() # print("r VECTOR: ", refl_val) # print("t VECTOR: ", tran_val) # print("E0 VECTOR: ", E_fund_vec) # print("E1 VECTOR: ", E_first_order_vec) # fund_refl_amp_2 = np.conj(np.dot(refl_val, E_fund_vec) / np.dot(E_fund_vec, E_fund_vec)) # Conjugate becasue MEEP uses physics exp(kz-wt) rather than engineering exp(wt-kz) # first_order_refl_amp_2 = np.conj(np.dot(refl_val, E_first_order_vec) / np.dot(E_first_order_vec, E_first_order_vec)) # fund_tran_amp_2 = np.conj(np.dot(tran_val, E_fund_vec) / np.dot(E_fund_vec, E_fund_vec)) # first_order_tran_amp_2 = np.conj(np.dot(tran_val, E_first_order_vec) / np.dot(E_first_order_vec, E_first_order_vec)) fund_refl_amp = np.conj( np.dot(refl_val, E0) / np.dot(E0, E0) ) # Conjugate becasue MEEP uses physics exp(kz-wt) rather than engineering exp(wt-kz) first_order_refl_amp = 0 # np.conj(np.dot(refl_val, E1[:,2]) / np.dot(E1[:,2], E1[:,2])) fund_tran_amp = np.conj(np.dot(tran_val, E0) / np.dot(E0, E0)) first_order_tran_amp = 0 # np.conj(np.dot(tran_val, E1[:,2]) / np.dot(E1[:,2], E1[:,2])) fund_refl = np.conj(fund_refl_amp) * E0 not_fund_refl = refl_val - fund_refl fund_tran = np.conj(fund_tran_amp) * E0 not_fund_tran = tran_val - fund_tran fund_refl_power = np.dot(np.conj(fund_refl), fund_refl) not_fund_refl_power = np.dot(np.conj(not_fund_refl), not_fund_refl) fund_tran_power = np.dot(np.conj(fund_tran), fund_tran) not_fund_tran_power = np.dot(np.conj(not_fund_tran), not_fund_tran) fund_refl_ratio = np.abs(fund_refl_power / (fund_refl_power + not_fund_refl_power)) first_order_refl_ratio = 0 fund_tran_ratio = np.abs(fund_tran_power / (fund_tran_power + not_fund_tran_power)) first_order_tran_ratio = 0 # plt.plot(y_list, np.abs(refl_val), 'bo-',label='reflectance') # plt.plot(y_list, np.abs(tran_val), 'ro-',label='transmittance') # plt.plot(y_list, E0, 'go-',label='E0') # plt.plot(y_list, fund_refl_amp*E0, 'co-',label='over') # # plt.axis([40.0, 300.0, 0.0, 100.0]) # plt.xlabel("y (um)") # plt.ylabel("Field") # plt.legend(loc="center right") # plt.show() # # print("\n") # # print(tran_val.size, refl_val.size) # # print("\n") # # print(tran_val, refl_val, E0) # # print("\n") # # print(np.conj(tran_val), tran_val, E1[:,2]) # # # # print(np.conj(refl_val), refl_val, E1[:,2]) # # refl_tot_power = np.abs(np.dot(np.conj(refl_val), refl_val)) # tran_tot_power = np.abs(np.dot(np.conj(tran_val), tran_val)) # # print(fund_refl_amp, refl_tot_power, fund_tran_amp, tran_tot_power) # print(fund_refl_amp , fund_refl_amp_2 ) # print(first_order_refl_amp , first_order_refl_amp_2) # print(fund_tran_amp , fund_tran_amp_2 ) # print(first_order_tran_amp , first_order_tran_amp_2) # # print(np.angle(fund_refl_amp), np.angle(fund_refl_amp_2)) # print(np.angle(first_order_refl_amp), np.angle(first_order_refl_amp_2)) # print(np.angle(fund_tran_amp), np.angle(fund_tran_amp_2)) # print(np.angle(first_order_tran_amp), np.angle(first_order_tran_amp_2)) # fund_refl_power = np.abs(fund_tran_amp) ** 2 # fund_refl_power = np.abs(fund_refl_amp) ** 2 # first_order_refl_power = np.abs(first_order_refl_amp) ** 2 # fund_tran_power = np.abs(fund_tran_amp) ** 2 # first_order_tran_power = np.abs(first_order_tran_amp) ** 2 # print(fund_refl_power, first_order_refl_power, fund_tran_power, first_order_tran_power) # fund_refl_ratio = fund_refl_power / (fund_refl_power + first_order_refl_power) # first_order_refl_ratio = first_order_refl_power / (fund_refl_power + first_order_refl_power) # fund_tran_ratio = fund_tran_power / (fund_tran_power + first_order_tran_power) # first_order_tran_ratio = first_order_tran_power / (fund_tran_power + first_order_tran_power) # fund_refl_power = np.abs(fund_refl_amp) ** 2 # first_order_refl_power = np.abs(first_order_refl_amp) ** 2 # fund_tran_power = np.abs(fund_tran_amp) ** 2 # first_order_tran_power = np.abs(first_order_tran_amp) ** 2 # # fund_refl_ratio = fund_refl_power / refl_tot_power # first_order_refl_ratio = first_order_refl_power / refl_tot_power # fund_tran_ratio = fund_tran_power / tran_tot_power # first_order_tran_ratio = first_order_tran_power / tran_tot_power # # fund_refl_ratio = 1 # first_order_refl_ratio = 0 # fund_tran_ratio = 1 # first_order_tran_ratio = 0 print("Percentage of reflected light in fundamental mode: ", fund_refl_ratio * 100) print("Percentage of reflected light in first order mode: ", first_order_refl_ratio * 100) print("Percentage of transmitted light in fundamental mode: ", fund_tran_ratio * 100) print("Percentage of transmitted light in first order mode: ", first_order_tran_ratio * 100) # ------------------------ CODE FOR SEPARATING FUND AND FIRST ORDER MODE ENDS HERE ------------------------ wl = [] #list of wavelengths refl1_flux = mp.get_fluxes(refl1) refl2_flux = mp.get_fluxes(refl2) tran_flux = mp.get_fluxes(tran) su_flux = mp.get_fluxes(su) sd_flux = mp.get_fluxes(sd) flux_freqs = mp.get_flux_freqs(refl1) for i in range(nfreq): wl = np.append(wl, 1 / flux_freqs[i]) print(1 / flux_freqs[i]) # for ind, elt in enumerate(wl): # #print(round(elt, 4)) # if round(elt, 3) == 0.637: # #print("ALERT: MATCH FOUND") # index = ind index = 0 rp = refl1_flux[index] tp = tran_flux[index] # print("rp/tp:\n") # print(rp) # print(tp) # print("\n") R = -refl1_flux[index] / (refl2_flux[index] - refl1_flux[index]) T = tran_flux[index] / (refl2_flux[index] - refl1_flux[index]) S = (refl2_flux[index] - tran_flux[index]) / (refl2_flux[index] - refl1_flux[index]) Su = su_flux[index] / (refl2_flux[index] - refl1_flux[index]) Sd = -sd_flux[index] / (refl2_flux[index] - refl1_flux[index]) S_correction = (1 - R - T) / (Su + Sd) # print(R, T, S, Su, Sd) r = sqrt(R) t = sqrt(T) # The amplitude ... times the phase ... accounting for the distance to the detector (Reverse exp(-kz) of phase). # r_fund = (r * fund_refl_ratio) * (fund_refl_amp / np.abs(fund_refl_amp)) * (np.exp( 2j*pi * (-Lr1 - w/2) * n_eff_fund / wavelength)) # Lr1 is negative because it is the (negative) position of the monitor, not the distace from the monitor to the center. # r_first = (r * first_order_refl_ratio) * (first_order_refl_amp / np.abs(first_order_refl_amp)) * (np.exp( 2j*pi * (-Lr1 - w/2) * n_eff_first / wavelength)) # t_fund = (t * fund_tran_ratio) * (fund_tran_amp / np.abs(fund_tran_amp)) * (np.exp( 2j*pi * ( Lt - w/2) * n_eff_fund / wavelength)) # t_first = (t * first_order_tran_ratio) * (first_order_tran_amp / np.abs(first_order_tran_amp)) * (np.exp( 2j*pi * ( Lt - w/2) * n_eff_first / wavelength)) r_fund = (r * fund_refl_ratio) * np.exp( 1j * np.angle(fund_refl_amp) + 2j * pi * (-Lr1 - w / 2) * n_eff_fund / wavelength ) # Lr1 is negative because it is the (negative) position of the monitor, not the distace from the monitor to the center. r_first = (r * first_order_refl_ratio ) * np.exp(1j * np.angle(first_order_refl_amp) + 2j * pi * (-Lr1 - w / 2) * n_eff_first / wavelength) t_fund = (t * fund_tran_ratio ) * np.exp(1j * np.angle(fund_tran_amp) + 2j * pi * (Lt - w / 2) * n_eff_fund / wavelength) t_first = (t * first_order_tran_ratio ) * np.exp(1j * np.angle(first_order_tran_amp) + 2j * pi * (Lt - w / 2) * n_eff_first / wavelength) if mode == 0: r00 = r_fund r01 = r_first t00 = t_fund t01 = t_first su0 = sqrt(np.abs(Su * S_correction)) sd0 = sqrt(np.abs(Sd * S_correction)) # su0 = sqrt(Su) # sd0 = sqrt(Sd) r00s.append(r00) r01s.append(r01) t00s.append(t00) t01s.append(t01) su0s.append(su0) sd0s.append(sd0) if only_fund: r10s.append(0) r11s.append(0) t10s.append(0) t11s.append(1) su1s.append(0) sd1s.append(0) else: r10 = r_fund r11 = r_first t10 = t_fund t11 = t_first su1 = sqrt(np.abs(Su * S_correction)) sd1 = sqrt(np.abs(Sd * S_correction)) # su1 = sqrt(Su) # sd1 = sqrt(Sd) r10s.append(r10) r11s.append(r11) t10s.append(t10) t11s.append(t11) su1s.append(su1) sd1s.append(sd1) norm_Su = S * Su / (Su + Sd) NET = round((R + T + S) * 100, 0) if NET > 100.0: NET = 100.0 NET_LOSS = round((Su + Sd) / S * 100, 0) if NET_LOSS > 100.0: NET_LOSS = 100.0 ''' np.append(ws, [w * 1000]) np.append(Rs, [R * 100]) np.append(Ts, [T * 100]) np.append(Ss, [S * 100]) np.append(NET_LIST, [NET]) np.append(Sus, [Su * 100]) np.append(Sds, [Sd * 100]) np.append(NET_LOSS_LIST, [NET_LOSS]) np.append(norm_Sus, [norm_Su * 100]) ''' if mode == 0: ws.append(w * 1000) Rs.append(R * 100) Ts.append(T * 100) Ss.append(S * 100) NET_LIST.append(NET) Sus.append(Su * 100) Sds.append(Sd * 100) NET_LOSS_LIST.append(NET_LOSS) norm_Sus.append(norm_Su * 100) if mode == 0: f1.write("--------------------------------------------------- \n") f1.write("Notch Width: %s nanometers \n" % (w * 1000)) f1.write("Reflection Percentage: %s\n" % (R * 100)) f1.write("Transmission Percentage: %s\n" % (T * 100)) f1.write("Total Loss Percentage: %s\n" % (S * 100)) f1.write("Percentage of Light Accounted For: %s\n" % (NET)) f1.write("Upper Loss Percentage: %s\n" % (Su * 100)) f1.write("Lower Loss Percentage: %s\n" % (Sd * 100)) f1.write("Percentage of Total Loss Accounted For: %s\n" % (NET_LOSS)) f1.write("Normalized Upper Loss Percentage: %s\n" % (norm_Su * 100)) f1.write("\n \n") f1.write("FUNDAMENTAL MODE \n") f1.write("n_eff: %s\n" % (n_eff_fund)) f1.write("Re(r00): %s\n" % (np.real(r00))) f1.write("Im(r00): %s\n" % (np.imag(r00))) f1.write("Re(r01): %s\n" % (np.real(r01))) f1.write("Im(r01): %s\n" % (np.imag(r01))) f1.write("Re(t00): %s\n" % (np.real(t00))) f1.write("Im(t00): %s\n" % (np.imag(t00))) f1.write("Re(t01): %s\n" % (np.real(t01))) f1.write("Im(t01): %s\n" % (np.imag(t01))) f1.write("Re(su0): %s\n" % (np.real(su0))) f1.write("Im(su0): %s\n" % (np.imag(su0))) f1.write("Re(sd0): %s\n" % (np.real(sd0))) f1.write("Im(sd0): %s\n" % (np.imag(sd0))) f1.write("\n") else: f1.write("FIRST ORDER MODE \n") f1.write("n_eff: %s\n" % (n_eff_first)) f1.write("Re(r10): %s\n" % (np.real(r10))) f1.write("Im(r10): %s\n" % (np.imag(r10))) f1.write("Re(r11): %s\n" % (np.real(r11))) f1.write("Im(r11): %s\n" % (np.imag(r11))) f1.write("Re(t10): %s\n" % (np.real(t10))) f1.write("Im(t10): %s\n" % (np.imag(t10))) f1.write("Re(t11): %s\n" % (np.real(t11))) f1.write("Im(t11): %s\n" % (np.imag(t11))) f1.write("Re(su1): %s\n" % (np.real(su1))) f1.write("Im(su1): %s\n" % (np.imag(su1))) f1.write("Re(sd1): %s\n" % (np.real(sd1))) f1.write("Im(sd1): %s\n" % (np.imag(sd1))) f1.write("--------------------------------------------------- \n") sim.reset_meep()
def main(args): print("\nstart time:", datetime.now()) # -------------------------------------------------------------------------- # physical parameters characterizing light source and interface characteris- # tics (must be adjusted - eihter here or via command line interface (CLI)) # -------------------------------------------------------------------------- e_z = args.e_z e_y = args.e_y m_charge = args.m_charge ref_medium = args.ref_medium n1 = args.n1 n2 = args.n2 kw_0 = args.kw_0 kr_w = args.kr_w # angle of incidence chi_deg = args.chi_deg #chi_deg = 1.0*Critical(n1, n2) #chi_deg = 0.95*Brewster(n1, n2) test_output = args.test_output # -------------------------------------------------------------------------- # specific Meep parameters (may need to be adjusted) # -------------------------------------------------------------------------- sx = 5 # size of cell including PML in x-direction sy = 5 # size of cell including PML in y-direction sz = 4 # size of cell including PML in z-direction pml_thickness = 0.25 # thickness of PML layer freq = 5 # vacuum frequency of source (default 5) runtime = 10 # runs simulation for 10 times freq periods # number of pixels per wavelength in the denser medium (at least 10, # 20 to 30 is a good choice) pixel = 10 # source position with respect to the center (point of impact) in Meep # units (-2.15 good); if equal -r_w, then source position coincides with # waist position source_shift = -2.15 # -------------------------------------------------------------------------- # derived (Meep) parameters (do not change) # -------------------------------------------------------------------------- k_vac = 2 * math.pi * freq k1 = n1 * k_vac n_ref = (1 if ref_medium == 0 else n1 if ref_medium == 1 else n2 if ref_medium == 2 else math.nan) r_w = kr_w / (n_ref * k_vac) w_0 = kw_0 / (n_ref * k_vac) shift = source_shift + r_w chi_rad = math.radians(chi_deg) s_pol = True if (e_z == 1 and e_y == 0) else False p_pol = True if (e_z == 0 and e_y == 1) else False params = dict(W_y=w_0, m=m_charge, k=k1) # -------------------------------------------------------------------------- # placement of the dielectric interface within the computational cell # -------------------------------------------------------------------------- # helper functions def alpha(chi_rad): """Angle of inclined plane with y-axis in radians.""" return math.pi / 2 - chi_rad def Delta_x(alpha): """Inclined plane offset to the center of the cell.""" sin_alpha = math.sin(alpha) cos_alpha = math.cos(alpha) return (sx / 2) * (( (math.sqrt(2) - cos_alpha) - sin_alpha) / sin_alpha) cell = mp.Vector3(sx, sy, sz) # geometry-lattice default_material = mp.Medium(index=n1) # located at lower right edge for 45 degree tilt geometry = [ mp.Block(size=mp.Vector3(mp.inf, sx * math.sqrt(2), mp.inf), center=mp.Vector3(+sx / 2 + Delta_x(alpha(chi_rad)), -sy / 2), e1=mp.Vector3(1 / math.tan(alpha(chi_rad)), 1, 0), e2=mp.Vector3(-1, 1 / math.tan(alpha(chi_rad)), 0), e3=mp.Vector3(0, 0, 1), material=mp.Medium(index=n2)) ] # -------------------------------------------------------------------------- # add absorbing boundary conditions and discretize structure # -------------------------------------------------------------------------- pml_layers = [mp.PML(pml_thickness)] resolution = pixel * (n1 if n1 > n2 else n2) * freq # set Courant factor (mandatory if either n1 or n2 is smaller than 1) Courant = (n1 if n1 < n2 else n2) / 3 # -------------------------------------------------------------------------- # 2d-beam profile distribution (field amplitude) at the waist of the beam # -------------------------------------------------------------------------- def Gauss(r, params): """Gauss profile.""" W_y = params['W_y'] return math.exp(-((r.y**2 + r.z**2) / W_y**2)) # -------------------------------------------------------------------------- # some test outputs # -------------------------------------------------------------------------- if test_output: print("Gauss 2d beam profile:", Gauss(mp.Vector3(0, 0.5, 0.2), params)) print() # -------------------------------------------------------------------------- # spectrum amplitude distribution(s) # -------------------------------------------------------------------------- # cartesian coordinates (not recommmended) ------------------------- def phi(k_y, k_z): """Azimuthal angle. Part of coordinate transformation from k-space to (theta, phi)-space. """ return math.atan2(k_y, -k_z) def theta(k_y, k_z, k): """Polar angle. Part of coordinate transformation from k-space to (theta, phi)-space. """ return math.acos(cmath.sqrt(k**2 - k_y**2 - k_z**2).real / k) def f_Gauss_cartesian(k_y, k_z, params): """2d-Gaussian spectrum amplitude. Impementation for Cartesian coordinates. """ W_y = params['W_y'] return math.exp(-W_y**2 * (k_y**2 + k_z**2) / 4) def f_Laguerre_Gauss_cartesian(k_y, k_z, params): """Laguerre-Gaussian spectrum amplitude. Impementation for Cartesian coordinates. """ m, k = params['m'], params['k'] return f_Gauss_cartesian(k_y, k_z, params) * \ cmath.exp(1j*m*phi(k_y, k_z)) * theta(k_y, k_z, k)**abs(m) # spherical coordinates -------------------------------------------- def f_Gauss_spherical(sin_theta, theta, phi, params): """2d-Gaussian spectrum amplitude. Impementation for spherical coordinates. """ W_y, k = params['W_y'], params['k'] return math.exp(-(k * W_y * sin_theta / 2)**2) def f_Laguerre_Gauss_spherical(sin_theta, theta, phi, params): """Laguerre-Gaussian spectrum amplitude. Impementation for spherical coordinates. """ m = params['m'] return f_Gauss_spherical(sin_theta, theta, phi, params) * theta**abs(m) * \ cmath.exp(1j*m*phi) # -------------------------------------------------------------------------- # some test outputs # -------------------------------------------------------------------------- if test_output: k_y, k_z = 1.0, 5.2 theta_ = theta(k_y, k_z, k1) phi_ = phi(k_y, k_z) print("Gauss spectrum (cartesian):", f_Gauss_cartesian(k_y, k_z, params)) print("Gauss spectrum (spherical):", f_Gauss_spherical(math.sin(theta_), theta_, phi_, params)) print() print("L-G spectrum (cartesian):", f_Laguerre_Gauss_cartesian(k_y, k_z, params)) print( "L-G spectrum (spherical):", f_Laguerre_Gauss_spherical(math.sin(theta_), theta_, phi_, params)) print() # -------------------------------------------------------------------------- # plane wave decomposition # (purpose: calculate field amplitude at light source position if not # coinciding with beam waist) # -------------------------------------------------------------------------- def psi_cartesian(r, x, params): """Field amplitude function. Integration in Cartesian coordinates. """ k, m = params['k'], params['m'] try: getattr(psi_cartesian, "called") except AttributeError: psi_cartesian.called = True print("Calculating inital field configuration. " "This will take some time...") def phase(k_y, k_z, x, y, z): """Phase function.""" return x * cmath.sqrt(k**2 - k_y**2 - k_z**2).real + y * k_y + z * k_z f = (f_Gauss_cartesian if m == 0 else f_Laguerre_Gauss_cartesian) try: (result, real_tol, imag_tol) = complex_dblquad( lambda k_y, k_z: f(k_y, k_z, params) * cmath.exp(1j * phase( k_y, k_z, x, r.y, r.z)), -k, k, -k, k) except Exception as e: print(type(e).__name__ + ":", e) sys.exit() return result def psi_spherical(r, x, params): """Field amplitude function. Integration in spherical coordinates. """ k, m = params['k'], params['m'] try: getattr(psi_spherical, "called") except AttributeError: psi_spherical.called = True print("Calculating inital field configuration. " "This will take some time...") def phase(theta, phi, x, y, z): """Phase function.""" sin_theta, sin_phi = math.sin(theta), math.sin(phi) cos_theta, cos_phi = math.cos(theta), math.cos(phi) return k * (sin_theta * (y * sin_phi - z * cos_phi) + cos_theta * x) f = (f_Gauss_spherical if m == 0 else f_Laguerre_Gauss_spherical) try: (result, real_tol, imag_tol) = complex_dblquad( lambda theta, phi: math.sin(theta) * math.cos(theta) * f(math.sin(theta), theta, phi, params) * cmath.exp(1j * phase( theta, phi, x, r.y, r.z)), 0, 2 * math.pi, 0, math.pi / 2) except Exception as e: print(type(e).__name__ + ":", e) sys.exit() return k**2 * result # -------------------------------------------------------------------------- # some test outputs (uncomment if needed) # -------------------------------------------------------------------------- if test_output: k_y, k_z = 1.0, 5.2 x, y, z = -2.15, 0.3, 0.5 r = mp.Vector3(0, y, z) print("phi:", phi(k_y, k_z)) print() print("psi (cartesian):", psi_cartesian(r, f_Laguerre_Gauss_cartesian, x, params)) print("psi (spherical):", psi_spherical(r, f_Laguerre_Gauss_spherical, x, params)) print("psi (origin, simple):", Gauss(r, params)) sys.exit() # -------------------------------------------------------------------------- # display values of physical variables # -------------------------------------------------------------------------- print() print("Expected output file size:", round(8 * (sx * sy * sz * resolution**3) / (1024**2)), "MiB") print() print("Specified variables and derived values:") print("n1:", n1) print("n2:", n2) print("chi: ", chi_deg, " [degree]") # interface inclination with respect to the x-axis print("incl.:", 90 - chi_deg, " [degree]") print("kw_0: ", kw_0) print("kr_w: ", kr_w) print("k_vac:", k_vac) print("vortex charge:", m_charge) print("Jones vector components: " "(e_z=", e_z, ", e_y=", e_y, ")", sep="", end="") print(" --->", ("s-" if s_pol else "p-" if p_pol else "mixed-") + "polarisation") print("degree of linear polarisation at pi/4:", 2 * (-e_z.conjugate() * e_y).real) print("degree of circular polarisation:", 2 * (-e_z.conjugate() * e_y).imag) # -------------------------------------------------------------------------- # exploiting symmetries to reduce computational effort # (only possible for beams without intrinsic orbital angular momentum, i.e. # no vortex charge) # -------------------------------------------------------------------------- # The plane of incidence (x-y-plane) is a mirror plane which is characterised # to be orthogonal to the z-axis (symmetry of the geometric structure). # Symmetry of the sources must be ensured simultaneously, which is only # possible for certain cases. If I am not mistaken this can only be achieved # for vortex free beams with pure s- or p-polarisation, i.e. where either # the Ez or Ey component is specified. symmetries = [] if m_charge == 0: if s_pol: symmetries.append(mp.Mirror(mp.Z, phase=-1)) if p_pol: symmetries.append(mp.Mirror(mp.Y, phase=+1)) # -------------------------------------------------------------------------- # specify current source, output functions and run simulation # -------------------------------------------------------------------------- force_complex_fields = True # default: True eps_averaging = True # default: True sources = [] if e_z != 0: source_Ez = mp.Source( src=mp.ContinuousSource(frequency=freq, width=0.5), component=mp.Ez, amplitude=e_z, size=mp.Vector3(0, 3, 3), center=mp.Vector3(source_shift, 0, 0), #amp_func=lambda r: Gauss(r, params) #amp_func=lambda r: psi_cartesian(r, shift, params) amp_func=lambda r: psi_spherical(r, shift, params)) sources.append(source_Ez) if e_y != 0: source_Ey = mp.Source( src=mp.ContinuousSource(frequency=freq, width=0.5), component=mp.Ey, amplitude=e_y, size=mp.Vector3(0, 3, 3), center=mp.Vector3(source_shift, 0, 0), #amp_func=lambda r: Gauss(r, params) #amp_func=lambda r: psi_cartesian(r, shift, params) amp_func=lambda r: psi_spherical(r, shift, params)) sources.append(source_Ey) sim = mp.Simulation(cell_size=cell, boundary_layers=pml_layers, symmetries=symmetries, default_material=default_material, Courant=Courant, geometry=geometry, sources=sources, resolution=resolution, force_complex_fields=force_complex_fields, eps_averaging=eps_averaging) sim.use_output_directory() # put output files in a separate folder def efield_real_squared(r, ex, ey, ez): """Calculate |Re E|^2. With |.| denoting the complex modulus if 'force_complex_fields?' is set to true, otherwise |.| gives the Euclidean norm. """ return ex.real**2 + ey.real**2 + ez.real**2 def efield_imag_squared(r, ex, ey, ez): """Calculate |Im E|^2. With |.| denoting the complex modulus if 'force_complex_fields?' is set to true, otherwise |.| gives the Euclidean norm. """ return ex.imag**2 + ey.imag**2 + ez.imag**2 def output_efield_real_squared(sim): """Output E-field (real part) intensity.""" name = "e_real2_s" if s_pol else "e_real2_p" if p_pol else "e_real2_mixed" func = efield_real_squared cs = [mp.Ex, mp.Ey, mp.Ez] return sim.output_field_function(name, cs, func, real_only=True) def output_efield_imag_squared(sim): """Output E-field (imag part) intensity.""" name = "e_imag2_s" if s_pol else "e_imag2_p" if p_pol else "e_imag2_mixed" func = efield_imag_squared cs = [mp.Ex, mp.Ey, mp.Ez] return sim.output_field_function(name, cs, func, real_only=True) run_args = [ #mp.at_beginning(mp.output_epsilon), # output of dielectric function #mp.at_end(mp.output_efield_x), # output of E_x component #mp.at_end(mp.output_efield_z), # output of E_y component #mp.at_end(mp.output_efield_y), # output of E_z component mp.at_end(output_efield_real_squared ) # output of electric field intensity ] if force_complex_fields: run_args.append(mp.at_end(output_efield_imag_squared)) sim.run(*run_args, until=runtime) print("\nend time:", datetime.now())
import numpy as np import matplotlib.pyplot as plt from matplotlib import animation resolution = 16 frequency = 2.0 length = 5.0 endTime = 5.0 courantFactor = 0.5 timestepDuration = courantFactor / resolution numberTimesteps = int(endTime / timestepDuration) cellSize = mp.Vector3(0, 0, length) sources = [mp.Source( mp.ContinuousSource(frequency=frequency), component=mp.Ex, center=mp.Vector3(0, 0, 0))] simulation = mp.Simulation( cell_size=cellSize, sources=sources, resolution=resolution) simulation.run(until=timestepDuration) field_Ex = simulation.get_array(center=mp.Vector3(0, 0, 0), size=cellSize, component=mp.Ex) fieldData = np.array(field_Ex) for i in range(numberTimesteps-1): simulation.run(until=timestepDuration) fieldEx = simulation.get_array(center=mp.Vector3(0, 0, 0), size=cellSize, component=mp.Ex)