def test_get_dft_array(self): sim = self.init() sim.init_sim() dft_fields = sim.add_dft_fields([mp.Ez], self.fcen, self.fcen, 1) fr = mp.FluxRegion(mp.Vector3(), size=mp.Vector3(self.sxy, self.sxy), direction=mp.X) dft_flux = sim.add_flux(self.fcen, 0, 1, fr) # volumes with zero thickness in x and y directions to test collapsing # of empty dimensions in DFT array and HDF5 output routines thin_x_volume = mp.volume(mp.vec(0.35 * self.sxy, -0.4 * self.sxy), mp.vec(0.35 * self.sxy, +0.4 * self.sxy)) thin_x_flux = sim.fields.add_dft_fields([mp.Ez], thin_x_volume, self.fcen, self.fcen, 1) thin_y_volume = mp.volume(mp.vec(-0.5 * self.sxy, 0.25 * self.sxy), mp.vec(+0.5 * self.sxy, 0.25 * self.sxy)) thin_y_flux = sim.fields.add_dft_flux(mp.Y, thin_y_volume, self.fcen, self.fcen, 1) sim.run(until_after_sources=100) # test proper collapsing of degenerate dimensions in HDF5 files and arrays thin_x_array = sim.get_dft_array(thin_x_flux, mp.Ez, 0) thin_y_array = sim.get_dft_array(thin_y_flux, mp.Ez, 0) np.testing.assert_equal(thin_x_array.ndim, 1) np.testing.assert_equal(thin_y_array.ndim, 1) sim.output_dft(thin_x_flux, 'thin-x-flux') sim.output_dft(thin_y_flux, 'thin-y-flux') with h5py.File('thin-x-flux.h5', 'r') as thin_x: thin_x_h5 = mp.complexarray(thin_x['ez_0.r'].value, thin_x['ez_0.i'].value) with h5py.File('thin-y-flux.h5', 'r') as thin_y: thin_y_h5 = mp.complexarray(thin_y['ez_0.r'].value, thin_y['ez_0.i'].value) np.testing.assert_allclose(thin_x_array, thin_x_h5) np.testing.assert_allclose(thin_y_array, thin_y_h5) # compare array data to HDF5 file content for fields and flux fields_arr = sim.get_dft_array(dft_fields, mp.Ez, 0) flux_arr = sim.get_dft_array(dft_flux, mp.Ez, 0) sim.output_dft(dft_fields, 'dft-fields') sim.output_dft(dft_flux, 'dft-flux') with h5py.File('dft-fields.h5', 'r') as fields, h5py.File('dft-flux.h5', 'r') as flux: exp_fields = mp.complexarray(fields['ez_0.r'].value, fields['ez_0.i'].value) exp_flux = mp.complexarray(flux['ez_0.r'].value, flux['ez_0.i'].value) np.testing.assert_allclose(exp_fields, fields_arr) np.testing.assert_allclose(exp_flux, flux_arr)
def test_get_dft_array(self): sim = self.init() sim.init_sim() dft_fields = sim.add_dft_fields([mp.Ez], self.fcen, self.fcen, 1) fr = mp.FluxRegion(mp.Vector3(), size=mp.Vector3(self.sxy, self.sxy), direction=mp.X) dft_flux = sim.add_flux(self.fcen, 0, 1, fr) # volumes with zero thickness in x and y directions to test collapsing # of empty dimensions in DFT array and HDF5 output routines thin_x_volume = mp.volume( mp.vec(0.35*self.sxy, -0.4*self.sxy), mp.vec(0.35*self.sxy, +0.4*self.sxy)); thin_x_flux = sim.fields.add_dft_fields([mp.Ez], thin_x_volume, self.fcen, self.fcen, 1) thin_y_volume = mp.volume( mp.vec(-0.5*self.sxy, 0.25*self.sxy), mp.vec(+0.5*self.sxy, 0.25*self.sxy)); thin_y_flux = sim.fields.add_dft_flux(mp.Y, thin_y_volume, self.fcen, self.fcen, 1) sim.run(until_after_sources=100) # test proper collapsing of degenerate dimensions in HDF5 files and arrays thin_x_array = sim.get_dft_array(thin_x_flux, mp.Ez, 0) thin_y_array = sim.get_dft_array(thin_y_flux, mp.Ez, 0) np.testing.assert_equal(thin_x_array.ndim, 1) np.testing.assert_equal(thin_y_array.ndim, 1) sim.output_dft(thin_x_flux, 'thin-x-flux') sim.output_dft(thin_y_flux, 'thin-y-flux') with h5py.File('thin-x-flux.h5', 'r') as thin_x: thin_x_h5 = mp.complexarray(thin_x['ez_0.r'].value, thin_x['ez_0.i'].value) with h5py.File('thin-y-flux.h5', 'r') as thin_y: thin_y_h5 = mp.complexarray(thin_y['ez_0.r'].value, thin_y['ez_0.i'].value) np.testing.assert_allclose(thin_x_array, thin_x_h5) np.testing.assert_allclose(thin_y_array, thin_y_h5) # compare array data to HDF5 file content for fields and flux fields_arr = sim.get_dft_array(dft_fields, mp.Ez, 0) flux_arr = sim.get_dft_array(dft_flux, mp.Ez, 0) sim.output_dft(dft_fields, 'dft-fields') sim.output_dft(dft_flux, 'dft-flux') with h5py.File('dft-fields.h5', 'r') as fields, h5py.File('dft-flux.h5', 'r') as flux: exp_fields = mp.complexarray(fields['ez_0.r'].value, fields['ez_0.i'].value) exp_flux = mp.complexarray(flux['ez_0.r'].value, flux['ez_0.i'].value) np.testing.assert_allclose(exp_fields, fields_arr) np.testing.assert_allclose(exp_flux, flux_arr)
def test_get_center_and_size(self): v1d = mp.volume(mp.vec(-2), mp.vec(2)) center, size = mp.get_center_and_size(v1d) self.assertTrue(center.close(mp.Vector3())) self.assertTrue(size.close(mp.Vector3(z=4))) v2d = mp.volume(mp.vec(-1, -1), mp.vec(1, 1)) center, size = mp.get_center_and_size(v2d) self.assertTrue(center.close(mp.Vector3())) self.assertTrue(size.close(mp.Vector3(2, 2))) v3d = mp.volume(mp.vec(-1, -1, -1), mp.vec(1, 1, 1)) center, size = mp.get_center_and_size(v3d) self.assertTrue(center.close(mp.Vector3())) self.assertTrue(size.close(mp.Vector3(2, 2, 2)))
def main(args): n = 3.4 # index of waveguide w = 1.0 # width of waveguide r = 1.0 # inner radius of ring pad = 4 # padding between waveguide and edge of PML dpml = 2 # thickness of PML sxy = 2.0 * (r + w + pad + dpml) # cell size resolution = 10.0 gv = mp.voltwo(sxy, sxy, resolution) gv.center_origin() sym = mp.mirror(mp.Y, gv) # exploit the mirror symmetry in structure+source: the_structure = mp.structure(gv, dummy_eps, mp.pml(dpml), sym) # Create a ring waveguide by two overlapping cylinders - later objects # take precedence over earlier objects, so we put the outer cylinder first. # and the inner (air) cylinder second. objects = [] n2 = n * n dielectric = gm.Medium(epsilon_diag=gm.Vector3(n2, n2, n2)) objects.append(gm.Cylinder(r + w, material=dielectric)) objects.append(gm.Cylinder(r)) mp.set_materials_from_geometry(the_structure, objects) f = mp.fields(the_structure) # If we don't want to excite a specific mode symmetry, we can just # put a single point source at some arbitrary place, pointing in some # arbitrary direction. We will only look for TM modes (E out of the plane). fcen = 0.15 # pulse center frequency df = 0.1 src = GaussianSource(fcen, df) v = mp.volume(mp.vec(r + 0.1, 0.0), mp.vec(0.0, 0.0)) f.add_volume_source(mp.Ez, src, v) T = 300.0 stop_time = f.last_source_time() + T while f.round_time() < stop_time: f.step() # TODO: translate call to harminv # int bands = do_harminv (... Ez, vec3(r+0.1), fcen, df) # Output fields for one period at the end. (If we output # at a single time, we might accidentally catch the Ez field # when it is almost zero and get a distorted view.) DeltaT = 1.0 / (20 * fcen) NextOutputTime = f.round_time() + DeltaT while f.round_time() < 1.0 / fcen: f.step() if f.round_time() >= NextOutputTime: f.output_hdf5(mp.Ez, f.total_volume()) NextOutputTime += DeltaT
def __addMeepFluxplane(self, flx, meep_fields): '''Convert a fluxplane (runtime.basic.Fluxplane) into a Meep fluxplane and add it to the Meep fields object''' if not isinstance(flx, Fluxplane): raise InvalidArgumentException( "Invalid argument:: not of type runtime.basic.Fluxplane") LOG.debug( "Meep node %i -Creating Meep volume object for the flux plane..." % (self.node_nr)) vec1 = self.__make_meep_vec__(flx.north) vec2 = self.__make_meep_vec__(flx.south) print "Meep node %i : flux plane between points (%f , %f) and (%f , %f) " % ( self.node_nr, vec1.x(), vec1.y(), vec2.x(), vec2.y()) meepFlxVol = Meep.volume(vec1, vec2) center_freq = 1.0 / (float(flx.center_wavelength) / 1000.0) pw = ((float(flx.pulse_width) / 1000.0) / (float(flx.center_wavelength) / 1000.0)) * center_freq max_freq = center_freq + pw / 2.0 min_freq = center_freq - pw / 2.0 LOG.debug( "Meep node %i -Now adding the fluxplane to the Meep field..." % (self.node_nr)) meepFluxplane = meep_fields.add_dft_flux_plane( meepFlxVol, min_freq, max_freq, flx.number_of_sampling_freq) flx.flux_per_freq_callback = lambda: Meep.getFluxData(meepFluxplane) setattr(flx, "save_hdf5", lambda fn: self.__saveFluxToHDF5(meepFluxplane, fn)) setattr(flx, "scale", lambda factor: self.__scaleFluxplane(meepFluxplane, factor)) setattr(flx, "load_hdf5", lambda fn: self.__loadFluxFromHDF5(meepFluxplane, fn)) LOG.debug("Meep node %i -initializeing the fluxplane ..." % (self.node_nr)) flx.initialize() LOG.debug("Meep node %i - done with fluxplane ..." % (self.node_nr))
def __addMeepSource(self, src, meep_fields): '''Convert a source (runtime.basic.__EMSource__) into a Meep source and add it to the Meep fields object''' if not isinstance(src, __EMSource__): raise InvalidArgumentException("Invalid argument:: not of type runtime.basic.__EMSource__") LOG.debug("Meep node %i -Adding source...." %(self.node_nr)) #create Meep source object meepSource = None center_freq = 1.0 / (float(src.center_wavelength) / 1000.0) if isinstance(src, __GaussianSource__): pw = ( (float(src.pulse_width)/1000.0) / (float(src.center_wavelength)/1000.0) ) * center_freq meepSource = Meep.gaussian_src_time(center_freq, pw) if isinstance(src, __ContinuousSource__): meepSource = Meep.continuous_src_time(center_freq, src.smoothing_width, src.start_time, src.stop_time, src.cutoff) #create Meep component meepComp = self.__makeMeepComponent(src.field_component) #add source to the Meep field if isinstance(src, __EMPointSource__): vec = self.__make_meep_vec__(src.point) meep_fields.add_point_source(meepComp, meepSource, vec) print "Point source at point (%f , %f)" %(vec.x(), vec.y()) elif isinstance(src, __EMVolumeSource__): vec1 = self.__make_meep_vec__(src.south) vec2 = self.__make_meep_vec__(src.north) LOG.debug("Meep node %i -Creating volume for source plane..." %(self.node_nr)) meepSrcVol = Meep.volume(vec1, vec2) print "Meep node %i - source plane between points (%f , %f) and (%f , %f)." %(self.node_nr, vec1.x(), vec1.y(), vec2.x(), vec2.y()) LOG.debug("Meep node %i -Now adding the volume source to Meep..." %(self.node_nr)) if isinstance(src, __AmplitudeShapedSource__): ampl = AmplitudeFactor(source = src) Meep.set_AMPL_Callback(ampl.__disown__()) meep_fields.add_volume_source(meepComp, meepSource, meepSrcVol, Meep.AMPL) else: meep_fields.add_volume_source(meepComp, meepSource, meepSrcVol, src.amplitude) else: raise NotImplementedException("Unexpected case in MeepSimulationEngine::__addMeepSource")
def sim(): """perform scattering simulation""" sim = meep.Simulation(cell_size=cell, boundary_layers=[pml], geometry=geometry, default_material=medium, resolution=resolution) sim.init_fields() sim.init_sim() source(sim) freq = 1 / (600 * nm) # dft = sim.add_dft_fields([meep.Ex, meep.Ey, meep.Ez], freq, freq, 1, center=meep.Vector3(0,0,0), # size=meep.Vector3(L,L,0)) vol = meep.volume(meep.vec(-L / 2, -L / 2, 0), meep.vec(L / 2, L / 2, 0)) dft = sim.fields.add_dft_fields([meep.Ex, meep.Ey, meep.Ez], vol, freq, freq, 1) sim.run(until_after_sources=meep.stop_when_fields_decayed( .5 * um, decay, pt=meep.Vector3(0, 0, box[2] / 2), decay_by=1e-5)) # for i in range(100): # sim.fields.step() Ex = sim.get_dft_array(dft, meep.Ex, 0) Ey = sim.get_dft_array(dft, meep.Ey, 0) Ez = sim.get_dft_array(dft, meep.Ez, 0) E = np.array([Ex, Ey, Ez]) return dict(E=E)
def __init__(self, center, size=Vector3(), dims=2, is_cylindrical=False): self.center = center self.size = size self.dims = dims v1 = center - size.scale(0.5) v2 = center + size.scale(0.5) vec1 = py_v3_to_vec(self.dims, v1, is_cylindrical) vec2 = py_v3_to_vec(self.dims, v2, is_cylindrical) self.swigobj = mp.volume(vec1, vec2)
def setUp(self): def dummy_eps(v): return 1.0 gv = mp.voltwo(16, 16, 10) gv.center_origin() sym = mp.mirror(mp.Y, gv) the_structure = mp.structure(gv, dummy_eps, mp.pml(2), sym) objects = [] objects.append(Cylinder(1)) mp.set_materials_from_geometry(the_structure, objects) self.f = mp.fields(the_structure) self.v = mp.volume(mp.vec(1.1, 0.0), mp.vec(0.0, 0.0))
def add_flat_source(self,vol = volume(vec(0,1.0),vec(1.0,1.0)),comp = Ez): self.my_source = My_flat_source(vol,self.f,self.df,comp)
def vol_cut(self): if self.dim() == 2: return self.meep_space.surroundings() if self.dim() == 3: return volume(vec(0,self.gridSizeY/2.,0),vec(self.gridSizeX,self.gridSizeY/2.,self.gridSizeZ))
def bend_flux(no_bend): sx = 16.0 # size of cell in X direction sy = 32.0 # size of cell in Y direction pad = 4.0 # padding distance between waveguide and cell edge w = 1.0 # width of waveguide resolution = 10 # (set-param! resolution 10) gv = mp.voltwo(sx, sy, resolution) gv.center_origin() the_structure = mp.structure(gv, dummy_eps, mp.pml(1.0)) wvg_ycen = -0.5 * (sy - w - 2.0 * pad) # y center of horiz. wvg wvg_xcen = 0.5 * (sx - w - 2.0 * pad) # x center of vert. wvg e1 = gm.Vector3(1.0, 0.0, 0.0) e2 = gm.Vector3(0.0, 1.0, 0.0) e3 = gm.Vector3(0.0, 0.0, 1.0) dielectric = gm.Medium(epsilon_diag=gm.Vector3(12, 12, 12)) if no_bend: center = gm.Vector3(y=wvg_ycen) size = gm.Vector3(float('inf'), w, float('inf')) objects = [ gm.Block(size, e1, e2, e3, material=dielectric, center=center) ] mp.set_materials_from_geometry(the_structure, objects) else: objects = [] center = gm.Vector3(-0.5 * pad, wvg_ycen) size = gm.Vector3(sx - pad, w, float('inf')) objects.append( gm.Block(size, e1, e2, e3, material=dielectric, center=center)) center = gm.Vector3(wvg_xcen, 0.5 * pad) size = gm.Vector3(w, sy - pad, float('inf')) objects.append( gm.Block(size, e1, e2, e3, material=dielectric, center=center)) mp.set_materials_from_geometry(the_structure, objects) f = mp.fields(the_structure) fcen = 0.15 # pulse center frequency df = 0.1 src = GaussianSource(fcen, df) v = mp.volume(mp.vec(1.0 - 0.5 * sx, wvg_ycen), mp.vec(0.0, w)) f.add_volume_source(mp.Ez, src, v) f_start = fcen - 0.5 * df f_end = fcen + 0.5 * df nfreq = 100 # number of frequencies at which to compute flux if no_bend: trans_volume = mp.volume(mp.vec(0.5 * sx - 1.5, wvg_ycen), mp.vec(0.0, 2.0 * w)) else: trans_volume = mp.volume(mp.vec(wvg_xcen, 0.5 * sy - 1.5), mp.vec(2.0 * w, 0.0)) trans_vl = mp.volume_list(trans_volume, mp.Sz) trans = f.add_dft_flux(trans_vl, f_start, f_end, nfreq) refl_volume = mp.volume(mp.vec(-0.5 * sx + 1.5, wvg_ycen), mp.vec(0.0, 2.0 * w)) refl_vl = mp.volume_list(refl_volume, mp.Sz) refl = f.add_dft_flux(refl_vl, f_start, f_end, nfreq) dataname = "refl-flux" if not no_bend: refl.load_hdf5(f, dataname) refl.scale_dfts(-1.0) eval_point = mp.vec(0.5 * sx - 1.5, wvg_ycen) if no_bend else mp.vec( wvg_xcen, 0.5 * sy - 1.5) deltaT = 50.0 next_check_time = f.round_time() + deltaT tol = 1.0e-3 max_abs = 0.0 cur_max = 0.0 done = False while not done: f.step() # manually check fields-decayed condition absEz = abs(f.get_field(mp.Ez, eval_point)) cur_max = max(cur_max, absEz) if f.round_time() >= next_check_time: next_check_time += deltaT max_abs = max(max_abs, cur_max) if max_abs > 0.0 and cur_max < tol * max_abs: done = True cur_max = 0.0 # printf("%.2e %.2e %.2e %.2e\n",f.round_time(),absEz,max_abs,cur_max) if no_bend: refl.save_hdf5(f, dataname) print("{}\t\t | {}\t\t | {}".format("Time", "trans flux", "refl flux")) f0 = fcen - 0.5 * df fstep = df / (nfreq - 1) trans_flux = trans.flux() refl_flux = refl.flux() for nf in range(nfreq): print("{}\t\t | {}\t\t | {}".format(f0 + nf * fstep, trans_flux[nf], refl_flux[nf]))
def __init__( self, wA=1.0, wB=3.0, # smaller, larger waveguide thickness LWaveguide=3.0, # length of each waveguide section LTaper=3.0, pTaper=0, # taper length and smoothness index eps_waveguide=11.7, # permittivity inside waveguide eps_ambient=1.0, # permittivity of medium LY=6.0, # width of computational cell DPML=0.5, # PML thickness fcen=0.15, df=0.075, # center frequency / width band_num=1, # index of eigenmode source resolution=25.0, # grid points per unit length ): #-------------------------------------------------------------------- #- user-defined epsilon function #-------------------------------------------------------------------- eps_func = lambda loc: my_eps_func(loc, LTaper, pTaper, wA, wB, eps_ambient, eps_waveguide) #-------------------------------------------------------------------- #- eigenmode source at midpoint of smaller waveguide #-------------------------------------------------------------------- LX = 2.0 * (DPML + LWaveguide) + LTaper xA = -0.5 * LX + DPML + 0.5 * LWaveguide xB = +0.5 * LX - DPML - 0.5 * LWaveguide sources = [ mp.EigenModeSource(src=mp.GaussianSource(fcen, fwidth=df), center=mp.Vector3(xA, 0.0), size=mp.Vector3(0.0, LY), eig_band=band_num) ] self.sim = mp.Simulation(cell_size=mp.Vector3(LX, LY), resolution=resolution, boundary_layers=[mp.PML(DPML)], force_complex_fields=True, epsilon_func=eps_func, sources=sources) self.sim.run(mp.at_beginning(mp.output_epsilon), until=1.0) f = self.sim.fields #-------------------------------------------------- # add DFT flux regions at midpoints of smaller and larger waveguides #-------------------------------------------------- YP = 0.5 * LY - DPML self.vA = mp.volume(mp.vec(xA, -YP), mp.vec(xA, +YP)) self.vB = mp.volume(mp.vec(xB, -YP), mp.vec(xB, +YP)) nf = 1 self.fluxA = f.add_dft_flux_plane(self.vA, fcen - 0.5 * df, fcen + 0.5 * df, nf) self.fluxB = f.add_dft_flux_plane(self.vB, fcen - 0.5 * df, fcen + 0.5 * df, nf) #-------------------------------------------------- # save some other fields in the wvg_taper class for later use #-------------------------------------------------- self.xA = xA self.xB = xB self.wA = wA self.wB = wB self.LTaper = LTaper self.pTaper = pTaper self.fcen = fcen self.df = df self.band_num = band_num
def main(args): resolution = args.res w1 = 1 # width of waveguide 1 w2 = args.w2 # width of waveguide 2 Lw = 10 # length of waveguide 1 and 2 Lt = args.Lt # taper length Si = mp.Medium(epsilon=12.0) dair = 3.0 dpml = 3.0 sx = dpml + Lw + Lt + Lw + dpml sy = dpml + dair + w2 + dair + dpml cell_size = mp.Vector3(sx, sy, 0) geometry = [ mp.Block(material=Si, center=mp.Vector3(0, 0, 0), size=mp.Vector3(mp.inf, w1, mp.inf)), mp.Block(material=Si, center=mp.Vector3(0.5 * sx - 0.5 * (Lt + Lw + dpml), 0, 0), size=mp.Vector3(Lt + Lw + dpml, w2, mp.inf)) ] # form linear taper hh = w2 ww = 2 * Lt # taper angle (CCW, relative to +X axis) rot_theta = math.atan(0.5 * (w2 - w1) / Lt) pvec = mp.Vector3(-0.5 * sx + dpml + Lw, 0.5 * w1, 0) cvec = mp.Vector3(-0.5 * sx + dpml + Lw + 0.5 * ww, 0.5 * hh + 0.5 * w1, 0) rvec = cvec - pvec rrvec = rvec.rotate(mp.Vector3(0, 0, 1), rot_theta) geometry.append( mp.Block(material=mp.air, center=pvec + rrvec, size=mp.Vector3(ww, hh, mp.inf), e1=mp.Vector3(1, 0, 0).rotate(mp.Vector3(0, 0, 1), rot_theta), e2=mp.Vector3(0, 1, 0).rotate(mp.Vector3(0, 0, 1), rot_theta), e3=mp.Vector3(0, 0, 1))) pvec = mp.Vector3(-0.5 * sx + dpml + Lw, -0.5 * w1, 0) cvec = mp.Vector3(-0.5 * sx + dpml + Lw + 0.5 * ww, -(0.5 * hh + 0.5 * w1), 0) rvec = cvec - pvec rrvec = rvec.rotate(mp.Vector3(0, 0, 1), -rot_theta) geometry.append( mp.Block(material=mp.air, center=pvec + rrvec, size=mp.Vector3(ww, hh, mp.inf), e1=mp.Vector3(1, 0, 0).rotate(mp.Vector3(0, 0, 1), -rot_theta), e2=mp.Vector3(0, 1, 0).rotate(mp.Vector3(0, 0, 1), -rot_theta), e3=mp.Vector3(0, 0, 1))) boundary_layers = [mp.PML(dpml)] # mode frequency fcen = 0.15 sources = [ mp.EigenModeSource(src=mp.GaussianSource(fcen, fwidth=0.5 * fcen), component=mp.Ez, size=mp.Vector3(0, sy - 2 * dpml, 0), center=mp.Vector3(-0.5 * sx + dpml, 0, 0), eig_match_freq=True, eig_parity=mp.ODD_Z, eig_kpoint=mp.Vector3(0.4, 0, 0), eig_resolution=32) ] symmetries = [mp.Mirror(mp.Y, +1)] sim = mp.Simulation(resolution=resolution, cell_size=cell_size, boundary_layers=boundary_layers, geometry=geometry, sources=sources, symmetries=symmetries) xm = -0.5 * sx + dpml + 0.5 * Lw # x-coordinate of monitor mflux = sim.add_flux( fcen, 0, 1, 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(xm, 0), 1e-10)) bands = np.array( [1], dtype=np.int32 ) # indices of modes for which to compute expansion coefficients num_bands = 1 alpha = np.zeros( 2 * num_bands, dtype=np.complex128) # preallocate array to store coefficients vgrp = np.zeros(num_bands, dtype=np.float64) # also store mode group velocities mvol = mp.volume(mp.vec(xm, -0.5 * sy + dpml), mp.vec(xm, +0.5 * sy - dpml)) sim.get_eigenmode_coefficients(mflux, mp.X, mvol, bands, alpha, vgrp) alpha0Plus = alpha[2 * 0 + 0] # coefficient of forward-traveling fundamental mode alpha0Minus = alpha[2 * 0 + 1] # coefficient of backward-traveling fundamental mode print("refl:, {}, {:.8f}".format(Lt, abs(alpha0Minus)**2))