def empty_run(self, sx, sy, animate=False): sources, refl_fr, trans_fr = self.set_source(sx, sy) sim = mp.Simulation(cell_size=mp.Vector3(sx, sy, self.sz), geometry=[], sources=sources, boundary_layers=self.pml_layers, k_point=self.k, resolution=self.resolution) refl = sim.add_flux(self.fcen, self.df, self.nfreq, refl_fr) trans = sim.add_flux(self.fcen, self.df, self.nfreq, trans_fr) if animate: sim.run(mp.at_beginning(mp.output_epsilon), mp.to_appended("ex", mp.at_every(0.6, mp.output_efield_z)), until_after_sources=mp.stop_when_fields_decayed(25, mp.Ey, self.pt, 1e-3)) else: sim.run(until_after_sources=mp.stop_when_fields_decayed(25, mp.Ey, self.pt, 1e-3)) # for normalization run, save flux fields data for reflection plane self.store['straight_refl_data'] = sim.get_flux_data(refl) # save incident power for transmission plane self.store['flux_freqs'] = mp.get_flux_freqs(refl) self.store['straight_tran_flux'] = mp.get_fluxes(trans) self.store['straight_refl_flux'] = mp.get_fluxes(refl)
def get_flux_data_from_many(trans): # simulation data are saved in trans freqs = mp.get_flux_freqs(trans[0]) fluxes = [mp.get_fluxes(tran) for tran in trans] data = np.column_stack(( freqs, *fluxes, )) return data
def get_flux_data_from_one(ntran, nsize): # simulation data are saved in trans freqs = mp.get_flux_freqs(ntran) fluxes = mp.get_fluxes(ntran) data = np.column_stack(( freqs, fluxes, )) data = np.insert(data, 1, nsize, axis=1) return data
def my_display_fluxes(sim): nonlocal my_display_count nonlocal step_time freqs=mp.get_flux_freqs(trans[0]) fluxes=[mp.get_fluxes(tran) for tran in trans] data=np.column_stack((freqs, *fluxes,)) my.matrix_output(None,data,"{:10.3e}","flux") my_display_count+=1 print('No. {} display at t={}'.format( my_display_count,step_time)) mymeep.my_flush_step(sim)
def flux_monitor_cal(box_x1, box_x2, box_y1, box_y2, box_z1, box_z2): box_x1_flux = mp.get_fluxes(box_x1) box_x2_flux = mp.get_fluxes(box_x2) box_y1_flux = mp.get_fluxes(box_y1) box_y2_flux = mp.get_fluxes(box_y2) box_z1_flux = mp.get_fluxes(box_z1) box_z2_flux = mp.get_fluxes(box_z2) frqs = mp.get_flux_freqs(box_x1) p_flux = -(np.asarray(box_x1_flux) - np.asarray(box_x2_flux) + np.asarray(box_y1_flux) - np.asarray(box_y2_flux) + np.asarray(box_z1_flux) - np.asarray(box_z2_flux)) return frqs, p_flux
def runSimulation(thetaDegrees): thetaRadians = np.radians(thetaDegrees) kVector = mp.Vector3(np.sin(thetaRadians), 0, np.cos(thetaRadians)).scale(minimumFrequency) simulation = mp.Simulation(cell_size=cellSize, sources=sources, resolution=resolution, boundary_layers=pmlLayers, k_point=kVector) incidentFluxMonitor = simulation.add_flux(frequency, frequencyWidth, numberFrequencies, incidentRegion) simulation.run(until_after_sources=mp.stop_when_fields_decayed( 20, mp.Ex, transmissionMonitorLocation, powerDecayTarget)) incidentFluxToSubtract = simulation.get_flux_data(incidentFluxMonitor) simulation = mp.Simulation(cell_size=cellSize, sources=sources, resolution=resolution, boundary_layers=pmlLayers, geometry=geometry, k_point=kVector) transmissionRegion = mp.FluxRegion(center=transmissionMonitorLocation) transmissionFluxMonitor = simulation.add_flux(frequency, frequencyWidth, numberFrequencies, transmissionRegion) reflectionRegion = incidentRegion reflectionFluxMonitor = simulation.add_flux(frequency, frequencyWidth, numberFrequencies, reflectionRegion) simulation.load_minus_flux_data(reflectionFluxMonitor, incidentFluxToSubtract) simulation.run(until_after_sources=mp.stop_when_fields_decayed( 20, mp.Ex, transmissionMonitorLocation, powerDecayTarget)) incidentFlux = np.array(mp.get_fluxes(incidentFluxMonitor)) transmittedFlux = np.array(mp.get_fluxes(transmissionFluxMonitor)) reflectedFlux = np.array(mp.get_fluxes(reflectionFluxMonitor)) R = np.array(-reflectedFlux / incidentFlux) T = np.array(transmittedFlux / incidentFlux) frequencies = np.array(mp.get_flux_freqs(reflectionFluxMonitor)) kx = kVector.x angles = np.arcsin(kx / frequencies) return angles, frequencies, R, T
def test_ninety_degree_bend(self): # We have to run the straight waveguide version first to generate the 'refl-flux' # file that this test uses. We can't just prepend run_with_straight_waveguide # with 'test_' because execution order of unit tests isn't deterministic. self.run_with_straight_waveguide() self.sim = None self.init() self.sim.load_minus_flux('refl-flux', self.refl) self.sim.run(until_after_sources=mp.stop_when_fields_decayed( 50, mp.Ez, self.pt, 1e-3)) expected = [ (0.09999999999999999, 1.8392235204829767e-5, -7.259467687598002e-6), (0.10101010101010101, 2.7629932558236724e-5, -1.1107162110079347e-5), (0.10202020202020202, 4.1001228946782745e-5, -1.687561915798036e-5), (0.10303030303030304, 6.018966076122556e-5, -2.5425779493709066e-5), (0.10404040404040406, 8.758554071933231e-5, -3.794958119189475e-5), (0.10505050505050507, 1.2656696778129198e-4, -5.612512808928115e-5), (0.10606060606060609, 1.817948859871414e-4, -8.232188174309142e-5), (0.10707070707070711, 2.594514094902856e-4, -1.1981531280672989e-4), (0.10808080808080812, 3.6736164837695035e-4, -1.7300125173897737e-4), (0.10909090909090914, 5.150131339048232e-4, -2.476730940385436e-4), (0.11010101010101016, 7.136181099374187e-4, -3.5145561406042276e-4), (0.11111111111111117, 9.76491765781944e-4, -4.944142331545938e-4), (0.11212121212121219, 0.001320033637882244, -6.897357105189368e-4), (0.11313131313131321, 0.0017653940714397098, -9.543556354451615e-4), (0.11414141414141422, 0.0023404727796352857, -0.0013095604571818236), (0.11515151515151524, 0.0030813962415392098, -0.00178176942635486), (0.11616161616161626, 0.00403238648982478, -0.0024036650652026112), (0.11717171717171727, 0.005243320443599316, -0.003215529845495731), (0.11818181818181829, 0.0067654019326068, -0.004266367104375331), (0.11919191919191931, 0.008646855439680507, -0.005614491919262783), ] res = list( zip(mp.get_flux_freqs(self.trans), mp.get_fluxes(self.trans), mp.get_fluxes(self.refl))) np.testing.assert_allclose(expected, res[:20])
def force_norm(): """perform normalization simulation""" norm = meep.Simulation(cell_size=cell, boundary_layers=[pml], geometry=[], resolution=resolution) norm.init_fields() source(norm) flux_inc = meep_ext.add_flux_plane(norm, fcen, df, nfreq, [0,0,0], [2*radius, 2*radius, 0]) norm.run(until_after_sources=meep.stop_when_fields_decayed(.5*um, decay, pt=meep.Vector3(0,0,0), decay_by=1e-5)) return {'frequency': np.array(meep.get_flux_freqs(flux_inc)), 'area': (2*radius)**2, 'incident': np.asarray(meep.get_fluxes(flux_inc))}
def plot_power(self): flux_freqs = np.array(mp.get_flux_freqs(self.box_z2)) flux_up = np.array(mp.get_fluxes(self.box_z2)) flux_bot = np.array(mp.get_fluxes(self.box_z1)) flux_side = np.array(mp.get_fluxes(self.box_r)) flux_total = flux_bot + flux_up + flux_side flux_wvl = 1 / flux_freqs plt.figure(dpi=150) plt.plot(flux_wvl, flux_total, 'r-', label='Total emission') plt.plot(flux_wvl, flux_bot, 'g-', label='Bottom emission') plt.plot(flux_wvl, flux_side, 'y-', label='Side emission') plt.plot(flux_wvl, flux_up, 'b-', label='Upward emission') plt.legend(loc='upper right') plt.xlabel('Wavelength (µm)') plt.ylabel('Arbitrary intensity') return flux_freqs, flux_up, flux_bot, flux_side
def scat_sim(): """perform scattering simulation""" scat = meep.Simulation(cell_size=cell, boundary_layers=[pml], geometry=geometry, default_material=medium, resolution=resolution) scat.init_fields() source(scat) flux_box_absorb = meep_ext.add_flux_box(scat, fcen, df, nfreq, [0,0,0], monitor_size) flux_box_scat = meep_ext.add_flux_box(scat, fcen, df, nfreq, [0,0,0], monitor_size) scat.load_minus_flux(norm_file_ext, flux_box_scat) scat.run(until_after_sources=meep.stop_when_fields_decayed(.5*um, decay, pt=meep.Vector3(0,0,monitor_size[2]/2), decay_by=1e-5)) return {'scattering': np.array(meep.get_fluxes(flux_box_scat)),'absorption': -np.array(meep.get_fluxes(flux_box_absorb)), 'frequency': np.array(meep.get_flux_freqs(flux_box_scat))}
def norm_sim(): """perform normalization simulation""" norm = meep.Simulation(cell_size=cell, boundary_layers=[pml], geometry=[], default_material=medium, resolution=resolution) norm.init_fields() source(norm) flux_box_inc = meep_ext.add_flux_box(norm, fcen, df, nfreq, [0,0,0], monitor_size) flux_inc = meep_ext.add_flux_plane(norm, fcen, df, nfreq, [0,0,0], [box[0], box[1], 0]) norm.run(until_after_sources=meep.stop_when_fields_decayed(.5*um, decay, pt=meep.Vector3(0,0,monitor_size[2]/2), decay_by=1e-3)) norm.save_flux(norm_file_ext, flux_box_inc) return {'frequency': np.array(meep.get_flux_freqs(flux_inc)), 'area': box[0]*box[1], 'incident': np.asarray(meep.get_fluxes(flux_inc))}
def get_signal(self): trans = [] refls = [] for angle in [0, 90]: sim = self.simulator(self.medium[angle]) tran_monitor = sim.add_flux(self.f_center, self.f_width, self.n_freq, self.tran_fr) refl_monitor = sim.add_flux(self.f_center, self.f_width, self.n_freq, self.refl_fr) sim.load_minus_flux_data(refl_monitor, self.refl_straight) sim.run(until=self.sim_time) trans.append(sim.get_flux_data(tran_monitor).E[:self.n_freq]) refls.append(sim.get_flux_data(refl_monitor).E[:self.n_freq]) return \ np.array(trans), \ np.array(refls), \ np.array(mp.get_flux_freqs(tran_monitor))
def simulation(sim, cell, det_dir, det_tran, det_tran_2, **simrun_args): #inicialitzo els dos detectors (a les diferents posicions) det_dir = det_dir #Detectors(center=mp.Vector3(-4.25,0,0),size=mp.Vector3(0,5.0,0)) det_tran = det_tran #Detectors(center=mp.Vector3(3.25,0,0),size=mp.Vector3(0,5.0,0)) det_tran_2 = det_tran_2 #afegeixo els fluxos direct = sim.add_flux(Wave.fcen, Wave.df, Wave.nfreq, det_dir.detect_fr) tran = sim.add_flux(Wave.fcen, Wave.df, Wave.nfreq, det_tran.detect_fr) tran_2 = sim.add_flux(Wave.fcen, Wave.df, Wave.nfreq, det_tran_2.detect_fr) sim.run(**simrun_args) #prenc les dades per fer els dibuixos eps_data = sim.get_array(center=mp.Vector3(), size=cell, component=mp.Dielectric) ez_data = sim.get_array(center=mp.Vector3(), size=cell, component=mp.Ez) #prenc les dades per fer les gràfiques flux_freqs = mp.get_flux_freqs(direct) direct_data = mp.get_fluxes(direct) tran_data = mp.get_fluxes(tran) tran_data_2 = mp.get_fluxes(tran_2) reset = sim.reset_meep() return eps_data, ez_data, flux_freqs, direct_data, tran_data, tran_data_2, reset
def run_chi3(k_pow, amp=1): k = 10**k_pow default_material = mp.Medium(index=1, chi3=k) sources = mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Ex, center=mp.Vector3(0, 0, -0.5 * sz + dpml), amplitude=amp) sim = mp.Simulation(cell_size=cell, geometry=[], sources=[sources], boundary_layers=[pml_layers], default_material=default_material, resolution=resolution, dimensions=dimensions) trans = sim.add_flux( 0.5 * (fmin + fmax), fmax - fmin, nfreq, mp.FluxRegion(mp.Vector3(0, 0, 0.5 * sz - dpml - 0.5))) # Single frequency point at omega trans1 = sim.add_flux( fcen, 0, 1, mp.FluxRegion(mp.Vector3(0, 0, 0.5 * sz - dpml - 0.5))) # Singel frequency point at 3omega trans3 = sim.add_flux( 3 * fcen, 0, 1, mp.FluxRegion(mp.Vector3(0, 0, 0.5 * sz - dpml - 0.5))) sim.run(until_after_sources=mp.stop_when_fields_decayed( 50, mp.Ex, mp.Vector3(0, 0, 0.5 * sz - dpml - 0.5), 1e-6)) omega_flux = mp.get_fluxes(trans1) omega3_flux = mp.get_fluxes(trans3) freqs = mp.get_flux_freqs(trans) spectra = mp.get_fluxes(trans) return freqs, spectra, omega_flux, omega3_flux
def run_power(self, time_after_sources=100): self.time_after_sources = time_after_sources self._sim.run(until_after_sources=self.time_after_sources) flux_freqs = np.array(mp.get_flux_freqs(self.box_z2)) flux_up = np.array(mp.get_fluxes(self.box_z2)) flux_bot = np.array(mp.get_fluxes(self.box_z1)) flux_side = np.array(mp.get_fluxes(self.box_r)) flux_total = flux_bot + flux_up + flux_side max_uppower = max(flux_up) max_totalpower = max(flux_total) max_upindex = np.where(flux_up == max_uppower) maxwvl = 1 / flux_freqs[max_upindex] # find the wavelength of maximum sum_upratio = sum(flux_up) / sum( flux_total) # the ratio of total upward power max_upratio = max(flux_up) / max( flux_total ) # at the most productive wavelength, thr ratio of upward power flux_wvl = 1 / flux_freqs plt.figure(dpi=150) plt.axvline(x=maxwvl, color='b', linestyle='--') # mark where moset productive wavelength plt.plot(flux_wvl, flux_total, 'r-', label='Total emission') plt.plot(flux_wvl, flux_bot, 'g-', label='Bottom emission') plt.plot(flux_wvl, flux_side, 'y-', label='Side emission') plt.plot(flux_wvl, flux_up, 'b-', label='Upward emission') plt.legend(loc='upper right') plt.xlabel('Wavelength (µm)') plt.ylabel('Arbitrary intensity') return flux_freqs, flux_up, flux_bot, flux_side
def sim_cavity(N=3, sy=6): 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)))) src = [ mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Ey, center=mp.Vector3(-0.5 * sx + dpml), size=mp.Vector3(0, w)) ] sim = mp.Simulation(cell_size=cell, geometry=geometry, boundary_layers=pml_layers, sources=src, symmetries=sym, resolution=resolution) freg = mp.FluxRegion(center=mp.Vector3(0.5 * sx - dpml - 0.5), size=mp.Vector3(0, 2 * w)) nfreq = 500 trans = sim.add_flux(fcen, df, nfreq, freg) sim.run(until_after_sources=mp.stop_when_fields_decayed( 50, mp.Ey, mp.Vector3(0.5 * sx - dpml - 0.5), 1e-3)) freqs = mp.get_flux_freqs(trans) psd = mp.get_fluxes(trans) return freqs, psd
def adjoint_run(self): # Grab the simulation step size from the forward run self.dt = self.sim.fields.dt # Prepare adjoint run self.sim.reset_meep() # Replace sources with adjoint sources self.adjoint_sources = [] for mi, m in enumerate(self.objective_arguments): dJ = jacobian(self.objective_function,mi)(*self.results_list) # get gradient of objective w.r.t. monitor self.adjoint_sources.append(m.place_adjoint_source(dJ,self.dt)) # place the appropriate adjoint sources self.sim.change_sources(self.adjoint_sources) # register design flux # TODO use yee grid directly self.design_region_monitors = [self.sim.add_dft_fields([mp.Ex,mp.Ey,mp.Ez],self.fcen,self.df,self.nf,where=dr,yee_grid=False) for dr in self.design_regions] # add monitor used to track dft convergence mdft = self.sim.add_dft_fields(self.decay_fields,self.fcen,self.df,1,center=self.design_regions[0].center,size=mp.Vector3(1/self.sim.resolution)) # Adjoint run self.sim.run(until_after_sources=stop_when_dft_decayed(mdft, self.decay_dt, self.decay_fields, self.fcen, self.decay_by)) # Store adjoint fields for each design basis in array (x,y,z,field_components,frequencies) # FIXME allow for multiple design regions self.a_E = [np.zeros((len(dg.x),len(dg.y),len(dg.z),3,self.nf),dtype=np.complex128) for dg in self.design_grids] for nb, dgm in enumerate(self.design_region_monitors): for f in range(self.nf): for ic, c in enumerate([mp.Ex,mp.Ey,mp.Ez]): self.a_E[nb][:,:,:,ic,f] = np.atleast_3d(self.sim.get_dft_array(dgm,c,f)) # store frequencies (will be same for all monitors) self.frequencies = np.array(mp.get_flux_freqs(self.design_region_monitors[0])) # update optimizer's state self.current_state = "ADJ"
def compute_flux(m=1, n=0): if m == 1: sources = [] for n in range(ndipole): sources.append( mp.Source( mp.CustomSource(src_func=lambda t: np.random.randn()), component=mp.Ez, center=mp.Vector3(sx * (-0.5 + n / ndipole), -0.5 * sy + dAg + 0.5 * dsub))) else: sources = [ mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Ez, center=mp.Vector3(sx * (-0.5 + n / ndipole), -0.5 * sy + dAg + 0.5 * dsub)) ] sim = mp.Simulation(cell_size=cell_size, resolution=resolution, k_point=mp.Vector3(), boundary_layers=pml_layers, geometry=geometry, sources=sources) flux_mon = sim.add_flux( fcen, df, nfreq, mp.FluxRegion(center=mp.Vector3(0, 0.5 * sy - dpml), size=mp.Vector3(sx))) sim.run(until=run_time) flux = mp.get_fluxes(flux_mon) freqs = mp.get_flux_freqs(flux_mon) return freqs, flux
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()
sources=sources, ensure_periodicity=True, k_point=mp.Vector3()) transmittance_first_fr = mp.FluxRegion(center=mp.Vector3( 0.5 * cellx - dpml, 0, 0), size=mp.Vector3(0, celly)) transmittance_first = sim.add_flux(frq_cen, dfrq, nfrq, transmittance_first_fr) pt = mp.Vector3(0.5 * cellx - dpml, 0, 0) sim.run(until_after_sources=100) transmittance_first_flux = mp.get_fluxes(transmittance_first) box_x1_data = sim.get_flux_data(transmittance_first) flux_freqs = mp.get_flux_freqs(transmittance_first) sim.reset_meep() geometry = [ mp.Block(mp.Vector3(block_thicknessx, block_thicknessy, mp.inf), center=mp.Vector3(), material=Material) ] pt = mp.Vector3(0.5 * cellx - dpml, 0, 0) sim = mp.Simulation(resolution=resolution, symmetries=symmetries, cell_size=mp.Vector3(cellx, celly), boundary_layers=pml_layers, sources=sources, k_point=mp.Vector3(), ensure_periodicity=True,
def planar_reflectance(theta): # rotation angle (in degrees) of source: CCW around Y axis, 0 degrees along +Z axis theta_r = math.radians(theta) # plane of incidence is XZ; rotate counter clockwise (CCW) about y-axis k = mp.Vector3(z=fmin).rotate(mp.Vector3(y=1), theta_r) # if normal incidence, force number of dimensions to be 1 if theta_r == 0: dimensions = 1 else: dimensions = 3 sources = [mp.Source(mp.GaussianSource(fcen,fwidth=df), component=mp.Ex, center=mp.Vector3(z=-0.5*sz+dpml))] sim = mp.Simulation(cell_size=cell_size, boundary_layers=pml_layers, sources=sources, k_point=k, dimensions=dimensions, resolution=resolution) refl_fr = mp.FluxRegion(center=mp.Vector3(z=-0.25*sz)) refl = sim.add_flux(fcen, df, nfreq, refl_fr) sim.run(until_after_sources=mp.stop_when_fields_decayed(50, mp.Ex, mp.Vector3(z=-0.5*sz+dpml), 1e-9)) empty_flux = mp.get_fluxes(refl) empty_data = sim.get_flux_data(refl) sim.reset_meep() # add a block with n=3.5 for the air-dielectric interface geometry = [mp.Block(mp.Vector3(mp.inf,mp.inf,0.5*sz), center=mp.Vector3(z=0.25*sz), material=mp.Medium(index=3.5))] sim = mp.Simulation(cell_size=cell_size, geometry=geometry, boundary_layers=pml_layers, sources=sources, k_point=k, dimensions=dimensions, resolution=resolution) refl = sim.add_flux(fcen, df, nfreq, refl_fr) sim.load_minus_flux_data(refl, empty_data) sim.run(until_after_sources=mp.stop_when_fields_decayed(50, mp.Ex, mp.Vector3(z=-0.5*sz+dpml), 1e-9)) refl_flux = mp.get_fluxes(refl) freqs = mp.get_flux_freqs(refl) wvls = np.empty(nfreq) theta_out = np.empty(nfreq) R = np.empty(nfreq) for i in range(nfreq): wvls[i] = 1/freqs[i] theta_out[i] = math.degrees(math.asin(k.x/freqs[i])) R[i] = -refl_flux[i]/empty_flux[i] print("refl:, {}, {}, {}, {}".format(k.x,wvls[i],theta_out[i],R[i])) return k.x*np.ones(nfreq), wvls, theta_out, R
def main(args): resolution = args.res dpml = 1.0 # PML thickness sz = 10 + 2 * dpml # 10 is size of cell without PMLs # A 1d cell must be used since a higher-dimensional cell # will introduce artificial modes due to band folding. cell_size = mp.Vector3(0, 0, sz) pml_layers = [mp.PML(dpml)] # Gaussian w/visible spectrum wvl_min = 0.4 # min wavelength wvl_max = 0.8 # max wavelength fmin = 1 / wvl_max # min frequency fmax = 1 / wvl_min # max frequency fcen = 0.5 * (fmin + fmax) # center frequency df = fmax - fmin # frequency width nfreq = 50 # number of frequency bins # Unlike a continuous-wave (CW) source, a pulsed source turns off. # Rotation angle of planewave # (input in degrees and transformed to radians) theta_r = math.radians(args.theta) # Counterclockwise (CCW) around Y axis # 0 degrees along +Z axis # Plane of incidence is XZ k = mp.Vector3(math.sin(theta_r), 0, math.cos(theta_r)).scale(fmin) # Where k is given by dispersion relation formula # ω = c|k⃗|/n (planewave in homogeneous media of index n) # As the source here is incident from air, # |k⃗| = ω # >> Note that a fixed wavevector only applies to a single frequency. # Any broadband source is incident at a given angle # for only a single frequency. # >> In order to model the S-polarization, we must use an Ey source. # This example involves just the P-polarization. # If normal incidence, force number of dimensions to be 1 if theta_r == 0: dimensions = 1 else: dimensions = 3 # In Meep, a 1d cell is defined along the z direction. # When k⃗ is not set, only the Ex and Hy field components are permitted. sources = [ mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Ex, center=mp.Vector3(0, 0, -0.5 * sz + dpml)) ] sim = mp.Simulation(cell_size=cell_size, boundary_layers=pml_layers, sources=sources, k_point=k, dimensions=dimensions, resolution=resolution) refl_fr = mp.FluxRegion(center=mp.Vector3(0, 0, -0.25 * sz)) refl = sim.add_flux(fcen, df, nfreq, refl_fr) sim.run(until_after_sources=mp.stop_when_fields_decayed( 50, mp.Ex, mp.Vector3(0, 0, -0.5 * sz + dpml), 1e-9)) empty_flux = mp.get_fluxes(refl) empty_data = sim.get_flux_data(refl) sim.reset_meep() # add a block with n=3.5 for the air-dielectric interface geometry = [ mp.Block(mp.Vector3(mp.inf, mp.inf, 0.5 * sz), center=mp.Vector3(0, 0, 0.25 * sz), material=mp.Medium(index=3.5)) ] sim = mp.Simulation(cell_size=cell_size, geometry=geometry, boundary_layers=pml_layers, sources=sources, k_point=k, dimensions=dimensions, resolution=resolution) refl = sim.add_flux(fcen, df, nfreq, refl_fr) sim.load_minus_flux_data(refl, empty_data) sim.run(until_after_sources=mp.stop_when_fields_decayed( 50, mp.Ex, mp.Vector3(0, 0, -0.5 * sz + dpml), 1e-9)) refl_flux = mp.get_fluxes(refl) freqs = mp.get_flux_freqs(refl) for i in range(nfreq): print("refl:, {}, {}, {}, {}".format( k.x, 1 / freqs[i], math.degrees(math.asin(k.x / freqs[i])), # if freq is freqmin -refl_flux[i] / empty_flux[i]))
resolution=resolution) refl_fr = mp.FluxRegion(center=mp.Vector3(0,0,-0.25*sz)) refl = sim.add_flux(fcen, df, nfreq, refl_fr) sim.run(until_after_sources=mp.stop_when_fields_decayed(50, mp.Ex, mp.Vector3(), 1e-9)) empty_flux = mp.get_fluxes(refl) empty_data = sim.get_flux_data(refl) sim.reset_meep() geometry = [ mp.Block(mp.Vector3(mp.inf,mp.inf,0.5*sz), center=mp.Vector3(0,0,0.25*sz), material=fused_quartz) ] sim = mp.Simulation(cell_size=cell_size, boundary_layers=pml_layers, geometry=geometry, sources=sources, dimensions=1, resolution=resolution) refl = sim.add_flux(fcen, df, nfreq, refl_fr) sim.load_minus_flux_data(refl, empty_data) sim.run(until_after_sources=mp.stop_when_fields_decayed(50, mp.Ex, mp.Vector3(), 1e-9)) refl_flux = mp.get_fluxes(refl) freqs = mp.get_flux_freqs(refl) for i in range(nfreq): print("refl:, {}, {}".format(1/freqs[i],-refl_flux[i]/empty_flux[i]))
def refl_angular(self, theta): theta_r = math.radians(theta) # wavevector (in source medium); plane of incidence is XZ k = mp.Vector3(0, 0, 1).rotate(mp.Vector3(0, 1, 0), theta_r).scale(self.n1 * self.fmin) if theta == 0: dimensions = 1 else: dimensions = 3 cell_size = mp.Vector3(z=self.sz) pml_layers = [mp.PML(self.dpml)] sources = [ mp.Source( mp.GaussianSource(self.fcen, fwidth=self.df), component=mp.Ex, # P polarization center=mp.Vector3(z=-0.5 * self.sz + self.dpml)) ] sim = mp.Simulation(resolution=self.resolution, cell_size=cell_size, dimensions=dimensions, default_material=mp.Medium(index=self.n1), sources=sources, boundary_layers=pml_layers, k_point=k) mon_pt = -0.5 * self.sz + self.dpml + 0.25 * self.dz refl_fr = mp.FluxRegion(center=mp.Vector3(z=mon_pt)) refl = sim.add_flux(self.fcen, self.df, self.nfreq, refl_fr) termination_cond = mp.stop_when_fields_decayed(50, mp.Ex, mp.Vector3(z=mon_pt), 1e-9) sim.run(until_after_sources=termination_cond) empty_data = sim.get_flux_data(refl) empty_flux = mp.get_fluxes(refl) sim.reset_meep() geometry = [ mp.Block(size=mp.Vector3(mp.inf, mp.inf, 0.5 * self.sz), center=mp.Vector3(z=0.25 * self.sz), material=mp.Medium(index=self.n2)) ] sim = mp.Simulation(resolution=self.resolution, cell_size=cell_size, dimensions=dimensions, default_material=mp.Medium(index=self.n1), sources=sources, boundary_layers=pml_layers, k_point=k, geometry=geometry) refl = sim.add_flux(self.fcen, self.df, self.nfreq, refl_fr) sim.load_minus_flux_data(refl, empty_data) sim.run(until_after_sources=termination_cond) refl_flux = mp.get_fluxes(refl) freqs = mp.get_flux_freqs(refl) Rs = -np.array(refl_flux) / np.array(empty_flux) thetas = [] for i in range(self.nfreq): thetas.append(math.asin(k.x / (self.n1 * freqs[i]))) return freqs, thetas, Rs
default_material=CdSe, boundary_layers=pml_layers, eps_averaging=False, geometry=[], ensure_periodicity=True, sources=sources, dimensions=3, resolution=resolution) before_block = sim.add_flux(1 / 0.550, 0.5, 5, secfr) sim.run(until=60) before_block_flux = mp.get_fluxes(before_block) before_block_flux_data = sim.get_flux_data(before_block) flux_freqs = mp.get_flux_freqs(before_block) sim.reset_meep() geometry = [ mp.Block(mp.Vector3(1, cell.y, cell.z), center=mp.Vector3(-2), material=mp.Medium(index=1.6)) ] # cadmium selineid QD geometry.append( mp.Block(mp.Vector3(1, cell.z, cell.z), center=mp.Vector3(-1), material=mp.Medium(index=2.52))) numberof = int(cell.y // (2 * fingersize)) + 1
size=mp.Vector3(0,2*w,0)) #location of the flux region. refl = sim.add_flux(fcen, df, nfreq, refl_fr) #capture of the actual flux. # transmitted flux region...tran_fr tran_fr=mp.FluxRegion(center=mp.Vector3(0.5*sx-dpml-0.5,wvg_ycen,0), size=mp.Vector3(0,2*w,0)) #location of the flux region. tran=sim.add_flux(fcen,df,nfreq,tran_fr) #capture of the actual flux. pt=mp.Vector3(0.5*sx-dpml-0.5,wvg_ycen) sim.run(until_after_sources=mp.stop_when_fields_decayed(50,mp.Ez,pt,1e-3)) straight_refl_data=sim.get_flux_data(refl) straight_tran_data=sim.get_flux_data(tran) # save incident power for reflection and transmission planes (sanity check to make sure that flux is transmitted along wg without loss). straight_tran_flux=mp.get_fluxes(tran) straight_refl_flux=mp.get_fluxes(refl) flux_freqs=mp.get_flux_freqs(refl) # end of normalisation run #plot results wl=[] #wavelgnth (inverse of frequency). RNs=[] #Reflectance_Normal_straight_wg. TNs=[] #Transmittance_Normal_straight_wg. for i in range(nfreq): wl=np.append(wl, 1/flux_freqs[i]) RNs=np.append(RNs,straight_refl_flux[i]) TNs=np.append(TNs,straight_tran_flux[i]) plt.subplot(311)
sim.run(until=600) # Calculate the scattering params for each waveguide bands = [1,2,3] # just look at first, second, and third, TE modes m1_results = sim.get_eigenmode_coefficients(m1,[1],eig_parity=(mp.ODD_Z+mp.EVEN_Y)).alpha m2_results = sim.get_eigenmode_coefficients(m2,bands,eig_parity=(mp.ODD_Z+mp.EVEN_Y)).alpha a1 = m1_results[:,:,0] #forward wave b1 = m1_results[:,:,1] #backward wave a2 = m2_results[:,:,0] #forward wave b2 = m2_results[:,:,1] #backward wave S12_mode1 = a2[0,:] / a1[0,:] S12_mode2 = a2[1,:] / a1[0,:] S12_mode3 = a2[2,:] / a1[0,:] freqs = np.array(mp.get_flux_freqs(m1)) # visualize results plt.figure() plt.semilogy(1/freqs,np.abs(S12_mode1)**2,'-o',label='S12 Input Mode 1 Output Mode 1') plt.semilogy(1/freqs,np.abs(S12_mode2)**2,'-o',label='S12 Input Mode 1 Output Mode 2') plt.semilogy(1/freqs,np.abs(S12_mode3)**2,'-o',label='S12 Input Mode 1 Output Mode 3') plt.ylabel('Power') plt.xlabel('Wavelength (microns)') plt.legend() plt.grid(True) plt.savefig('Results.png') plt.show()
refl_after = sim.add_flux(fcen, df, nfreq, refl_fr2) # transmitted flux tran_fr = mp.FluxRegion(center=mp.Vector3(sx/2-dpml-2.5,sy/2-5, 0), size=mp.Vector3(0,2*4,0)) tran = sim.add_flux(fcen, df, nfreq, tran_fr) tran_fr2 = mp.FluxRegion(center=mp.Vector3(-(sx/2-dpml-2.5),sy/2-5, 0), size=mp.Vector3(0,2*4,0)) tran2= sim.add_flux(fcen, df, nfreq, tran_fr) pt = mp.Vector3(sx/2-dpml-0.5,sy/2-5,0) sim.use_output_directory() sim.run(until_after_sources=mp.stop_when_fields_decayed(10,mp.Ez,pt,1e-3)) #mp.at_beginning(mp.output_epsilon), mp.at_every(0.1, mp.output_png(mp.Ez, "-Zc dkbluered")), fluxfreqs=mp.get_flux_freqs(refl_before) reflectedflux_after=mp.get_fluxes(refl_after) reflectedflux_before=mp.get_fluxes(refl_before) infrontofsrcflux=mp.get_fluxes(infrontofsrc) tran_flux = mp.get_fluxes(tran) tran2_flux = mp.get_fluxes(tran2) refl, tran=[],[] freq, refl_after_fl, refl_before_fl, tran2 = [],[],[],[] infrontofsrc=[] for i in range(nfreq): freq=np.append(freq, fluxfreqs[i]) infrontofsrc=np.append(infrontofsrc, infrontofsrcflux[i]) refl_after=np.append(refl_after_fl, reflectedflux_after[i]) refl_before=np.append(refl_before_fl, reflectedflux_before[i]) tran=np.append(tran, tran_flux[i])
def test_refl_angular(self): resolution = 100 dpml = 1.0 sz = 10 sz = sz + 2 * dpml cell_size = mp.Vector3(z=sz) pml_layers = [mp.PML(dpml)] wvl_min = 0.4 wvl_max = 0.8 fmin = 1 / wvl_max fmax = 1 / wvl_min fcen = 0.5 * (fmin + fmax) df = fmax - fmin nfreq = 50 theta_r = math.radians(0) k = mp.Vector3(math.sin(theta_r), 0, math.cos(theta_r)).scale(fcen) dimensions = 1 sources = [mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Ex, center=mp.Vector3(z=-0.5 * sz + dpml))] sim = mp.Simulation(cell_size=cell_size, boundary_layers=pml_layers, sources=sources, k_point=k, dimensions=dimensions, resolution=resolution) refl_fr = mp.FluxRegion(center=mp.Vector3(z=-0.25 * sz)) refl = sim.add_flux(fcen, df, nfreq, refl_fr) sim.run(until_after_sources=mp.stop_when_fields_decayed(50, mp.Ex, mp.Vector3(z=-0.5 * sz + dpml), 1e-9)) empty_data = sim.get_flux_data(refl) sim.reset_meep() geometry = [mp.Block(mp.Vector3(mp.inf, mp.inf, 0.5 * sz), center=mp.Vector3(z=0.25 * sz), material=mp.Medium(index=3.5))] sim = mp.Simulation(cell_size=cell_size, geometry=geometry, boundary_layers=pml_layers, sources=sources, k_point=k, dimensions=dimensions, resolution=resolution) refl = sim.add_flux(fcen, df, nfreq, refl_fr) sim.load_minus_flux_data(refl, empty_data) sim.run(until_after_sources=mp.stop_when_fields_decayed(50, mp.Ex, mp.Vector3(z=-0.5 * sz + dpml), 1e-9)) refl_flux = mp.get_fluxes(refl) freqs = mp.get_flux_freqs(refl) expected = [ (1.25, -1.123696883299492e-6), (1.2755102040816326, -2.5749667658387866e-6), (1.3010204081632653, -5.70480204599006e-6), (1.3265306122448979, -1.2220464827582253e-5), (1.3520408163265305, -2.531247480206961e-5), (1.3775510204081631, -5.069850309492639e-5), (1.4030612244897958, -9.819256552437341e-5), (1.4285714285714284, -1.8390448659017395e-4), (1.454081632653061, -3.330762066794769e-4), (1.4795918367346936, -5.833650417163753e-4), (1.5051020408163263, -9.8807834237052e-4), (1.5306122448979589, -0.001618472171445976), (1.5561224489795915, -0.0025638388059825985), (1.5816326530612241, -0.003927863989816029), (1.6071428571428568, -0.005819831283556752), (1.6326530612244894, -0.008339881000982728), (1.658163265306122, -0.011558769654206626), (1.6836734693877546, -0.015494308354153143), (1.7091836734693873, -0.02008850084337135), (1.73469387755102, -0.025190871516857616), (1.7602040816326525, -0.030553756123198477), (1.7857142857142851, -0.03584404966066722), (1.8112244897959178, -0.040672967700428275), (1.8367346938775504, -0.04464118393086191), (1.862244897959183, -0.047392712128477496), (1.8877551020408156, -0.048667403362887635), (1.9132653061224483, -0.048341494285878264), (1.938775510204081, -0.04644739000778679), (1.9642857142857135, -0.043168390293742316), (1.9897959183673462, -0.0388094755730579), (2.0153061224489788, -0.03375052221907117), (2.0408163265306114, -0.02839209067703472), (2.066326530612244, -0.023104245646230648), (2.0918367346938767, -0.01818725699718267), (2.1173469387755093, -0.013849270759480073), (2.142857142857142, -0.010201733597436358), (2.1683673469387745, -0.007269616609175294), (2.193877551020407, -0.005011210495189995), (2.21938775510204, -0.0033417192031464896), (2.2448979591836724, -0.0021557351734376256), (2.270408163265305, -0.0013453062176115673), (2.2959183673469377, -8.121742663131631e-4), (2.3214285714285703, -4.7433135191915683e-4), (2.346938775510203, -2.6799188013374266e-4), (2.3724489795918355, -1.464781343401766e-4), (2.397959183673468, -7.745339273024636e-5), (2.423469387755101, -3.9621374769542025e-5), (2.4489795918367334, -1.9608458558430508e-5), (2.474489795918366, -9.38818477949983e-6), (2.4999999999999987, -4.3484671364929225e-6), ] np.testing.assert_allclose(expected, list(zip(freqs, refl_flux)), rtol=1e-6)
def run_mode_coeffs(self, mode_num, kpoint_func, nf=1, resolution=15): w = 1 # width of waveguide L = 10 # length of waveguide Si = mp.Medium(epsilon=12.0) dair = 3.0 dpml = 3.0 sx = dpml + L + dpml sy = dpml + dair + w + dair + dpml cell_size = mp.Vector3(sx, sy, 0) prism_x = sx + 1 prism_y = w / 2 vertices = [mp.Vector3(-prism_x, prism_y), mp.Vector3(prism_x, prism_y), mp.Vector3(prism_x, -prism_y), mp.Vector3(-prism_x, -prism_y)] geometry = [mp.Prism(vertices, height=mp.inf, material=Si)] boundary_layers = [mp.PML(dpml)] # mode frequency fcen = 0.20 # > 0.5/sqrt(11) to have at least 2 modes df = 0.5*fcen source=mp.EigenModeSource(src=mp.GaussianSource(fcen, fwidth=df), eig_band=mode_num, size=mp.Vector3(0,sy-2*dpml,0), center=mp.Vector3(-0.5*sx+dpml,0,0), eig_match_freq=True, eig_resolution=2*resolution) sim = mp.Simulation(resolution=resolution, cell_size=cell_size, boundary_layers=boundary_layers, geometry=geometry, sources=[source], symmetries=[mp.Mirror(mp.Y, phase=1 if mode_num % 2 == 1 else -1)]) xm = 0.5*sx - dpml # x-coordinate of monitor mflux = sim.add_mode_monitor(fcen, df, nf, mp.ModeRegion(center=mp.Vector3(xm,0), size=mp.Vector3(0,sy-2*dpml))) mode_flux = sim.add_flux(fcen, df, nf, mp.FluxRegion(center=mp.Vector3(xm,0), size=mp.Vector3(0,sy-2*dpml))) # sim.run(until_after_sources=mp.stop_when_fields_decayed(50, mp.Ez, mp.Vector3(-0.5*sx+dpml,0), 1e-10)) sim.run(until_after_sources=200) ################################################## # If the number of analysis frequencies is >1, we # are testing the unit-power normalization # of the eigenmode source: we observe the total # power flux through the mode_flux monitor (which # equals the total power emitted by the source as # there is no scattering in this ideal waveguide) # and check that it agrees with the prediction # of the eig_power() class method in EigenmodeSource. ################################################## if nf>1: power_observed=mp.get_fluxes(mode_flux) freqs=mp.get_flux_freqs(mode_flux) power_expected=[source.eig_power(f) for f in freqs] return freqs, power_expected, power_observed modes_to_check = [1, 2] # indices of modes for which to compute expansion coefficients res = sim.get_eigenmode_coefficients(mflux, modes_to_check, kpoint_func=kpoint_func) self.assertTrue(res.kpoints[0].close(mp.Vector3(0.604301, 0, 0))) self.assertTrue(res.kpoints[1].close(mp.Vector3(0.494353, 0, 0), tol=1e-2)) self.assertTrue(res.kdom[0].close(mp.Vector3(0.604301, 0, 0))) self.assertTrue(res.kdom[1].close(mp.Vector3(0.494353, 0, 0), tol=1e-2)) mode_power = mp.get_fluxes(mode_flux)[0] TestPassed = True TOLERANCE = 5.0e-3 c0 = res.alpha[mode_num - 1, 0, 0] # coefficient of forward-traveling wave for mode #mode_num for nm in range(1, len(modes_to_check)+1): if nm != mode_num: cfrel = np.abs(res.alpha[nm - 1, 0, 0]) / np.abs(c0) cbrel = np.abs(res.alpha[nm - 1, 0, 1]) / np.abs(c0) if cfrel > TOLERANCE or cbrel > TOLERANCE: TestPassed = False self.sim = sim # test 1: coefficient of excited mode >> coeffs of all other modes self.assertTrue(TestPassed, msg="cfrel: {}, cbrel: {}".format(cfrel, cbrel)) # test 2: |mode coeff|^2 = power self.assertAlmostEqual(mode_power / abs(c0**2), 1.0, places=1) return res
def test_transmission_spectrum(self): expected = [ (0.15, 7.218492264696595e-6), (0.1504008016032064, 6.445696315927592e-6), (0.1508016032064128, 5.140949243632777e-6), (0.15120240480961922, 3.6159747936427164e-6), (0.15160320641282563, 2.263940553705969e-6), (0.15200400801603203, 1.4757165844336744e-6), (0.15240480961923844, 1.5491803919142815e-6), (0.15280561122244485, 2.612053246626972e-6), (0.15320641282565126, 4.577504371188737e-6), (0.15360721442885766, 7.1459089162998185e-6), (0.15400801603206407, 9.856622013418823e-6), (0.15440881763527048, 1.2182309227954296e-5), (0.1548096192384769, 1.3647726444709649e-5), (0.1552104208416833, 1.3947420613633674e-5), (0.1556112224448897, 1.303466755716231e-5), (0.1560120240480961, 1.115807915037775e-5), (0.15641282565130252, 8.832335196969796e-6), (0.15681362725450892, 6.743645773127985e-6), (0.15721442885771533, 5.605913756087576e-6), (0.15761523046092174, 5.996668564026961e-6), (0.15801603206412815, 8.209400611614078e-6), (0.15841683366733456, 1.2158641936828497e-5), (0.15881763527054096, 1.73653230513453e-5), (0.15921843687374737, 2.303382576477893e-5), (0.15961923847695378, 2.821180350795834e-5), (0.1600200400801602, 3.200359292911769e-5), (0.1604208416833666, 3.3792624373001934e-5), (0.160821643286573, 3.342171394788991e-5), (0.1612224448897794, 3.1284866146526904e-5), (0.16162324649298582, 2.830022088581398e-5), (0.16202404809619222, 2.5758413657344014e-5), (0.16242484969939863, 2.506899997971769e-5), (0.16282565130260504, 2.7453508915303887e-5), (0.16322645290581145, 3.365089813497114e-5), (0.16362725450901786, 4.370486834112e-5), (0.16402805611222426, 5.689050715055283e-5), (0.16442885771543067, 7.181133157470506e-5), (0.16482965931863708, 8.666168027415369e-5), (0.16523046092184349, 9.961094123261317e-5), (0.1656312625250499, 1.0923388232657953e-4), (0.1660320641282563, 1.1489334204708105e-4), (0.1664328657314627, 1.1698318060032011e-4), (0.16683366733466912, 1.169621456132733e-4), (0.16723446893787552, 1.1714995241571987e-4), (0.16763527054108193, 1.2030783847222252e-4), (0.16803607214428834, 1.2907652919660887e-4), ] self.sim.sources = [ mp.Source(mp.GaussianSource(self.fcen, fwidth=self.df), mp.Ey, mp.Vector3(self.dpml + (-0.5 * self.sx)), size=mp.Vector3(0, self.w)) ] self.sim.symmetries = [mp.Mirror(mp.Y, phase=-1)] freg = mp.FluxRegion(center=mp.Vector3((0.5 * self.sx) - self.dpml - 0.5), size=mp.Vector3(0, 2 * self.w)) trans = self.sim.add_flux(self.fcen, self.df, self.nfreq, freg) self.sim.run( until_after_sources=mp.stop_when_fields_decayed( 50, mp.Ey, mp.Vector3((0.5 * self.sx) - self.dpml - 0.5, 0), 1e-1) ) res = zip(mp.get_flux_freqs(trans), mp.get_fluxes(trans)) for e, r in zip(expected, res): np.testing.assert_allclose(e, r)
def simulation_fun(): resolution = 200 geom = common.geom sig = common.sig # source parameters fcen = common.fcen df = common.df df2 = df * 1.4 # source frequency width nfreq = 101 # number of frequency bins pol = common.pol # polarization src_cmpt = eval('mp.{}'.format(pol)) theta = common.theta # incident angle theta_r = math.radians(theta) # material n_GaSb = 3.8 mat_src = mp.Medium(index=n_GaSb) if geom == "Pda": mat_metal = mym.lossy_Pd(common.r) elif geom in ("Pd", "Empty"): mat_metal = mat.Pd else: sys.exit("Wrong materials") # geometry # from bottom to top sx = 0.1 sxx = 0.1 # periodic along x direction d_back = 0.3 d_metal = 0.7 d_src = 1 dpml = 2 sy = d_back + d_metal + d_src syy = sy + 2 * dpml cell_size = mp.Vector3(sxx, syy, 0) boundary_layers = [mp.PML(thickness=dpml, direction=mp.Y)] if geom == "Empty": geometry = [ mp.Block(size=mp.Vector3(sxx, syy, mp.inf), center=mp.Vector3(0, 0, 0), material=mat_src) ] else: tts = [d_back, d_metal] ccs = my.center_from_thickness(tts, -sy / 2) geometry = [ mp.Block(size=mp.Vector3(sxx, syy, mp.inf), center=mp.Vector3(0, 0, 0), material=mat_src), mp.Block(size=mp.Vector3(sxx, tts[1], mp.inf), center=mp.Vector3(0, ccs[1], 0), material=mat_metal), ] # bloch k vector k = mp.Vector3(math.sin(theta_r), math.cos(theta_r), 0).scale( fcen * mym.get_refractive_index(fcen, mat_src).real) amp_func = lambda x: cmath.exp(1j * 2 * math.pi * k.dot(x)) # oblique source y0 = -sy / 2 + d_back + d_metal # metal/GaSb interface sources = [ mp.Source(mp.GaussianSource(fcen, fwidth=df2), component=src_cmpt, center=mp.Vector3(0, y0 + d_src * 0.8), size=mp.Vector3(sxx, 0), amp_func=amp_func) ] # setup simulations sim = mp.Simulation(cell_size=cell_size, geometry=geometry, boundary_layers=boundary_layers, sources=sources, k_point=k, force_complex_fields=True, filename_prefix=sig, resolution=resolution) # flux y_frs = [ y0 + d_src * 0.4, ] frs = [ mp.FluxRegion(center=mp.Vector3(0, y, 0), size=mp.Vector3(sxx, 0, 0), weight=-1) for y in y_frs ] trans = [sim.add_flux(fcen, df, nfreq, fr) for fr in frs] #### # define step function to display fluxes my_display_count = 0 step_time_flush = 10 step_time_print = 200 step_time_terminate = 50 def my_display_fluxes(sim): nonlocal my_display_count print('=' * 40) print('=' * 40) freqs = mp.get_flux_freqs(trans[0]) fluxes = [mp.get_fluxes(tran) for tran in trans] data = np.column_stack(( freqs, *fluxes, )) my.matrix_output(None, data, "{:10.3e}", "flux") my_display_count += 1 print('=' * 40) print('No. {} display at t={}'.format(my_display_count, step_time_print)) my.my_flush_step(sim) # run simulations pt_field = mp.Vector3(0.1 * sxx, y0 + d_src * 0.4, 0) # monitor point sim.run( # mp.at_beginning(mp.output_epsilon), mp.at_every(step_time_flush, my.my_flush_step), mp.at_every(step_time_print, my_display_fluxes), until_after_sources=mp.stop_when_fields_decayed( step_time_terminate, src_cmpt, pt_field, 1e-9)) sys.stdout.flush() # collect data freqs = mp.get_flux_freqs(trans[0]) fluxes = [mp.get_fluxes(tran) for tran in trans] data = np.column_stack(( freqs, *fluxes, )) # output fname = sig + ".dat" my.matrix_output(fname, data, "{:10.3e}", "flux")
def test_transmission_spectrum(self): expected = [ (0.15, 7.218492264696595e-6), (0.1504008016032064, 6.445696315927592e-6), (0.1508016032064128, 5.140949243632777e-6), (0.15120240480961922, 3.6159747936427164e-6), (0.15160320641282563, 2.263940553705969e-6), (0.15200400801603203, 1.4757165844336744e-6), (0.15240480961923844, 1.5491803919142815e-6), (0.15280561122244485, 2.612053246626972e-6), (0.15320641282565126, 4.577504371188737e-6), (0.15360721442885766, 7.1459089162998185e-6), (0.15400801603206407, 9.856622013418823e-6), (0.15440881763527048, 1.2182309227954296e-5), (0.1548096192384769, 1.3647726444709649e-5), (0.1552104208416833, 1.3947420613633674e-5), (0.1556112224448897, 1.303466755716231e-5), (0.1560120240480961, 1.115807915037775e-5), (0.15641282565130252, 8.832335196969796e-6), (0.15681362725450892, 6.743645773127985e-6), (0.15721442885771533, 5.605913756087576e-6), (0.15761523046092174, 5.996668564026961e-6), (0.15801603206412815, 8.209400611614078e-6), (0.15841683366733456, 1.2158641936828497e-5), (0.15881763527054096, 1.73653230513453e-5), (0.15921843687374737, 2.303382576477893e-5), (0.15961923847695378, 2.821180350795834e-5), (0.1600200400801602, 3.200359292911769e-5), (0.1604208416833666, 3.3792624373001934e-5), (0.160821643286573, 3.342171394788991e-5), (0.1612224448897794, 3.1284866146526904e-5), (0.16162324649298582, 2.830022088581398e-5), (0.16202404809619222, 2.5758413657344014e-5), (0.16242484969939863, 2.506899997971769e-5), (0.16282565130260504, 2.7453508915303887e-5), (0.16322645290581145, 3.365089813497114e-5), (0.16362725450901786, 4.370486834112e-5), (0.16402805611222426, 5.689050715055283e-5), (0.16442885771543067, 7.181133157470506e-5), (0.16482965931863708, 8.666168027415369e-5), (0.16523046092184349, 9.961094123261317e-5), (0.1656312625250499, 1.0923388232657953e-4), (0.1660320641282563, 1.1489334204708105e-4), (0.1664328657314627, 1.1698318060032011e-4), (0.16683366733466912, 1.169621456132733e-4), (0.16723446893787552, 1.1714995241571987e-4), (0.16763527054108193, 1.2030783847222252e-4), (0.16803607214428834, 1.2907652919660887e-4), ] self.sim.sources = [ mp.Source(mp.GaussianSource(self.fcen, fwidth=self.df), mp.Ey, mp.Vector3(self.dpml + (-0.5 * self.sx)), size=mp.Vector3(0, self.w)) ] self.sim.symmetries = [mp.Mirror(mp.Y, phase=-1)] freg = mp.FluxRegion(center=mp.Vector3((0.5 * self.sx) - self.dpml - 0.5), size=mp.Vector3(0, 2 * self.w)) trans = self.sim.add_flux(self.fcen, self.df, self.nfreq, freg) self.sim.run(until_after_sources=mp.stop_when_fields_decayed( 50, mp.Ey, mp.Vector3((0.5 * self.sx) - self.dpml - 0.5, 0), 1e-1)) res = zip(mp.get_flux_freqs(trans), mp.get_fluxes(trans)) for e, r in zip(expected, res): np.testing.assert_allclose(e, r)
def run_bend_flux(self, from_gdsii_file): # Normalization run self.init(no_bend=True, gdsii=from_gdsii_file) self.sim.run(until_after_sources=mp.stop_when_fields_decayed(50, mp.Ez, self.pt, 1e-3)) # Save flux data for use in real run below fdata = self.sim.get_flux_data(self.refl) expected = [ (0.1, 3.65231563251e-05, 3.68932495077e-05), (0.10101010101, 5.55606718876e-05, 5.6065539588e-05), (0.10202020202, 8.38211697478e-05, 8.44909864736e-05), (0.10303030303, 0.000125411162229, 0.000126268639045), (0.10404040404, 0.000186089117531, 0.000187135303398), (0.105050505051, 0.000273848867869, 0.000275039134667), (0.106060606061, 0.000399674037745, 0.000400880269423), (0.107070707071, 0.00057849953593, 0.000579454087881), (0.108080808081, 0.000830418432986, 0.000830635406881), (0.109090909091, 0.00118217282661, 0.00118084271347), (0.110101010101, 0.00166896468348, 0.00166481944189), (0.111111111111, 0.00233661613864, 0.00232776318321), (0.112121212121, 0.00324409729096, 0.00322782257917), (0.113131313131, 0.00446642217385, 0.00443896468822), (0.114141414141, 0.0060978895019, 0.0060541922825), (0.115151515152, 0.00825561352398, 0.00818906047274), (0.116161616162, 0.0110832518495, 0.010985404883), (0.117171717172, 0.0147547920552, 0.0146151488236), (0.118181818182, 0.0194782085272, 0.0192840042241), (0.119191919192, 0.0254987474079, 0.0252348211592), ] res = list(zip(mp.get_flux_freqs(self.trans), mp.get_fluxes(self.trans), mp.get_fluxes(self.refl))) tolerance = 1e-2 if from_gdsii_file else 1e-3 compare_arrays(self, np.array(expected), np.array(res[:20]), tol=tolerance) # Real run self.sim = None self.init(gdsii=from_gdsii_file) # Load flux data obtained from normalization run self.sim.load_minus_flux_data(self.refl, fdata) self.sim.run(until_after_sources=mp.stop_when_fields_decayed(50, mp.Ez, self.pt, 1e-3)) expected = [ (0.09999999999999999, 1.8392235204829767e-5, -7.259467687598002e-6), (0.10101010101010101, 2.7629932558236724e-5, -1.1107162110079347e-5), (0.10202020202020202, 4.1001228946782745e-5, -1.687561915798036e-5), (0.10303030303030304, 6.018966076122556e-5, -2.5425779493709066e-5), (0.10404040404040406, 8.758554071933231e-5, -3.794958119189475e-5), (0.10505050505050507, 1.2656696778129198e-4, -5.612512808928115e-5), (0.10606060606060609, 1.817948859871414e-4, -8.232188174309142e-5), (0.10707070707070711, 2.594514094902856e-4, -1.1981531280672989e-4), (0.10808080808080812, 3.6736164837695035e-4, -1.7300125173897737e-4), (0.10909090909090914, 5.150131339048232e-4, -2.476730940385436e-4), (0.11010101010101016, 7.136181099374187e-4, -3.5145561406042276e-4), (0.11111111111111117, 9.76491765781944e-4, -4.944142331545938e-4), (0.11212121212121219, 0.001320033637882244, -6.897357105189368e-4), (0.11313131313131321, 0.0017653940714397098, -9.543556354451615e-4), (0.11414141414141422, 0.0023404727796352857, -0.0013095604571818236), (0.11515151515151524, 0.0030813962415392098, -0.00178176942635486), (0.11616161616161626, 0.00403238648982478, -0.0024036650652026112), (0.11717171717171727, 0.005243320443599316, -0.003215529845495731), (0.11818181818181829, 0.0067654019326068, -0.004266367104375331), (0.11919191919191931, 0.008646855439680507, -0.005614491919262783), ] res = list(zip(mp.get_flux_freqs(self.trans), mp.get_fluxes(self.trans), mp.get_fluxes(self.refl))) tolerance = 1e-2 if from_gdsii_file else 1e-3 compare_arrays(self, np.array(expected), np.array(res[:20]), tol=tolerance)