Esempio n. 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(center=mp.Vector3(0.35 * self.sxy),
                                  size=mp.Vector3(y=0.8 * self.sxy))
        thin_x_flux = sim.add_dft_fields([mp.Ez],
                                         self.fcen,
                                         self.fcen,
                                         1,
                                         where=thin_x_volume)
        thin_y_volume = mp.Volume(center=mp.Vector3(y=0.25 * self.sxy),
                                  size=mp.Vector3(x=self.sxy))
        thin_y_flux = sim.add_flux(self.fcen, self.fcen, 1,
                                   mp.FluxRegion(volume=thin_y_volume))

        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'][()],
                                        thin_x['ez_0.i'][()])

        with h5py.File('thin-y-flux.h5', 'r') as thin_y:
            thin_y_h5 = mp.complexarray(thin_y['ez_0.r'][()],
                                        thin_y['ez_0.i'][()])

        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'][()],
                                         fields['ez_0.i'][()])
            exp_flux = mp.complexarray(flux['ez_0.r'][()], flux['ez_0.i'][()])

        np.testing.assert_allclose(exp_fields, fields_arr)
        np.testing.assert_allclose(exp_flux, flux_arr)
Esempio n. 2
0
    def test_1d_with_partial_fragment(self):
        # A cell with z=26, with a 16 unit block in the center, split into 3 fragments,
        # with the first and last fragment of length 8, and 3/8 covered by the block,
        # and the middle fragment completely covered.

        # dft_flux with 2 volumes, 1 covering the first fragment and one covering
        # half of the second fragment
        dft_vecs = make_dft_vecs(flx_reg=[
            mp.FluxRegion(mp.Vector3(z=-9), mp.Vector3(z=8)),
            mp.FluxRegion(mp.Vector3(z=-2.5), mp.Vector3(z=5))
        ])
        fs = self.get_fragment_stats(mp.Vector3(z=16), mp.Vector3(z=26), 1, dft_vecs=dft_vecs)

        self.assertEqual(len(fs), 3)
        # Check first and last box sizes
        self.assertEqual(fs[0].box.low.z, -13)
        self.assertEqual(fs[0].box.high.z, -5)
        self.assertEqual(fs[2].box.low.z, 5)
        self.assertEqual(fs[2].box.high.z, 13)

        # Middle fragment is completely covered by block
        self.check_stats(fs[1], a_eps=100, a_mu=100, nonlin=300, susc=300, cond=300)
        # Outer fragments are 3/8 covered
        for i in [0, 2]:
            self.check_stats(fs[i], a_eps=30, a_mu=30, nonlin=90, susc=90, cond=90)

        # Check dft stats
        self.assertEqual(fs[0].num_dft_pixels, 8000)
        self.assertEqual(fs[1].num_dft_pixels, 5600)
        self.assertEqual(fs[2].num_dft_pixels, 0)
Esempio n. 3
0
    def set_source(self, sx, sy):
        sources = [mp.Source(mp.GaussianSource(self.fcen, fwidth=self.df), component=mp.Hx,
                             center=mp.Vector3(0, 0, self.src_pos),
                             size=mp.Vector3(sx, sy, 0),
                             amp_func=pw_amp(self.k, mp.Vector3(0, 0, self.src_pos)))]

        refl_fr = mp.FluxRegion(center=mp.Vector3(0, 0, self.z_flux_refl), size=mp.Vector3(sx, sy, 0))
        trans_fr = mp.FluxRegion(center=mp.Vector3(0, 0, self.z_flux_trans), size=mp.Vector3(sx, sy, 0))
        return sources, refl_fr, trans_fr
Esempio n. 4
0
    def init(self, no_bend=False):
        sx = 16
        sy = 32
        cell = mp.Vector3(sx, sy, 0)
        pad = 4
        w = 1
        wvg_ycen = -0.5 * (sy - w - (2 * pad))
        wvg_xcen = 0.5 * (sx - w - (2 * pad))
        height = 100

        if no_bend:
            no_bend_vertices = [mp.Vector3(-0.5 * sx - 5, wvg_ycen - 0.5 * w),
                                mp.Vector3(+0.5 * sx + 5, wvg_ycen - 0.5 * w),
                                mp.Vector3(+0.5 * sx + 5, wvg_ycen + 0.5 * w),
                                mp.Vector3(-0.5 * sx - 5, wvg_ycen + 0.5 * w)]

            geometry = [mp.Prism(no_bend_vertices, height, material=mp.Medium(epsilon=12))]
        else:
            bend_vertices = [mp.Vector3(-0.5 * sx, wvg_ycen - 0.5 * w),
                             mp.Vector3(wvg_xcen + 0.5 * w, wvg_ycen - 0.5 * w),
                             mp.Vector3(wvg_xcen + 0.5 * w, 0.5 * sy),
                             mp.Vector3(wvg_xcen - 0.5 * w, 0.5 * sy),
                             mp.Vector3(wvg_xcen - 0.5 * w, wvg_ycen + 0.5 * w),
                             mp.Vector3(-0.5 * sx, wvg_ycen + 0.5 * w)]

            geometry = [mp.Prism(bend_vertices, height, material=mp.Medium(epsilon=12))]

        fcen = 0.15
        df = 0.1
        sources = [mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Ez,
                             center=mp.Vector3(1 + (-0.5 * sx), wvg_ycen), size=mp.Vector3(0, w))]

        pml_layers = [mp.PML(1.0)]
        resolution = 10
        nfreq = 100

        self.sim = mp.Simulation(cell_size=cell,
                                 boundary_layers=pml_layers,
                                 geometry=geometry,
                                 sources=sources,
                                 resolution=resolution)

        if no_bend:
            fr = mp.FluxRegion(center=mp.Vector3((sx / 2) - 1.5, wvg_ycen), size=mp.Vector3(0, w * 2))
        else:
            fr = mp.FluxRegion(center=mp.Vector3(wvg_xcen, (sy / 2) - 1.5), size=mp.Vector3(w * 2, 0))

        self.trans = self.sim.add_flux(fcen, df, nfreq, fr)
        refl_fr = mp.FluxRegion(center=mp.Vector3((-0.5 * sx) + 1.5, wvg_ycen),
                                size=mp.Vector3(0, w * 2))

        self.refl = self.sim.add_flux(fcen, df, nfreq, refl_fr)

        if no_bend:
            self.pt = mp.Vector3((sx / 2) - 1.5, wvg_ycen)
        else:
            self.pt = mp.Vector3(wvg_xcen, (sy / 2) - 1.5)
