示例#1
0
    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)
示例#2
0
文件: dft_fields.py 项目: oskooi/meep
    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)
示例#3
0
    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)))
示例#4
0
    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)))
示例#5
0
文件: test_ring.py 项目: eroen/meep
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
示例#6
0
 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))
示例#7
0
 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")
示例#8
0
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)
示例#9
0
    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)
示例#10
0
    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))
示例#11
0
文件: source.py 项目: oskooi/meep
    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)) 
示例#14
0
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]))
示例#15
0
    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
示例#16
0
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))