Esempio n. 5
0
def main(args):

    sz = 100  # size of cell in z direction
    fcen = 1 / 3.0  # center frequency of source
    df = fcen / 20.0  # frequency width of source
    amp = args.amp  # amplitude of source
    k = 10**args.logk  # Kerr susceptibility
    dpml = 1.0  # PML thickness

    # We'll use an explicitly 1d simulation.  Setting dimensions=1 will actually
    # result in faster execution than just using two no-size dimensions.  However,
    # in this case Meep requires us to use E in the x direction (and H in y),
    # and our one no-size dimension must be z.
    dimensions = 1
    cell = mp.Vector3(0, 0, sz)
    pml_layers = mp.PML(dpml)
    resolution = 20

    # to put the same material in all space, we can just set the default material
    # and pass it to the Simulation constructor
    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)

    # frequency range for flux calculation
    nfreq = 400
    fmin = fcen / 2.0
    fmax = fcen * 4

    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)))
    trans1 = sim.add_flux(
        fcen, 0, 1, mp.FluxRegion(mp.Vector3(0, 0, 0.5 * sz - dpml - 0.5)))
    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))

    # sim.display_fluxes(trans)
    print("harmonics:, {}, {}, {}, {}".format(k, amp,
                                              mp.get_fluxes(trans1)[0],
                                              mp.get_fluxes(trans3)[0]))
Esempio n. 6
0
    def test_divide_parallel_processes(self):
        resolution = 20

        sxy = 4
        dpml = 1
        cell = mp.Vector3(sxy + 2 * dpml, sxy + 2 * dpml)

        pml_layers = [mp.PML(dpml)]

        n = mp.divide_parallel_processes(2)
        fcen = 1.0 / (n + 1)

        sources = [
            mp.Source(src=mp.GaussianSource(fcen, fwidth=0.2 * fcen),
                      center=mp.Vector3(),
                      component=mp.Ez)
        ]

        symmetries = [mp.Mirror(mp.X), mp.Mirror(mp.Y)]

        self.sim = mp.Simulation(cell_size=cell,
                                 resolution=resolution,
                                 sources=sources,
                                 symmetries=symmetries,
                                 boundary_layers=pml_layers)

        flux_box = self.sim.add_flux(fcen,
                                     0,
                                     1,
                                     mp.FluxRegion(mp.Vector3(y=0.5 * sxy),
                                                   size=mp.Vector3(sxy)),
                                     mp.FluxRegion(mp.Vector3(y=-0.5 * sxy),
                                                   size=mp.Vector3(sxy),
                                                   weight=-1),
                                     mp.FluxRegion(mp.Vector3(0.5 * sxy),
                                                   size=mp.Vector3(y=sxy)),
                                     mp.FluxRegion(mp.Vector3(-0.5 * sxy),
                                                   size=mp.Vector3(y=sxy),
                                                   weight=-1),
                                     decimation_factor=1)

        self.sim.run(until_after_sources=30)

        tot_flux = mp.get_fluxes(flux_box)[0]

        tot_fluxes = mp.merge_subgroup_data(tot_flux)
        fcens = mp.merge_subgroup_data(fcen)

        self.assertEqual(fcens[0], 1)
        self.assertEqual(fcens[1], 0.5)
        places = 4 if mp.is_single_precision() else 7
        self.assertAlmostEqual(tot_fluxes[0], 9.8628728533, places=places)
        self.assertAlmostEqual(tot_fluxes[1], 19.6537275387, places=places)
Esempio n. 7
0
    def test_chunks(self):
        sxy = 10
        cell = mp.Vector3(sxy, sxy, 0)

        fcen = 1.0  # pulse center frequency
        df = 0.1    # pulse width (in frequency)

        sources = [mp.Source(mp.GaussianSource(fcen, fwidth=df), mp.Ez, mp.Vector3())]

        dpml = 1.0
        pml_layers = [mp.PML(dpml)]
        resolution = 10

        sim = mp.Simulation(cell_size=cell,
                            boundary_layers=pml_layers,
                            sources=sources,
                            resolution=resolution,
                            split_chunks_evenly=False)

        sim.use_output_directory(temp_dir)

        top = mp.FluxRegion(center=mp.Vector3(0,+0.5*sxy-dpml), size=mp.Vector3(sxy-2*dpml,0), weight=+1.0)
        bot = mp.FluxRegion(center=mp.Vector3(0,-0.5*sxy+dpml), size=mp.Vector3(sxy-2*dpml,0), weight=-1.0)
        rgt = mp.FluxRegion(center=mp.Vector3(+0.5*sxy-dpml,0), size=mp.Vector3(0,sxy-2*dpml), weight=+1.0)
        lft = mp.FluxRegion(center=mp.Vector3(-0.5*sxy+dpml,0), size=mp.Vector3(0,sxy-2*dpml), weight=-1.0)

        tot_flux = sim.add_flux(fcen, 0, 1, top, bot, rgt, lft)

        sim.run(until_after_sources=mp.stop_when_fields_decayed(50, mp.Ez, mp.Vector3(), 1e-5))

        sim.save_flux('tot_flux', tot_flux)
        sim1 = sim

        geometry = [mp.Block(center=mp.Vector3(), size=mp.Vector3(sxy, sxy, mp.inf), material=mp.Medium(index=3.5)),
                    mp.Block(center=mp.Vector3(), size=mp.Vector3(sxy-2*dpml, sxy-2*dpml, mp.inf), material=mp.air)]

        sim = mp.Simulation(cell_size=cell,
                            geometry=geometry,
                            boundary_layers=pml_layers,
                            sources=sources,
                            resolution=resolution,
                            chunk_layout=sim1)

        sim.use_output_directory(temp_dir)

        tot_flux = sim.add_flux(fcen, 0, 1, top, bot, rgt, lft)

        sim.load_minus_flux('tot_flux', tot_flux)

        sim.run(until_after_sources=mp.stop_when_fields_decayed(50, mp.Ez, mp.Vector3(), 1e-5))

        self.assertAlmostEqual(86.90826609300862, mp.get_fluxes(tot_flux)[0])
    def test_1d_with_partial_fragment(self):
        # A cell with z=26, with a 16 unit block in the center

        # dft_flux with 2 volumes, 1 covering the first 10 units and one covering
        # half of the second 10
        dft_vecs = make_dft_vecs(flx_reg=[
            mp.FluxRegion(mp.Vector3(z=-9), mp.Vector3(z=8)),
            mp.FluxRegion(mp.Vector3(z=-2.5), mp.Vector3(z=5))
        ])
        fs = self.get_fragment_stats(mp.Vector3(z=16), mp.Vector3(z=26), 1, dft_vecs=dft_vecs)

        self.check_stats(fs, a_eps=260, a_mu=260, nonlin=480, susc=480, cond=480)
        # Check dft stats
        self.assertEqual(fs.num_dft_pixels, 10400)
Esempio n. 9
0
    def test_cyl(self):
        # A 30 x 30 cell, with a 10 x 10 block in the middle

        # flux covering top-left fragment, near2far covering top-middle, force covering top-right
        dft_vecs = make_dft_vecs([
            mp.FluxRegion(mp.Vector3(-10, z=10), size=mp.Vector3(10, z=10))
        ], [mp.Near2FarRegion(mp.Vector3(0, z=10), size=mp.Vector3(10, z=10))],
                                 [
                                     mp.ForceRegion(mp.Vector3(10, z=10),
                                                    direction=mp.X,
                                                    size=mp.Vector3(10, z=10))
                                 ])
        fs = self.get_fragment_stats(mp.Vector3(10, 0, 10),
                                     mp.Vector3(30, 0, 30),
                                     mp.CYLINDRICAL,
                                     dft_vecs=dft_vecs)
        self.assertEqual(fs.box.low.x, -15)
        self.assertEqual(fs.box.low.z, -15)
        self.assertEqual(fs.box.high.x, 15)
        self.assertEqual(fs.box.high.z, 15)
        self.check_stats(fs,
                         a_eps=10000,
                         a_mu=10000,
                         nonlin=30000,
                         susc=30000,
                         cond=30000)
        self.assertEqual(fs.num_dft_pixels, 2040000)
Esempio n. 10
0
    def _test_3d(self, sym, pml=[]):
        # A 30 x 30 x 30 cell with a 10 x 10 x 10 block placed at the center

        # flux covering lower-front-left 10x10x10, near2far covering lower-middle-left,
        # force covering lower-back-left
        dft_vecs = make_dft_vecs([
            mp.FluxRegion(mp.Vector3(-10, -10, -10),
                          size=mp.Vector3(10, 10, 10))
        ], [
            mp.Near2FarRegion(mp.Vector3(-10, -10, 0),
                              size=mp.Vector3(10, 10, 10))
        ], [
            mp.ForceRegion(mp.Vector3(-10, -10, 10),
                           direction=mp.X,
                           size=mp.Vector3(10, 10, 10))
        ])
        fs = self.get_fragment_stats(mp.Vector3(10, 10, 10),
                                     mp.Vector3(30, 30, 30),
                                     3,
                                     dft_vecs=dft_vecs,
                                     sym=sym,
                                     pml=pml)

        sym_factor = 8 if sym else 1
        self.check_stats(fs,
                         a_eps=1000000 / sym_factor,
                         a_mu=1000000 / sym_factor,
                         nonlin=3000000 / sym_factor,
                         susc=3000000 / sym_factor,
                         cond=3000000 / sym_factor)

        # Check DFT regions
        self.assertEqual(fs.num_dft_pixels, 102000000)
        self.fs = fs
Esempio n. 11
0
    def add_eigenmode_monitor(self,
                              port,
                              wavelength,
                              fwidth,
                              nfreq,
                              z=None,
                              height=None):
        """
        Adds an eigenmode monitor at the given port.

        :param port: Port at which the monitor is added
        :param wavelength: Center wavelength of the monitored spectrum
        :param fwidth: Width of the monitored spectrum
        :param nfreq: Number of monitored wavelengths
        :param z: Z-position of the monitor
        :param height: Height of the area for calculating the eigenmode
        :return: Added Meep-Monitor
        """

        size = [
            0, port.total_width * 2
        ] if port.angle % np.pi < np.pi / 4 else [port.total_width * 2, 0]
        monitor = self.sim.add_mode_monitor(
            1 / wavelength, fwidth, nfreq,
            mp.FluxRegion(mp.Vector3(*port.origin, z),
                          size=mp.Vector3(*size, height)))
        return monitor
Esempio n. 12
0
def compute_flux(m, n):
    if m == 2:
        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))
        ]
    else:
        sources = [
            mp.Source(mp.GaussianSource(fcen, fwidth=df),
                      component=mp.Ez,
                      center=mp.Vector3(0, -0.5 * sy + dAg + 0.5 * dsub),
                      size=mp.Vector3(sx, 0),
                      amp_func=src_amp_func(n))
        ]

    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
Esempio n. 13
0
def add_flux_plane(sim, fcen, df, nfreq, position, size):
    """add a flux plane to a meep simulation"""
    position = meep.Vector3(*position)
    size = meep.Vector3(*size)

    plane = meep.FluxRegion(center=position, size=size)
    return sim.add_flux(fcen, df, nfreq, plane)
Esempio n. 14
0
def get_refl_ref():
    geometry = [
        # mp.Block(
        # size=mp.Vector3(mp.inf, mp.inf, w),
        # center=mp.Vector3(0,0,0),
        # material=mp.perfect_electric_conductor),
    ]

    sim = mp.Simulation(cell_size=cell,
                        boundary_layers=pml_layers,
                        geometry=geometry,
                        sources=sources,
                        resolution=resolution,
                        k_point=mp.Vector3())


    refl_fr = mp.FluxRegion(center=mp.Vector3(0,0,-400), direction=mp.Y, weight=-1) 
    refl = sim.add_flux(fcen, df, nfreq, refl_fr)

    pt = mp.Vector3(0,0,-400)
    # sim.run(until_after_sources=mp.stop_when_fields_decayed(50,mp.Ex,pt,1e-3))
    sim.run(until=time)

    straight_refl_data = sim.get_flux_data(refl)

    return straight_refl_data
Esempio n. 15
0
    def _test_2d(self, sym, pml=[]):
        # A 30 x 30 cell, with a 10 x 10 block in the middle

        # flux covering top-left 10x10, near2far covering top-middle 10x10, force covering top-right
        dft_vecs = make_dft_vecs(
            [mp.FluxRegion(mp.Vector3(-10, 10), size=mp.Vector3(10, 10))],
            [mp.Near2FarRegion(mp.Vector3(0, 10), size=mp.Vector3(10, 10))],
            [mp.ForceRegion(mp.Vector3(10, 10), direction=mp.X, size=mp.Vector3(10, 10))]
        )
        fs = self.get_fragment_stats(mp.Vector3(10, 10), mp.Vector3(30, 30), 2,
                                     dft_vecs=dft_vecs, sym=sym, pml=pml)

        # Check fragment boxes
        self.assertEqual(fs.box.low.x, -15)
        self.assertEqual(fs.box.low.y, -15)
        self.assertEqual(fs.box.high.x, 15)
        self.assertEqual(fs.box.high.y, 15)

        # Middle fragment contains entire block
        sym_factor = 4 if sym else 1
        self.check_stats(fs,
                         a_eps=90000 / sym_factor,
                         a_mu=90000 / sym_factor,
                         nonlin=30000 / sym_factor,
                         susc=30000 / sym_factor,
                         cond=30000 / sym_factor)

        # Check DFT regions
        self.assertEqual(fs.num_dft_pixels, 2040000)
        self.fs = fs
Esempio n. 16
0
    def setUp(self):
        self.sz = 100
        fcen = 1 / 3.0
        df = fcen / 20.0
        self.amp = 1.0
        self.k = 1e-2
        self.dpml = 1.0
        dimensions = 1
        cell = mp.Vector3(0, 0, self.sz)

        default_material = mp.Medium(index=1, chi3=self.k)

        pml_layers = mp.PML(self.dpml)

        sources = mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Ex,
                            center=mp.Vector3(0, 0, (-0.5 * self.sz) + self.dpml), amplitude=self.amp)

        nfreq = 400
        fmin = fcen / 2.0
        fmax = fcen * 4

        self.sim = mp.Simulation(cell_size=cell,
                                 geometry=[],
                                 sources=[sources],
                                 boundary_layers=[pml_layers],
                                 default_material=default_material,
                                 resolution=20,
                                 dimensions=dimensions)

        fr = mp.FluxRegion(mp.Vector3(0, 0, (0.5 * self.sz) - self.dpml - 0.5))
        self.trans = self.sim.add_flux(0.5 * (fmin + fmax), fmax - fmin, nfreq, fr, decimation_factor=1)
        self.trans1 = self.sim.add_flux(fcen, 0, 1, fr, decimation_factor=1)
        self.trans3 = self.sim.add_flux(3 * fcen, 0, 1, fr, decimation_factor=1)
Esempio n. 17
0
    def _test_1d(self, sym, pml=[]):
        # A z=30 cell, with a size 10 block in the middle.

        # flux covering first 10 units, near2far covering second 10, and force covering third
        dft_vecs = make_dft_vecs(
            [mp.FluxRegion(mp.Vector3(z=-10), size=mp.Vector3(z=10))],
            [mp.Near2FarRegion(mp.Vector3(), size=mp.Vector3(z=10))], [
                mp.ForceRegion(
                    mp.Vector3(z=10), direction=mp.X, size=mp.Vector3(z=10))
            ])

        fs = self.get_fragment_stats(mp.Vector3(z=10),
                                     mp.Vector3(z=30),
                                     1,
                                     dft_vecs=dft_vecs,
                                     sym=sym,
                                     pml=pml)

        sym_factor = 2 if sym else 1
        self.check_stats(fs,
                         a_eps=100 / sym_factor,
                         a_mu=100 / sym_factor,
                         nonlin=300 / sym_factor,
                         susc=300 / sym_factor,
                         cond=300 / sym_factor)

        # Check DFT regions
        self.assertEqual(fs.num_dft_pixels, 40800)
        self.fs = fs
Esempio n. 18
0
    def _test_1d(self, sym):
        # A z=30 cell, split into three fragments of size 10 each, with a block
        # covering the middle fragment.

        # flux covering first fragment, near2far covering second, force covering third
        dft_vecs = make_dft_vecs(
            [mp.FluxRegion(mp.Vector3(z=-10), size=mp.Vector3(z=10))],
            [mp.Near2FarRegion(mp.Vector3(), size=mp.Vector3(z=10))],
            [mp.ForceRegion(mp.Vector3(z=10), direction=mp.X, size=mp.Vector3(z=10))]
        )

        fs = self.get_fragment_stats(mp.Vector3(z=10), mp.Vector3(z=30), 1, dft_vecs=dft_vecs, sym=sym)

        self.assertEqual(len(fs), 3)

        # First and last fragments have no geometry, only default_material
        for i in [0, 2]:
            self.check_stats(fs[i], 0, 0, 0, 0, 0)

        # Second fragment contains entire block
        sym_factor = 2 if sym else 1
        self.check_stats(fs[1],
                         a_eps=100 / sym_factor,
                         a_mu=100 / sym_factor,
                         nonlin=300 / sym_factor,
                         susc=300 / sym_factor,
                         cond=300 / sym_factor)

        # Check DFT regions
        self.assertEqual(fs[0].num_dft_pixels, 10240)
        self.assertEqual(fs[1].num_dft_pixels, 17120)
        self.assertEqual(fs[2].num_dft_pixels, 23840)
Esempio n. 19
0
    def register(self, sim):
        """ 'Register' the cell in a MEEP simulation to request computation of frequency-domain fields.

        Parameters
        ----------
        sim : mp.Simulation
        """
        self.sim = sim
        if self.celltype == 'flux':
            flux_region = mp.FluxRegion(self.region.center,
                                        self.region.size,
                                        direction=self.normal)
            self.dft_obj = sim.add_flux(self.fcen, self.df, self.nfreq,
                                        flux_region)
        else:
            self.dft_obj = sim.add_dft_fields(self.components,
                                              self.freqs[0],
                                              self.freqs[-1],
                                              self.nfreq,
                                              center=self.region.center,
                                              size=self.region.size)

        # take this opportunity to initialize simulation-dependent fields
        if self.grid is None:
            xyzw = sim.get_array_metadata(center=self.region.center,
                                          size=self.region.size,
                                          collapse=True,
                                          snap=True)
            fix_array_metadata(xyzw, self.region.center, self.region.size)
            self.grid = xyzw2grid(xyzw)
Esempio n. 20
0
    def _test_2d(self, sym):
        # A 30 x 30 cell, with a 10 x 10 block in the middle, split into 9 10 x 10 fragments.

        # flux covering top-left fragment, near2far covering top-middle, force covering top-right
        dft_vecs = make_dft_vecs(
            [mp.FluxRegion(mp.Vector3(-10, 10), size=mp.Vector3(10, 10))],
            [mp.Near2FarRegion(mp.Vector3(0, 10), size=mp.Vector3(10, 10))], [
                mp.ForceRegion(mp.Vector3(10, 10),
                               direction=mp.X,
                               size=mp.Vector3(10, 10))
            ])
        fs = self.get_fragment_stats(mp.Vector3(10, 10),
                                     mp.Vector3(30, 30),
                                     2,
                                     dft_vecs=dft_vecs,
                                     sym=sym)

        self.assertEqual(len(fs), 9)

        # Check fragment boxes
        self.assertEqual(fs[0].box.low.x, -15)
        self.assertEqual(fs[0].box.low.y, -15)
        self.assertEqual(fs[0].box.high.x, -5)
        self.assertEqual(fs[0].box.high.y, -5)

        self.assertEqual(fs[1].box.low.x, -15)
        self.assertEqual(fs[1].box.low.y, -5)
        self.assertEqual(fs[1].box.high.x, -5)
        self.assertEqual(fs[1].box.high.y, 5)

        self.assertEqual(fs[2].box.low.x, -15)
        self.assertEqual(fs[2].box.low.y, 5)
        self.assertEqual(fs[2].box.high.x, -5)
        self.assertEqual(fs[2].box.high.y, 15)

        # All fragments besides the middle one have no geometry, only default_material
        for i in [0, 1, 2, 3, 5, 6, 7, 8]:
            self.check_stats(fs[i], 0, 0, 0, 0, 0)

        # Middle fragment contains entire block
        idx = 4
        sym_factor = 4 if sym else 1
        self.check_stats(fs[idx],
                         a_eps=10000 / sym_factor,
                         a_mu=10000 / sym_factor,
                         nonlin=30000 / sym_factor,
                         susc=30000 / sym_factor,
                         cond=30000 / sym_factor)

        # Check DFT regions
        for i in [0, 3, 6]:
            self.assertEqual(fs[i].num_dft_pixels, 0)

        self.assertEqual(fs[1].num_dft_pixels, 8224)
        self.assertEqual(fs[4].num_dft_pixels, 11792)
        self.assertEqual(fs[7].num_dft_pixels, 21824)

        self.assertEqual(fs[2].num_dft_pixels, 411200)
        self.assertEqual(fs[5].num_dft_pixels, 589600)
        self.assertEqual(fs[8].num_dft_pixels, 1091200)
Esempio n. 21
0
    def _test_3d(self, sym):
        # A 30 x 30 x 30 cell with a 10 x 10 x 10 block placed at the center, split
        # into 27 10 x 10 x 10 fragments

        # flux covering lower-front-left fragment, near2far covering lower-middle-left,
        # force covering lower-back-left
        dft_vecs = make_dft_vecs(
            [mp.FluxRegion(mp.Vector3(-10, -10, -10), size=mp.Vector3(10, 10, 10))],
            [mp.Near2FarRegion(mp.Vector3(-10, -10, 0), size=mp.Vector3(10, 10, 10))],
            [mp.ForceRegion(mp.Vector3(-10, -10, 10), direction=mp.X, size=mp.Vector3(10, 10, 10))]
        )
        fs = self.get_fragment_stats(mp.Vector3(10, 10, 10), mp.Vector3(30, 30, 30), 3, dft_vecs=dft_vecs, sym=sym)

        self.assertEqual(len(fs), 27)

        # All fragments besides the middle one have no geometry, only default_material
        for i in range(27):
            if i == 13:
                continue
            self.check_stats(fs[i], 0, 0, 0, 0, 0)

        # Middle fragments contains entire block
        idx = 13
        sym_factor = 8 if sym else 1
        self.check_stats(fs[idx],
                         a_eps=10000 / sym_factor,
                         a_mu=10000 / sym_factor,
                         nonlin=30000 / sym_factor,
                         susc=30000 / sym_factor,
                         cond=30000 / sym_factor)

        # Check DFT regions
        self.assertEqual(fs[0].num_dft_pixels, 256000)
        self.assertEqual(fs[1].num_dft_pixels, 428000)
        self.assertEqual(fs[2].num_dft_pixels, 596000)
Esempio n. 22
0
def add_monitors(simulation, geo=None, **kwargs):
    geo = kwargs_to_geo(geo, **kwargs)

    # reflected flux
    refl_fr = mp.FluxRegion(center=mp.Vector3(-monitor_x(geo), 0, 0),
                            size=mp.Vector3(0, 2 * geo.sm_width,
                                            2 * geo.thickness))
    refl = simulation.add_flux(fcen, df, nfreq, refl_fr)

    # transmitted flux
    tran_fr = mp.FluxRegion(center=mp.Vector3(monitor_x(geo), 0, 0),
                            size=mp.Vector3(0, 2 * geo.sm_width,
                                            2 * geo.thickness))
    tran = simulation.add_flux(fcen, df, nfreq, tran_fr)

    return refl, tran
 def get_flux_region(self):
     p, a, w = self.pos, int(np.round(self.angle)) % 360, self.width
     if a % 90 < 1e-3:
         raise ValueError('Flux can only be measured on orthogonal lines'
                          f'got: {a}')
     s = [w, 0] if a in {0, 180} else [0, w]
     return mp.FluxRegion(center=mp.Vector3(*p), size=mp.Vector3(*s))
Esempio n. 24
0
    def test_cyl(self):
        # A 30 x 30 cell, with a 10 x 10 block in the middle, split into 9 10 x 10 fragments.

        # flux covering top-left fragment, near2far covering top-middle, force covering top-right
        dft_vecs = make_dft_vecs([
            mp.FluxRegion(mp.Vector3(-10, z=10), size=mp.Vector3(10, z=10))
        ], [mp.Near2FarRegion(mp.Vector3(0, z=10), size=mp.Vector3(10, z=10))],
                                 [
                                     mp.ForceRegion(mp.Vector3(10, z=10),
                                                    mp.X,
                                                    size=mp.Vector3(10, z=10))
                                 ])
        fs = self.get_fragment_stats(mp.Vector3(10, 0, 10),
                                     mp.Vector3(30, 0, 30),
                                     mp.CYLINDRICAL,
                                     dft_vecs=dft_vecs)

        self.assertEqual(len(fs), 9)

        # Check fragment boxes
        self.assertEqual(fs[0].box.low.x, -15)
        self.assertEqual(fs[0].box.low.z, -15)
        self.assertEqual(fs[0].box.high.x, -5)
        self.assertEqual(fs[0].box.high.z, -5)

        self.assertEqual(fs[1].box.low.x, -15)
        self.assertEqual(fs[1].box.low.z, -5)
        self.assertEqual(fs[1].box.high.x, -5)
        self.assertEqual(fs[1].box.high.z, 5)

        self.assertEqual(fs[2].box.low.x, -15)
        self.assertEqual(fs[2].box.low.z, 5)
        self.assertEqual(fs[2].box.high.x, -5)
        self.assertEqual(fs[2].box.high.z, 15)

        # All fragments besides the middle one have no geometry, only default_material
        for i in [0, 1, 2, 3, 5, 6, 7, 8]:
            self.check_stats(fs[i], 0, 0, 0, 0, 0)

        # Middle fragment contains entire block
        idx = 4
        self.check_stats(fs[idx],
                         a_eps=1000,
                         a_mu=1000,
                         nonlin=3000,
                         susc=3000,
                         cond=3000)

        # Check DFT regions
        for i in [0, 3, 6]:
            self.assertEqual(fs[i].num_dft_pixels, 0)

        self.assertEqual(fs[1].num_dft_pixels, 10240)
        self.assertEqual(fs[4].num_dft_pixels, 17120)
        self.assertEqual(fs[7].num_dft_pixels, 23840)

        self.assertEqual(fs[2].num_dft_pixels, 51200)
        self.assertEqual(fs[5].num_dft_pixels, 85600)
        self.assertEqual(fs[8].num_dft_pixels, 119200)
Esempio n. 25
0
    def test_eigsrc_kz(self, kz_2d):
        resolution = 30  # pixels/um

        cell_size = mp.Vector3(14, 14)

        pml_layers = [mp.PML(thickness=2)]

        geometry = [
            mp.Block(center=mp.Vector3(),
                     size=mp.Vector3(mp.inf, 1, mp.inf),
                     material=mp.Medium(epsilon=12))
        ]

        fsrc = 0.3  # frequency of eigenmode or constant-amplitude source
        bnum = 1  # band number of eigenmode
        kz = 0.2  # fixed out-of-plane wavevector component

        sources = [
            mp.EigenModeSource(src=mp.GaussianSource(fsrc, fwidth=0.2 * fsrc),
                               center=mp.Vector3(),
                               size=mp.Vector3(y=14),
                               eig_band=bnum,
                               eig_parity=mp.EVEN_Y,
                               eig_match_freq=True)
        ]

        sim = mp.Simulation(cell_size=cell_size,
                            resolution=resolution,
                            boundary_layers=pml_layers,
                            sources=sources,
                            geometry=geometry,
                            symmetries=[mp.Mirror(mp.Y)],
                            k_point=mp.Vector3(z=kz),
                            kz_2d=kz_2d)

        tran = sim.add_flux(
            fsrc, 0, 1,
            mp.FluxRegion(center=mp.Vector3(x=5), size=mp.Vector3(y=14)))

        sim.run(until_after_sources=50)

        res = sim.get_eigenmode_coefficients(tran, [1, 2],
                                             eig_parity=mp.EVEN_Y)

        total_flux = mp.get_fluxes(tran)[0]
        mode1_flux = abs(res.alpha[0, 0, 0])**2
        mode2_flux = abs(res.alpha[1, 0, 0])**2

        mode1_frac = 0.99
        self.assertGreater(mode1_flux / total_flux, mode1_frac)
        self.assertLess(mode2_flux / total_flux, 1 - mode1_frac)

        d = 3.5
        ez1 = sim.get_field_point(mp.Ez, mp.Vector3(2.3, -5.7, 4.8))
        ez2 = sim.get_field_point(mp.Ez, mp.Vector3(2.3, -5.7, 4.8 + d))
        ratio_ez = ez2 / ez1
        phase_diff = cmath.exp(1j * 2 * cmath.pi * kz * d)
        self.assertAlmostEqual(ratio_ez.real, phase_diff.real, places=10)
        self.assertAlmostEqual(ratio_ez.imag, phase_diff.imag, places=10)
Esempio n. 26
0
    def test_waveguide_flux(self):
        cell_size = mp.Vector3(10, 10, 0)

        pml_layers = [mp.PML(thickness=2.0)]

        rot_angles = range(
            0, 60, 20)  # rotation angle of waveguide, CCW around z-axis

        fluxes = []
        for t in rot_angles:
            rot_angle = math.radians(t)
            sources = [
                mp.EigenModeSource(src=mp.GaussianSource(1.0, fwidth=0.1),
                                   size=mp.Vector3(y=10),
                                   center=mp.Vector3(x=-3),
                                   direction=mp.NO_DIRECTION,
                                   eig_kpoint=mp.Vector3(
                                       math.cos(rot_angle),
                                       math.sin(rot_angle), 0),
                                   eig_band=1,
                                   eig_parity=mp.ODD_Z,
                                   eig_match_freq=True)
            ]

            geometry = [
                mp.Block(center=mp.Vector3(),
                         size=mp.Vector3(mp.inf, 1, mp.inf),
                         e1=mp.Vector3(1, 0, 0).rotate(mp.Vector3(0, 0, 1),
                                                       rot_angle),
                         e2=mp.Vector3(0, 1, 0).rotate(mp.Vector3(0, 0, 1),
                                                       rot_angle),
                         material=mp.Medium(index=1.5))
            ]

            sim = mp.Simulation(cell_size=cell_size,
                                resolution=50,
                                boundary_layers=pml_layers,
                                sources=sources,
                                geometry=geometry)

            tran = sim.add_flux(
                1.0, 0, 1,
                mp.FluxRegion(center=mp.Vector3(x=3), size=mp.Vector3(y=10)))

            sim.run(until_after_sources=100)

            fluxes.append(mp.get_fluxes(tran)[0])
            print("flux:, {:.2f}, {:.6f}".format(t, fluxes[-1]))

        self.assertAlmostEqual(fluxes[0], fluxes[1], places=0)
        self.assertAlmostEqual(fluxes[1], fluxes[2], places=0)

        # self.assertAlmostEqual(fluxes[0], fluxes[2], places=0)
        # sadly the above line requires a workaround due to the
        # following annoying numerical accident:
        # AssertionError: 100.33815231783535 != 99.81145343586365 within 0 places
        f0, f2 = fluxes[0], fluxes[2]
        self.assertLess(abs(f0 - f2), 0.5 * max(abs(f0), abs(f2)))
Esempio n. 27
0
 def register_monitors(self, frequencies):
     self.frequencies = np.asarray(frequencies)
     self.monitor = self.sim.add_mode_monitor(frequencies,
                                              mp.FluxRegion(
                                                  center=self.volume.center,
                                                  size=self.volume.size),
                                              yee_grid=True)
     self.normal_direction = self.monitor.normal_direction
     return self.monitor
Esempio n. 28
0
    def refl_planar(self, theta, special_kz):
        resolution = 100  # pixels/um

        dpml = 1.0
        sx = 3+2*dpml
        sy = 1/resolution
        cell_size = mp.Vector3(sx,sy)
        pml_layers = [mp.PML(dpml,direction=mp.X)]

        fcen = 1.0 # source wavelength = 1 um

        k_point = mp.Vector3(z=math.sin(theta)).scale(fcen)

        sources = [mp.Source(mp.GaussianSource(fcen,fwidth=0.2*fcen),
                             component=mp.Ez,
                             center=mp.Vector3(-0.5*sx+dpml),
                             size=mp.Vector3(y=sy))]

        sim = mp.Simulation(cell_size=cell_size,
                            boundary_layers=pml_layers,
                            sources=sources,
                            k_point=k_point,
                            special_kz=special_kz,
                            resolution=resolution)

        refl_fr = mp.FluxRegion(center=mp.Vector3(-0.25*sx),
                                size=mp.Vector3(y=sy))
        refl = sim.add_flux(fcen,0,1,refl_fr)

        sim.run(until_after_sources=mp.stop_when_fields_decayed(50,mp.Ez,mp.Vector3(),1e-9))

        empty_flux = mp.get_fluxes(refl)
        empty_data = sim.get_flux_data(refl)
        sim.reset_meep()

        geometry = [mp.Block(material=mp.Medium(index=3.5),
                             size=mp.Vector3(0.5*sx,mp.inf,mp.inf),
                             center=mp.Vector3(0.25*sx))]

        sim = mp.Simulation(cell_size=cell_size,
                            boundary_layers=pml_layers,
                            geometry=geometry,
                            sources=sources,
                            k_point=k_point,
                            special_kz=special_kz,
                            resolution=resolution)

        refl = sim.add_flux(fcen,0,1,refl_fr)
        sim.load_minus_flux_data(refl,empty_data)

        sim.run(until_after_sources=mp.stop_when_fields_decayed(50,mp.Ez,mp.Vector3(),1e-9))

        refl_flux = mp.get_fluxes(refl)

        Rmeep = -refl_flux[0]/empty_flux[0]
        return Rmeep
Esempio n. 29
0
    def test_check_material_frequencies(self):
        mat = mp.Medium(valid_freq_range=mp.FreqRange(min=10, max=20))
        invalid_sources = [
            [mp.Source(mp.GaussianSource(5, fwidth=1), mp.Ez, mp.Vector3())],
            [mp.Source(mp.ContinuousSource(10, fwidth=1), mp.Ez, mp.Vector3())],
            [mp.Source(mp.GaussianSource(10, width=1), mp.Ez, mp.Vector3())],
            [mp.Source(mp.GaussianSource(20, width=1), mp.Ez, mp.Vector3())],
        ]

        cell_size = mp.Vector3(5, 5)
        resolution = 5

        def check_warnings(sim, should_warn=True):
            with warnings.catch_warnings(record=True) as w:
                warnings.simplefilter("always")
                sim.run(until=5)

                if should_warn:
                    self.assertEqual(len(w), 1)
                    self.assertIn("material", str(w[-1].message))
                else:
                    self.assertEqual(len(w), 0)

        geom = [mp.Sphere(0.2, material=mat)]

        for s in invalid_sources:
            # Check for invalid extra_materials
            sim = mp.Simulation(cell_size=cell_size, resolution=resolution, sources=s, extra_materials=[mat])
            check_warnings(sim)

            # Check for invalid geometry materials
            sim = mp.Simulation(cell_size=cell_size, resolution=resolution, sources=s, geometry=geom)
            check_warnings(sim)

        valid_sources = [
            [mp.Source(mp.GaussianSource(15, fwidth=1), mp.Ez, mp.Vector3())],
            [mp.Source(mp.ContinuousSource(15, width=5), mp.Ez, mp.Vector3())]
        ]

        for s in valid_sources:
            sim = mp.Simulation(cell_size=cell_size, resolution=resolution, sources=s, extra_materials=[mat])
            check_warnings(sim, False)

        # Check DFT frequencies

        # Invalid extra_materials
        sim = mp.Simulation(cell_size=cell_size, resolution=resolution, sources=valid_sources[0],
                            extra_materials=[mat])
        fregion = mp.FluxRegion(center=mp.Vector3(0, 1), size=mp.Vector3(2, 2), direction=mp.X)
        sim.add_flux(18, 6, 2, fregion)
        check_warnings(sim)

        # Invalid geometry material
        sim = mp.Simulation(cell_size=cell_size, resolution=resolution, sources=valid_sources[0], geometry=geom)
        sim.add_flux(18, 6, 2, fregion)
        check_warnings(sim)
Esempio n. 30
0
    def register_monitors(self, fcen, df, nf):
        self.fcen = fcen
        self.df = df
        self.nf = nf

        self.monitor = self.sim.add_mode_monitor(
            self.fcen, self.df, self.nf,
            mp.FluxRegion(center=self.volume.center, size=self.volume.size))
        self.normal_direction = self.monitor.normal_direction
        return self.monitor