예제 #1
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
예제 #2
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)
예제 #3
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
예제 #4
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)
예제 #5
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)
예제 #6
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
예제 #7
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)
예제 #8
0
def forward_simulation(design_params):
    matgrid = mp.MaterialGrid(mp.Vector3(Nr, 0, Nz),
                              SiO2,
                              Si,
                              weights=design_params.reshape(Nr, 1, Nz))

    geometry = [
        mp.Block(center=mp.Vector3(design_r / 2, 0, 0),
                 size=mp.Vector3(design_r, 0, design_z),
                 material=matgrid)
    ]

    sim = mp.Simulation(resolution=resolution,
                        cell_size=cell_size,
                        boundary_layers=boundary_layers,
                        sources=source,
                        geometry=geometry,
                        dimensions=dimensions,
                        m=m)

    frequencies = [fcen]
    far_x = [mp.Vector3(5, 0, 20)]
    mode = sim.add_near2far(
        frequencies,
        mp.Near2FarRegion(center=mp.Vector3(
            design_r / 2, 0, (sz / 2 - dpml + design_z / 2) / 2),
                          size=mp.Vector3(design_r, 0, 0),
                          weight=+1))

    sim.run(until_after_sources=1200)
    Er = sim.get_farfield(mode, far_x[0])
    sim.reset_meep()

    return abs(Er[0])**2
예제 #9
0
파일: test.py 프로젝트: domeeneka/Meep
    def define_near_field_box(self,
                              wvl_near_min=0.6,
                              wvl_near_max=1,
                              nfreq_near=1,
                              near_box_dis=1):

        if self._sim is not None:
            self.wvl_near_min = wvl_near_min
            self.wvl_near_max = wvl_near_max
            self.nfreq_near = nfreq_near
            self.near_box_dis = near_box_dis  #distance from the whole structure

            self.f_near_min = 1 / self.wvl_near_max
            self.f_near_max = 1 / self.wvl_near_min
            self.fcen_near = 0.5 * (self.f_near_min + self.f_near_max)
            self.df_near = self.f_near_max - self.f_near_min

            #upper surface
            self.near_field_z1 = self._sim.add_near2far(
                self.fcen_near, self.df_near, self.nfreq_near,
                mp.Near2FarRegion(center=mp.Vector3(
                    0, 0,
                    self.source_position + self.shift + self.near_box_dis),
                                  size=mp.Vector3(2 * self.near_box_dis),
                                  direction=mp.Z,
                                  weight=+1))
예제 #10
0
    def free_space_radiation(self):
        sxy = 4
        dpml = 1
        cell_size = mp.Vector3(sxy + 2 * dpml, sxy + 2 * dpml)

        pml_layers = [mp.PML(dpml)]

        fcen = 1 / self.wvl

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

        if self.src_cmpt == mp.Hz:
            symmetries = [mp.Mirror(mp.X, phase=-1), mp.Mirror(mp.Y, phase=-1)]
        elif self.src_cmpt == mp.Ez:
            symmetries = [mp.Mirror(mp.X, phase=+1), mp.Mirror(mp.Y, phase=+1)]
        else:
            symmetries = []

        sim = mp.Simulation(cell_size=cell_size,
                            resolution=self.resolution,
                            sources=sources,
                            symmetries=symmetries,
                            boundary_layers=pml_layers,
                            default_material=mp.Medium(index=self.n))

        nearfield_box = sim.add_near2far(
            fcen, 0, 1,
            mp.Near2FarRegion(center=mp.Vector3(0, +0.5 * sxy),
                              size=mp.Vector3(sxy, 0)),
            mp.Near2FarRegion(center=mp.Vector3(0, -0.5 * sxy),
                              size=mp.Vector3(sxy, 0),
                              weight=-1),
            mp.Near2FarRegion(center=mp.Vector3(+0.5 * sxy, 0),
                              size=mp.Vector3(0, sxy)),
            mp.Near2FarRegion(center=mp.Vector3(-0.5 * sxy, 0),
                              size=mp.Vector3(0, sxy),
                              weight=-1))

        sim.run(until_after_sources=mp.stop_when_dft_decayed())

        Pr = self.radial_flux(sim, nearfield_box, self.r)

        return Pr
예제 #11
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)
예제 #12
0
    def setUp(self):
        resolution = 50
        sxy = 4
        dpml = 1
        cell = mp.Vector3(sxy + 2 * dpml, sxy + 2 * dpml, 0)

        pml_layers = mp.PML(dpml)

        fcen = 1.0
        df = 0.4
        self.src_cmpt = mp.Ez

        sources = mp.Source(
            src=mp.GaussianSource(fcen, fwidth=df),
            center=mp.Vector3(),
            component=self.src_cmpt
        )

        if self.src_cmpt == mp.Ex:
            symmetries = [mp.Mirror(mp.Y)]
        elif self.src_cmpt == mp.Ey:
            symmetries = [mp.Mirror(mp.X)]
        elif self.src_cmpt == 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]
        )

        self.nearfield = self.sim.add_near2far(
            fcen,
            0,
            1,
            mp.Near2FarRegion(mp.Vector3(0, 0.5 * sxy), size=mp.Vector3(sxy)),
            mp.Near2FarRegion(mp.Vector3(0, -0.5 * sxy), size=mp.Vector3(sxy), weight=-1.0),
            mp.Near2FarRegion(mp.Vector3(0.5 * sxy), size=mp.Vector3(0, sxy)),
            mp.Near2FarRegion(mp.Vector3(-0.5 * sxy), size=mp.Vector3(0, sxy), weight=-1.0)
        )
예제 #13
0
def near2far(position, size):
    """create 6 near2far planes of a closed box with size and position"""
    position = meep.Vector3(*position)
    size = meep.Vector3(*size)

    x1 = meep.Near2FarRegion(center=position - meep.Vector3(size[0] / 2, 0, 0),
                             size=meep.Vector3(0, size[1], size[2]),
                             weight=-1)

    x2 = meep.Near2FarRegion(center=position + meep.Vector3(size[0] / 2, 0, 0),
                             size=meep.Vector3(0, size[1], size[2]),
                             weight=1)

    y1 = meep.Near2FarRegion(center=position - meep.Vector3(0, size[1] / 2, 0),
                             size=meep.Vector3(size[0], 0, size[2]),
                             weight=-1)

    y2 = meep.Near2FarRegion(center=position + meep.Vector3(0, size[1] / 2, 0),
                             size=meep.Vector3(size[0], 0, size[2]),
                             weight=1)

    z1 = meep.Near2FarRegion(center=position - meep.Vector3(0, 0, size[2] / 2),
                             size=meep.Vector3(size[0], size[1], 0),
                             weight=-1)

    z2 = meep.Near2FarRegion(center=position + meep.Vector3(0, 0, size[2] / 2),
                             size=meep.Vector3(size[0], size[1], 0),
                             weight=1)

    return [x1, x2, y1, y2, z1, z2]
예제 #14
0
def adjoint_solver(design_params):

    design_variables = mp.MaterialGrid(mp.Vector3(Nr, 0, Nz), SiO2, Si)
    design_region = mpa.DesignRegion(
        design_variables,
        volume=mp.Volume(center=mp.Vector3(design_r / 2, 0, 0),
                         size=mp.Vector3(design_r, 0, design_z)))
    geometry = [
        mp.Block(center=design_region.center,
                 size=design_region.size,
                 material=design_variables)
    ]

    sim = mp.Simulation(cell_size=cell_size,
                        boundary_layers=boundary_layers,
                        geometry=geometry,
                        sources=source,
                        resolution=resolution,
                        dimensions=dimensions,
                        m=m)

    far_x = [mp.Vector3(5, 0, 20)]
    NearRegions = [
        mp.Near2FarRegion(center=mp.Vector3(
            design_r / 2, 0, (sz / 2 - dpml + design_z / 2) / 2),
                          size=mp.Vector3(design_r, 0, 0),
                          weight=+1)
    ]
    FarFields = mpa.Near2FarFields(sim, NearRegions, far_x)
    ob_list = [FarFields]

    def J(alpha):
        return npa.abs(alpha[0, 0, 0])**2

    opt = mpa.OptimizationProblem(simulation=sim,
                                  objective_functions=J,
                                  objective_arguments=ob_list,
                                  design_regions=[design_region],
                                  fcen=fcen,
                                  df=0,
                                  nf=1,
                                  maximum_run_time=1200)

    f, dJ_du = opt([design_params])
    sim.reset_meep()

    return f, dJ_du
예제 #15
0
sources = [mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Ez, center=src_pt)]

k_point = mp.Vector3()

glass = mp.Medium(index=1.5)

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

nfreq = 21
n2f_pt = mp.Vector3(0.5*sx-dpml-0.5*dpad)
n2f_obj = sim.add_near2far(fcen, df, nfreq, mp.Near2FarRegion(center=n2f_pt))

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

ff_source = sim.get_farfields(n2f_obj, ff_res, center=mp.Vector3(ff_distance,0.5*ff_length), size=mp.Vector3(y=ff_length))

sim.reset_meep()

### unit cell with periodic boundaries

sy = gp
cell_size = mp.Vector3(sx,sy)

sources = [mp.Source(mp.GaussianSource(fcen, fwidth=df), component=mp.Ez, center=src_pt, size=mp.Vector3(y=sy))]

geometry = [mp.Block(material=glass, size=mp.Vector3(dpml+dsub,mp.inf,mp.inf), center=mp.Vector3(-0.5*sx+0.5*(dpml+dsub))),
예제 #16
0
    symmetries = [mp.Mirror(mp.X, phase=+1), mp.Mirror(mp.Y, phase=-1)]
elif src_cmpt == mp.Ez:
    symmetries = [mp.Mirror(mp.X, phase=+1), mp.Mirror(mp.Y, phase=+1)]

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

# The flux is measured in a box of 1 um side around the source but these are used to get the far field
nearfield_box = sim.add_near2far(
    fcen, 0, 1,
    mp.Near2FarRegion(center=mp.Vector3(0, +0.5 * sxy),
                      size=mp.Vector3(sxy, 0),
                      weight=+1),
    mp.Near2FarRegion(center=mp.Vector3(0, -0.5 * sxy),
                      size=mp.Vector3(sxy, 0),
                      weight=-1),
    mp.Near2FarRegion(center=mp.Vector3(+0.5 * sxy, 0),
                      size=mp.Vector3(0, sxy),
                      weight=+1),
    mp.Near2FarRegion(center=mp.Vector3(-0.5 * sxy, 0),
                      size=mp.Vector3(0, sxy),
                      weight=-1))

flux_box = sim.add_flux(
    fcen, 0, 1,
    mp.FluxRegion(center=mp.Vector3(0, +0.5 * sxy),
                  size=mp.Vector3(sxy, 0),
예제 #17
0
                    component=mp.Hz, center=mp.Vector3())

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

d1 = 0.2

sim = mp.Simulation(cell_size=cell,
                    geometry=geometry,
                    sources=[sources],
                    symmetries=symmetries,
                    boundary_layers=[pml_layers],
                    resolution=resolution)

nearfield = sim.add_near2far(
    fcen, 0, 1,
    mp.Near2FarRegion(mp.Vector3(0, 0.5 * w + d1),
                      size=mp.Vector3(2 * dpml - sx)),
    mp.Near2FarRegion(mp.Vector3(-0.5 * sx + dpml, 0.5 * w +
                                 0.5 * d1), size=mp.Vector3(0, d1), weight=-1.0),
    mp.Near2FarRegion(mp.Vector3(0.5 * sx - dpml, 0.5 *
                                 w + 0.5 * d1), size=mp.Vector3(0, d1))
)

sim.run(until_after_sources=mp.stop_when_fields_decayed(
    50, mp.Hz, mp.Vector3(0.12, -0.37), 1e-8))

d2 = 20
h = 4

sim.output_farfields(nearfield, "spectra-{}-{}-{}".format(d1, d2, h), resolution,
                     where=mp.Volume(mp.Vector3(0, (0.5 * w) + d2 + (0.5 * h)),
                                     size=mp.Vector3(sx - 2 * dpml, h)))
예제 #18
0
def main(from_um_factor, resolution, courant, r, material, paper, reference,
         submerged_index, displacement, surface_index, wlen_range, nfreq,
         air_r_factor, pml_wlen_factor, flux_r_factor, time_factor_cell,
         second_time_factor, series, folder, parallel, n_processes, n_cores,
         n_nodes, split_chunks_evenly, load_flux, load_chunks, near2far):

    #%% CLASSIC INPUT PARAMETERS
    """
    # Simulation size
    from_um_factor = 10e-3 # Conversion of 1 μm to my length unit (=10nm/1μm)
    resolution = 2 # >=8 pixels per smallest wavelength, i.e. np.floor(8/wvl_min)
    courant = 0.5
    
    # Nanoparticle specifications: Sphere in Vacuum :)
    r = 51.5  # Radius of sphere in nm
    paper = "R"
    reference = "Meep"
    displacement = 0 # Displacement of the surface from the bottom of the sphere in nm
    submerged_index = 1 # 1.33 for water
    surface_index = 1 # 1.54 for glass
    
    # Frequency and wavelength
    wlen_range = np.array([350,500]) # Wavelength range in nm
    nfreq = 100
    
    # Box dimensions
    pml_wlen_factor = 0.38
    air_r_factor = 0.5
    flux_r_factor = 0 #0.1
    
    # Simulation time
    time_factor_cell = 1.2
    second_time_factor = 10
    
    # Saving directories
    series = "SilverRes4"
    folder = "Test/TestSilver"
    
    # Configuration
    parallel = False
    n_processes = 1
    n_cores = 1
    n_nodes = 1
    split_chunks_evenly = True
    load_flux = False
    load_chunks = True    
    near2far = False
    """

    #%% MORE INPUT PARAMETERS

    # Frequency and wavelength
    cutoff = 3.2  # Gaussian planewave source's parameter of shape
    nazimuthal = 16
    npolar = 20

    ### TREATED INPUT PARAMETERS

    # Nanoparticle specifications: Sphere in Vacuum :)
    r = r / (from_um_factor * 1e3)  # Now in Meep units
    if reference == "Meep":
        medium = vmt.import_medium(material,
                                   from_um_factor=from_um_factor,
                                   paper=paper)
        # Importing material constants dependant on frequency from Meep Library
    elif reference == "RIinfo":
        medium = vmt.MediumFromFile(material,
                                    paper=paper,
                                    reference=reference,
                                    from_um_factor=from_um_factor)
        # Importing material constants dependant on frequency from external file
    else:
        raise ValueError("Reference for medium not recognized. Sorry :/")
    displacement = displacement / (from_um_factor * 1e3)  # Now in Meep units

    # Frequency and wavelength
    wlen_range = np.array(wlen_range)
    wlen_range = wlen_range / (from_um_factor * 1e3)  # Now in Meep units
    freq_range = 1 / wlen_range  # Hz range in Meep units from highest to lowest
    freq_center = np.mean(freq_range)
    freq_width = max(freq_range) - min(freq_range)

    # Space configuration
    pml_width = pml_wlen_factor * max(wlen_range)  # 0.5 * max(wlen_range)
    air_width = air_r_factor * r  # 0.5 * max(wlen_range)
    flux_box_size = 2 * (1 + flux_r_factor) * r

    # Saving directories
    if series is None:
        series = "Test"
    if folder is None:
        folder = "Test"
    params_list = [
        "from_um_factor", "resolution", "courant", "material", "r", "paper",
        "reference", "submerged_index", "displacement", "surface_index",
        "wlen_range", "nfreq", "nazimuthal", "npolar", "cutoff",
        "flux_box_size", "cell_width", "pml_width", "air_width",
        "source_center", "until_after_sources", "time_factor_cell",
        "second_time_factor", "enlapsed", "parallel", "n_processes", "n_cores",
        "n_nodes", "split_chunks_evenly", "near2far", "script", "sysname",
        "path"
    ]

    #%% GENERAL GEOMETRY SETUP

    air_width = air_width - air_width % (1 / resolution)

    pml_width = pml_width - pml_width % (1 / resolution)
    pml_layers = [mp.PML(thickness=pml_width)]

    # symmetries = [mp.Mirror(mp.Y),
    #               mp.Mirror(mp.Z, phase=-1)]
    # Two mirror planes reduce cell size to 1/4
    # Issue related that lead me to comment this lines:
    # https://github.com/NanoComp/meep/issues/1484

    cell_width = 2 * (pml_width + air_width + r)
    cell_width = cell_width - cell_width % (1 / resolution)
    cell_size = mp.Vector3(cell_width, cell_width, cell_width)

    # surface_center = r/4 - displacement/2 + cell_width/4
    # surface_center = surface_center - surface_center%(1/resolution)
    # displacement = r/2 + cell_width/2 - 2*surface_center

    displacement = displacement - displacement % (1 / resolution)

    flux_box_size = flux_box_size - flux_box_size % (1 / resolution)

    source_center = -0.5 * cell_width + pml_width
    sources = [
        mp.Source(mp.GaussianSource(freq_center,
                                    fwidth=freq_width,
                                    is_integrated=True,
                                    cutoff=cutoff),
                  center=mp.Vector3(source_center),
                  size=mp.Vector3(0, cell_width, cell_width),
                  component=mp.Ez)
    ]
    # Ez-polarized planewave pulse
    # (its size parameter fills the entire cell in 2d)
    # >> The planewave source extends into the PML
    # ==> is_integrated=True must be specified

    until_after_sources = time_factor_cell * cell_width * submerged_index
    # Enough time for the pulse to pass through all the cell
    # Originally: Aprox 3 periods of lowest frequency, using T=λ/c=λ in Meep units
    # Now: Aprox 3 periods of highest frequency, using T=λ/c=λ in Meep units

    geometry = [mp.Sphere(material=medium, center=mp.Vector3(), radius=r)]
    # Au sphere with frequency-dependant characteristics imported from Meep.

    if surface_index != 1:
        geometry = [
            mp.Block(material=mp.Medium(index=surface_index),
                     center=mp.Vector3(
                         r / 2 - displacement / 2 + cell_width / 4, 0, 0),
                     size=mp.Vector3(cell_width / 2 - r + displacement,
                                     cell_width, cell_width)), *geometry
        ]
    # A certain material surface underneath it

    home = vs.get_home()
    sysname = vs.get_sys_name()
    path = os.path.join(home, folder, series)
    if not os.path.isdir(path) and vm.parallel_assign(0, n_processes,
                                                      parallel):
        os.makedirs(path)
    file = lambda f: os.path.join(path, f)

    # Computation
    enlapsed = []

    parallel_specs = np.array([n_processes, n_cores, n_nodes], dtype=int)
    max_index = np.argmax(parallel_specs)
    for index, item in enumerate(parallel_specs):
        if item == 0: parallel_specs[index] = 1
    parallel_specs[0:max_index] = np.full(parallel_specs[0:max_index].shape,
                                          max(parallel_specs))
    n_processes, n_cores, n_nodes = parallel_specs
    parallel = max(parallel_specs) > 1
    del parallel_specs, max_index, index, item

    if parallel:
        np_process = mp.count_processors()
    else:
        np_process = 1

    #%% FIRST RUN

    measure_ram()

    params = {}
    for p in params_list:
        params[p] = eval(p)

    stable, max_courant = vm.check_stability(params)
    if stable:
        print("As a whole, the simulation should be stable")
    else:
        print("As a whole, the simulation could not be stable")
        print(f"Recommended maximum courant factor is {max_courant}")

    if load_flux:
        try:
            flux_path = vm.check_midflux(params)[0]
            flux_needed = False
        except:
            flux_needed = True
    else:
        flux_needed = True

    if load_chunks and not split_chunks_evenly:
        try:
            chunks_path = vm.check_chunks(params)[0]
            chunk_layout = os.path.join(chunks_path, "Layout.h5")
            chunks_needed = False
        except:
            chunks_needed = True
            flux_needed = True
    else:
        if not split_chunks_evenly:
            chunks_needed = True
            flux_needed = True
        else:
            chunk_layout = None
            chunks_needed = False

    if chunks_needed:

        sim = mp.Simulation(
            resolution=resolution,
            cell_size=cell_size,
            boundary_layers=pml_layers,
            sources=sources,
            k_point=mp.Vector3(),
            Courant=courant,
            default_material=mp.Medium(index=submerged_index),
            output_single_precision=True,
            split_chunks_evenly=split_chunks_evenly,
            # symmetries=symmetries,
            geometry=geometry)

        sim.init_sim()

        chunks_path = vm.save_chunks(sim, params, path)
        chunk_layout = os.path.join(chunks_path, "Layout.h5")

        del sim

    if flux_needed:

        #% FIRST RUN: SET UP

        measure_ram()

        sim = mp.Simulation(resolution=resolution,
                            cell_size=cell_size,
                            boundary_layers=pml_layers,
                            sources=sources,
                            k_point=mp.Vector3(),
                            Courant=courant,
                            default_material=mp.Medium(index=submerged_index),
                            split_chunks_evenly=split_chunks_evenly,
                            chunk_layout=chunk_layout,
                            output_single_precision=True)  #,
        # symmetries=symmetries)
        # >> k_point zero specifies boundary conditions needed
        # for the source to be infinitely extended

        measure_ram()

        # Scattered power --> Computed by surrounding it with closed DFT flux box
        # (its size and orientation are irrelevant because of Poynting's theorem)
        box_x1 = sim.add_flux(
            freq_center, freq_width, nfreq,
            mp.FluxRegion(center=mp.Vector3(x=-flux_box_size / 2),
                          size=mp.Vector3(0, flux_box_size, flux_box_size)))
        box_x2 = sim.add_flux(
            freq_center, freq_width, nfreq,
            mp.FluxRegion(center=mp.Vector3(x=+flux_box_size / 2),
                          size=mp.Vector3(0, flux_box_size, flux_box_size)))
        box_y1 = sim.add_flux(
            freq_center, freq_width, nfreq,
            mp.FluxRegion(center=mp.Vector3(y=-flux_box_size / 2),
                          size=mp.Vector3(flux_box_size, 0, flux_box_size)))
        box_y2 = sim.add_flux(
            freq_center, freq_width, nfreq,
            mp.FluxRegion(center=mp.Vector3(y=+flux_box_size / 2),
                          size=mp.Vector3(flux_box_size, 0, flux_box_size)))
        box_z1 = sim.add_flux(
            freq_center, freq_width, nfreq,
            mp.FluxRegion(center=mp.Vector3(z=-flux_box_size / 2),
                          size=mp.Vector3(flux_box_size, flux_box_size, 0)))
        box_z2 = sim.add_flux(
            freq_center, freq_width, nfreq,
            mp.FluxRegion(center=mp.Vector3(z=+flux_box_size / 2),
                          size=mp.Vector3(flux_box_size, flux_box_size, 0)))
        # Funny you can encase the sphere (r radius) so closely (2r-sided box)

        measure_ram()

        if near2far:
            near2far_box = sim.add_near2far(
                freq_center, freq_width, nfreq,
                mp.Near2FarRegion(center=mp.Vector3(x=-flux_box_size / 2),
                                  size=mp.Vector3(0, flux_box_size,
                                                  flux_box_size),
                                  weight=-1),
                mp.Near2FarRegion(center=mp.Vector3(x=+flux_box_size / 2),
                                  size=mp.Vector3(0, flux_box_size,
                                                  flux_box_size),
                                  weight=+1),
                mp.Near2FarRegion(center=mp.Vector3(y=-flux_box_size / 2),
                                  size=mp.Vector3(flux_box_size, 0,
                                                  flux_box_size),
                                  weight=-1),
                mp.Near2FarRegion(center=mp.Vector3(y=+flux_box_size / 2),
                                  size=mp.Vector3(flux_box_size, 0,
                                                  flux_box_size),
                                  weight=+1),
                mp.Near2FarRegion(center=mp.Vector3(z=-flux_box_size / 2),
                                  size=mp.Vector3(flux_box_size, flux_box_size,
                                                  0),
                                  weight=-1),
                mp.Near2FarRegion(center=mp.Vector3(z=+flux_box_size / 2),
                                  size=mp.Vector3(flux_box_size, flux_box_size,
                                                  0),
                                  weight=+1))
            measure_ram()
        else:
            near2far_box = None
            # used_ram.append(used_ram[-1])

        #% FIRST RUN: INITIALIZE

        temp = time()
        sim.init_sim()
        enlapsed.append(time() - temp)
        measure_ram()

        step_ram_function = lambda sim: measure_ram()

        #% FIRST RUN: SIMULATION NEEDED TO NORMALIZE

        temp = time()
        sim.run(mp.at_beginning(step_ram_function),
                mp.at_time(int(until_after_sources / 2), step_ram_function),
                mp.at_end(step_ram_function),
                until_after_sources=until_after_sources)
        #     mp.stop_when_fields_decayed(
        # np.mean(wlen_range), # dT = mean period of source
        # mp.Ez, # Component of field to check
        # mp.Vector3(0.5*cell_width - pml_width, 0, 0), # Where to check
        # 1e-3)) # Factor to decay
        enlapsed.append(time() - temp)

        #% SAVE MID DATA

        for p in params_list:
            params[p] = eval(p)

        flux_path = vm.save_midflux(sim, box_x1, box_x2, box_y1, box_y2,
                                    box_z1, box_z2, near2far_box, params, path)

        freqs = np.asarray(mp.get_flux_freqs(box_x1))
        box_x1_flux0 = np.asarray(mp.get_fluxes(box_x1))
        box_x2_flux0 = np.asarray(mp.get_fluxes(box_x2))
        box_y1_flux0 = np.asarray(mp.get_fluxes(box_y1))
        box_y2_flux0 = np.asarray(mp.get_fluxes(box_y2))
        box_z1_flux0 = np.asarray(mp.get_fluxes(box_z1))
        box_z2_flux0 = np.asarray(mp.get_fluxes(box_z2))

        data_mid = np.array([
            1e3 * from_um_factor / freqs, box_x1_flux0, box_x2_flux0,
            box_y1_flux0, box_y2_flux0, box_z1_flux0, box_z2_flux0
        ]).T

        header_mid = [
            "Longitud de onda [nm]", "Flujo X10 [u.a.]", "Flujo X20 [u.a]",
            "Flujo Y10 [u.a]", "Flujo Y20 [u.a]", "Flujo Z10 [u.a]",
            "Flujo Z20 [u.a]"
        ]

        if vm.parallel_assign(0, n_processes, parallel):
            vs.savetxt(file("MidFlux.txt"),
                       data_mid,
                       header=header_mid,
                       footer=params)

        if not split_chunks_evenly:
            vm.save_chunks(sim, params, path)

        if parallel:
            f = h5.File(file("MidRAM.h5"),
                        "w",
                        driver='mpio',
                        comm=MPI.COMM_WORLD)
            current_process = mp.my_rank()
            f.create_dataset("RAM", (len(used_ram), np_process), dtype="float")
            f["RAM"][:, current_process] = used_ram
            for a in params:
                f["RAM"].attrs[a] = params[a]
            f.create_dataset("SWAP", (len(used_ram), np_process), dtype="int")
            f["SWAP"][:, current_process] = swapped_ram
            for a in params:
                f["SWAP"].attrs[a] = params[a]
        else:
            f = h5.File(file("MidRAM.h5"), "w")
            f.create_dataset("RAM", data=used_ram)
            for a in params:
                f["RAM"].attrs[a] = params[a]
            f.create_dataset("SWAP", data=swapped_ram)
            for a in params:
                f["SWAP"].attrs[a] = params[a]
        f.close()
        del f

        #% PLOT FLUX FOURIER MID DATA

        if vm.parallel_assign(1, np_process, parallel):
            ylims = (np.min(data_mid[:, 1:]), np.max(data_mid[:, 1:]))
            ylims = (ylims[0] - .1 * (ylims[1] - ylims[0]),
                     ylims[1] + .1 * (ylims[1] - ylims[0]))

            fig, ax = plt.subplots(3, 2, sharex=True)
            fig.subplots_adjust(hspace=0, wspace=.05)
            for a in ax[:, 1]:
                a.yaxis.tick_right()
                a.yaxis.set_label_position("right")
            for a, h in zip(np.reshape(ax, 6), header_mid[1:]):
                a.set_ylabel(h)

            for d, a in zip(data_mid[:, 1:].T, np.reshape(ax, 6)):
                a.plot(1e3 * from_um_factor / freqs, d)
                a.set_ylim(*ylims)
            ax[-1, 0].set_xlabel("Wavelength [nm]")
            ax[-1, 1].set_xlabel("Wavelength [nm]")

            plt.savefig(file("MidFlux.png"))
            del fig, ax, ylims, a, h

        sim.reset_meep()

    #%% SECOND RUN: SETUP

    measure_ram()

    sim = mp.Simulation(
        resolution=resolution,
        cell_size=cell_size,
        boundary_layers=pml_layers,
        sources=sources,
        k_point=mp.Vector3(),
        Courant=courant,
        default_material=mp.Medium(index=submerged_index),
        output_single_precision=True,
        split_chunks_evenly=split_chunks_evenly,
        chunk_layout=chunk_layout,
        # symmetries=symmetries,
        geometry=geometry)

    measure_ram()

    box_x1 = sim.add_flux(
        freq_center, freq_width, nfreq,
        mp.FluxRegion(center=mp.Vector3(x=-flux_box_size / 2),
                      size=mp.Vector3(0, flux_box_size, flux_box_size)))
    box_x2 = sim.add_flux(
        freq_center, freq_width, nfreq,
        mp.FluxRegion(center=mp.Vector3(x=+flux_box_size / 2),
                      size=mp.Vector3(0, flux_box_size, flux_box_size)))
    box_y1 = sim.add_flux(
        freq_center, freq_width, nfreq,
        mp.FluxRegion(center=mp.Vector3(y=-flux_box_size / 2),
                      size=mp.Vector3(flux_box_size, 0, flux_box_size)))
    box_y2 = sim.add_flux(
        freq_center, freq_width, nfreq,
        mp.FluxRegion(center=mp.Vector3(y=+flux_box_size / 2),
                      size=mp.Vector3(flux_box_size, 0, flux_box_size)))
    box_z1 = sim.add_flux(
        freq_center, freq_width, nfreq,
        mp.FluxRegion(center=mp.Vector3(z=-flux_box_size / 2),
                      size=mp.Vector3(flux_box_size, flux_box_size, 0)))
    box_z2 = sim.add_flux(
        freq_center, freq_width, nfreq,
        mp.FluxRegion(center=mp.Vector3(z=+flux_box_size / 2),
                      size=mp.Vector3(flux_box_size, flux_box_size, 0)))

    measure_ram()

    if near2far:
        near2far_box = sim.add_near2far(
            freq_center, freq_width, nfreq,
            mp.Near2FarRegion(center=mp.Vector3(x=-flux_box_size / 2),
                              size=mp.Vector3(0, flux_box_size, flux_box_size),
                              weight=-1),
            mp.Near2FarRegion(center=mp.Vector3(x=+flux_box_size / 2),
                              size=mp.Vector3(0, flux_box_size, flux_box_size),
                              weight=+1),
            mp.Near2FarRegion(center=mp.Vector3(y=-flux_box_size / 2),
                              size=mp.Vector3(flux_box_size, 0, flux_box_size),
                              weight=-1),
            mp.Near2FarRegion(center=mp.Vector3(y=+flux_box_size / 2),
                              size=mp.Vector3(flux_box_size, 0, flux_box_size),
                              weight=+1),
            mp.Near2FarRegion(center=mp.Vector3(z=-flux_box_size / 2),
                              size=mp.Vector3(flux_box_size, flux_box_size, 0),
                              weight=-1),
            mp.Near2FarRegion(center=mp.Vector3(z=+flux_box_size / 2),
                              size=mp.Vector3(flux_box_size, flux_box_size, 0),
                              weight=+1))
        measure_ram()
    else:
        near2far_box = None
        # used_ram.append(used_ram[-1])

    #%% SECOND RUN: INITIALIZE

    temp = time()
    sim.init_sim()
    enlapsed.append(time() - temp)
    measure_ram()

    #%% LOAD FLUX FROM FILE

    vm.load_midflux(sim, box_x1, box_x2, box_y1, box_y2, box_z1, box_z2,
                    near2far_box, flux_path)

    measure_ram()

    freqs = np.asarray(mp.get_flux_freqs(box_x1))
    box_x1_flux0 = np.asarray(mp.get_fluxes(box_x1))
    box_x1_data = sim.get_flux_data(box_x1)
    box_x2_data = sim.get_flux_data(box_x2)
    box_y1_data = sim.get_flux_data(box_y1)
    box_y2_data = sim.get_flux_data(box_y2)
    box_z1_data = sim.get_flux_data(box_z1)
    box_z2_data = sim.get_flux_data(box_z2)
    if near2far: near2far_data = sim.get_near2far_data(near2far_box)

    temp = time()
    sim.load_minus_flux_data(box_x1, box_x1_data)
    sim.load_minus_flux_data(box_x2, box_x2_data)
    sim.load_minus_flux_data(box_y1, box_y1_data)
    sim.load_minus_flux_data(box_y2, box_y2_data)
    sim.load_minus_flux_data(box_z1, box_z1_data)
    sim.load_minus_flux_data(box_z2, box_z2_data)
    if near2far: sim.load_minus_near2far_data(near2far_box, near2far_data)
    enlapsed.append(time() - temp)
    del box_x1_data, box_x2_data, box_y1_data, box_y2_data
    del box_z1_data, box_z2_data
    if near2far: del near2far_data

    measure_ram()

    #%% SECOND RUN: SIMULATION :D

    step_ram_function = lambda sim: measure_ram()

    temp = time()
    sim.run(mp.at_beginning(step_ram_function),
            mp.at_time(int(second_time_factor * until_after_sources / 2),
                       step_ram_function),
            mp.at_end(step_ram_function),
            until_after_sources=second_time_factor * until_after_sources)
    #     mp.stop_when_fields_decayed(
    # np.mean(wlen_range), # dT = mean period of source
    # mp.Ez, # Component of field to check
    # mp.Vector3(0.5*cell_width - pml_width, 0, 0), # Where to check
    # 1e-3)) # Factor to decay
    enlapsed.append(time() - temp)
    del temp
    # Aprox 30 periods of lowest frequency, using T=λ/c=λ in Meep units

    box_x1_flux = np.asarray(mp.get_fluxes(box_x1))
    box_x2_flux = np.asarray(mp.get_fluxes(box_x2))
    box_y1_flux = np.asarray(mp.get_fluxes(box_y1))
    box_y2_flux = np.asarray(mp.get_fluxes(box_y2))
    box_z1_flux = np.asarray(mp.get_fluxes(box_z1))
    box_z2_flux = np.asarray(mp.get_fluxes(box_z2))

    #%% SCATTERING ANALYSIS

    scatt_flux = box_x1_flux - box_x2_flux
    scatt_flux = scatt_flux + box_y1_flux - box_y2_flux
    scatt_flux = scatt_flux + box_z1_flux - box_z2_flux

    intensity = box_x1_flux0 / (flux_box_size)**2
    # Flux of one of the six monitor planes / Área
    # (the closest one, facing the planewave source)
    # This is why the six sides of the flux box are separated
    # (Otherwise, the box could've been one flux object with weights ±1 per side)

    scatt_cross_section = np.divide(scatt_flux, intensity)
    # Scattering cross section σ =
    # = scattered power in all directions / incident intensity.

    scatt_eff_meep = -1 * scatt_cross_section / (np.pi * r**2)
    # Scattering efficiency =
    # = scattering cross section / cross sectional area of the sphere

    freqs = np.array(freqs)
    scatt_eff_theory = [
        ps.MieQ(np.sqrt(medium.epsilon(f)[0, 0] * medium.mu(f)[0, 0]),
                1e3 * from_um_factor / f,
                2 * r * 1e3 * from_um_factor,
                nMedium=submerged_index,
                asDict=True)['Qsca'] for f in freqs
    ]
    # The simulation results are validated by comparing with
    # analytic theory of PyMieScatt module

    #%% ANGULAR PATTERN ANALYSIS

    if near2far:

        fraunhofer_distance = 8 * (r**2) / min(wlen_range)
        radial_distance = max(10 * fraunhofer_distance, 1.5 * cell_width / 2)
        # radius of far-field circle must be at least Fraunhofer distance

        azimuthal_angle = np.arange(0, 2 + 2 / nazimuthal,
                                    2 / nazimuthal)  # in multiples of pi
        polar_angle = np.arange(0, 1 + 1 / npolar, 1 / npolar)

        poynting_x = []
        poynting_y = []
        poynting_z = []
        poynting_r = []

        for phi in azimuthal_angle:

            poynting_x.append([])
            poynting_y.append([])
            poynting_z.append([])
            poynting_r.append([])

            for theta in polar_angle:

                farfield_dict = sim.get_farfields(
                    near2far_box,
                    1,
                    where=mp.Volume(center=mp.Vector3(
                        radial_distance * np.cos(np.pi * phi) *
                        np.sin(np.pi * theta),
                        radial_distance * np.sin(np.pi * phi) *
                        np.sin(np.pi *
                               theta), radial_distance *
                        np.cos(np.pi * theta))))

                Px = farfield_dict["Ey"] * np.conjugate(farfield_dict["Hz"])
                Px -= farfield_dict["Ez"] * np.conjugate(farfield_dict["Hy"])
                Py = farfield_dict["Ez"] * np.conjugate(farfield_dict["Hx"])
                Py -= farfield_dict["Ex"] * np.conjugate(farfield_dict["Hz"])
                Pz = farfield_dict["Ex"] * np.conjugate(farfield_dict["Hy"])
                Pz -= farfield_dict["Ey"] * np.conjugate(farfield_dict["Hx"])

                Px = np.real(Px)
                Py = np.real(Py)
                Pz = np.real(Pz)

                poynting_x[-1].append(Px)
                poynting_y[-1].append(Py)
                poynting_z[-1].append(Pz)
                poynting_r[-1].append(
                    np.sqrt(np.square(Px) + np.square(Py) + np.square(Pz)))

        poynting_x = np.array(poynting_x)
        poynting_y = np.array(poynting_y)
        poynting_z = np.array(poynting_z)
        poynting_r = np.array(poynting_r)

    #%% SAVE FINAL DATA

    for p in params_list:
        params[p] = eval(p)

    data = np.array(
        [1e3 * from_um_factor / freqs, scatt_eff_meep, scatt_eff_theory]).T

    header = [
        "Longitud de onda [nm]", "Sección eficaz efectiva (Meep) [u.a.]",
        "Sección eficaz efectiva (Theory) [u.a.]"
    ]

    data_base = np.array([
        1e3 * from_um_factor / freqs, box_x1_flux0, box_x1_flux, box_x2_flux,
        box_y1_flux, box_y2_flux, box_z1_flux, box_z2_flux, intensity,
        scatt_flux, scatt_cross_section
    ]).T

    header_base = [
        "Longitud de onda [nm]", "Flujo X10 [u.a.]", "Flujo X1 [u.a]",
        "Flujo X2 [u.a]", "Flujo Y1 [u.a]", "Flujo Y2 [u.a]", "Flujo Z1 [u.a]",
        "Flujo Z2 [u.a]", "Intensidad incidente [u.a.]",
        "Flujo scattereado [u.a.]", "Sección eficaz de scattering [u.a.]"
    ]

    if vm.parallel_assign(0, np_process, parallel):
        vs.savetxt(file("Results.txt"), data, header=header, footer=params)
        vs.savetxt(file("BaseResults.txt"),
                   data_base,
                   header=header_base,
                   footer=params)

    if near2far:

        header_near2far = [
            "Poynting medio Px [u.a.]", "Poynting medio Py [u.a.]",
            "Poynting medio Pz [u.a.]", "Poynting medio Pr [u.a.]"
        ]

        data_near2far = [
            poynting_x.reshape(poynting_x.size),
            poynting_y.reshape(poynting_y.size),
            poynting_z.reshape(poynting_z.size),
            poynting_r.reshape(poynting_r.size)
        ]

        if vm.parallel_assign(1, np_process, parallel):
            vs.savetxt(file("Near2FarResults.txt"),
                       data_near2far,
                       header=header_near2far,
                       footer=params)

    if not split_chunks_evenly:
        vm.save_chunks(sim, params, path)

    if parallel:
        f = h5.File(file("RAM.h5"), "w", driver='mpio', comm=MPI.COMM_WORLD)
        current_process = mp.my_rank()
        f.create_dataset("RAM", (len(used_ram), np_process), dtype="float")
        f["RAM"][:, current_process] = used_ram
        for a in params:
            f["RAM"].attrs[a] = params[a]
        f.create_dataset("SWAP", (len(used_ram), np_process), dtype="int")
        f["SWAP"][:, current_process] = swapped_ram
        for a in params:
            f["SWAP"].attrs[a] = params[a]
    else:
        f = h5.File(file("RAM.h5"), "w")
        f.create_dataset("RAM", data=used_ram)
        for a in params:
            f["RAM"].attrs[a] = params[a]
        f.create_dataset("SWAP", data=swapped_ram)
        for a in params:
            f["SWAP"].attrs[a] = params[a]
    f.close()
    del f

    if flux_needed and vm.parallel_assign(0, np_process, parallel):
        os.remove(file("MidRAM.h5"))

    #%% PLOT ALL TOGETHER

    if vm.parallel_assign(0, np_process, parallel) and surface_index == 1:
        plt.figure()
        plt.plot(1e3 * from_um_factor / freqs,
                 scatt_eff_meep,
                 'bo-',
                 label='Meep')
        plt.plot(1e3 * from_um_factor / freqs,
                 scatt_eff_theory,
                 'ro-',
                 label='Theory')
        plt.xlabel('Wavelength [nm]')
        plt.ylabel('Scattering efficiency [σ/πr$^{2}$]')
        plt.legend()
        plt.title('Scattering of Au Sphere With {:.1f} nm Radius'.format(
            r * from_um_factor * 1e3))
        plt.tight_layout()
        plt.savefig(file("Comparison.png"))

    #%% PLOT SEPARATE

    if vm.parallel_assign(1, np_process, parallel):
        plt.figure()
        plt.plot(1e3 * from_um_factor / freqs,
                 scatt_eff_meep,
                 'bo-',
                 label='Meep')
        plt.xlabel('Wavelength [nm]')
        plt.ylabel('Scattering efficiency [σ/πr$^{2}$]')
        plt.legend()
        plt.title('Scattering of Au Sphere With {:.1f} nm Radius'.format(
            r * from_um_factor * 1e3))
        plt.tight_layout()
        plt.savefig(file("Meep.png"))

    if vm.parallel_assign(0, np_process, parallel) and surface_index == 1:
        plt.figure()
        plt.plot(1e3 * from_um_factor / freqs,
                 scatt_eff_theory,
                 'ro-',
                 label='Theory')
        plt.xlabel('Wavelength [nm]')
        plt.ylabel('Scattering efficiency [σ/πr$^{2}$]')
        plt.legend()
        plt.title('Scattering of Au Sphere With {:.1f} nm Radius'.format(r *
                                                                         10))
        plt.tight_layout()
        plt.savefig(file("Theory.png"))

    #%% PLOT ONE ABOVE THE OTHER

    if vm.parallel_assign(1, np_process, parallel) and surface_index == 1:
        fig, axes = plt.subplots(nrows=2, sharex=True)
        fig.subplots_adjust(hspace=0)
        plt.suptitle('Scattering of Au Sphere With {:.1f} nm Radius'.format(
            r * from_um_factor * 1e3))

        axes[0].plot(1e3 * from_um_factor / freqs,
                     scatt_eff_meep,
                     'bo-',
                     label='Meep')
        axes[0].yaxis.tick_right()
        axes[0].set_ylabel('Scattering efficiency [σ/πr$^{2}$]')
        axes[0].legend()

        axes[1].plot(1e3 * from_um_factor / freqs,
                     scatt_eff_theory,
                     'ro-',
                     label='Theory')
        axes[1].set_xlabel('Wavelength [nm]')
        axes[1].set_ylabel('Scattering efficiency [σ/πr$^{2}$]')
        axes[1].legend()

        plt.savefig(file("SeparatedComparison.png"))

    #%% PLOT FLUX FOURIER FINAL DATA

    if vm.parallel_assign(0, np_process, parallel):

        ylims = (np.min(data_base[:, 2:8]), np.max(data_base[:, 2:8]))
        ylims = (ylims[0] - .1 * (ylims[1] - ylims[0]),
                 ylims[1] + .1 * (ylims[1] - ylims[0]))

        fig, ax = plt.subplots(3, 2, sharex=True)
        fig.subplots_adjust(hspace=0, wspace=.05)
        plt.suptitle('Final flux of Au Sphere With {:.1f} nm Radius'.format(
            r * from_um_factor * 1e3))
        for a in ax[:, 1]:
            a.yaxis.tick_right()
            a.yaxis.set_label_position("right")
        for a, h in zip(np.reshape(ax, 6), header_base[1:7]):
            a.set_ylabel(h)

        for d, a in zip(data_base[:, 3:9].T, np.reshape(ax, 6)):
            a.plot(1e3 * from_um_factor / freqs, d)
            a.set_ylim(*ylims)
        ax[-1, 0].set_xlabel("Wavelength [nm]")
        ax[-1, 1].set_xlabel("Wavelength [nm]")

        plt.savefig(file("FinalFlux.png"))

    #%% PLOT ANGULAR PATTERN IN 3D

    if near2far and vm.parallel_assign(1, np_process, parallel):

        freq_index = np.argmin(np.abs(freqs - freq_center))

        fig = plt.figure()
        plt.suptitle(
            'Angular Pattern of Au Sphere With {:.1f} nm Radius at {:.1f} nm'.
            format(r * from_um_factor * 1e3,
                   from_um_factor * 1e3 / freqs[freq_index]))
        ax = fig.add_subplot(1, 1, 1, projection='3d')
        ax.plot_surface(poynting_x[:, :, freq_index],
                        poynting_y[:, :, freq_index],
                        poynting_z[:, :, freq_index],
                        cmap=plt.get_cmap('jet'),
                        linewidth=1,
                        antialiased=False,
                        alpha=0.5)
        ax.set_xlabel(r"$P_x$")
        ax.set_ylabel(r"$P_y$")
        ax.set_zlabel(r"$P_z$")

        plt.savefig(file("AngularPattern.png"))

    #%% PLOT ANGULAR PATTERN PROFILE FOR DIFFERENT POLAR ANGLES

    if near2far and vm.parallel_assign(0, np_process, parallel):

        freq_index = np.argmin(np.abs(freqs - freq_center))
        index = [
            list(polar_angle).index(alpha) for alpha in [0, .25, .5, .75, 1]
        ]

        plt.figure()
        plt.suptitle(
            'Angular Pattern of Au Sphere With {:.1f} nm Radius at {:.1f} nm'.
            format(r * from_um_factor * 1e3,
                   from_um_factor * 1e3 / freqs[freq_index]))
        ax_plain = plt.axes()
        for i in index:
            ax_plain.plot(poynting_x[:, i, freq_index],
                          poynting_y[:, i, freq_index],
                          ".-",
                          label=rf"$\theta$ = {polar_angle[i]:.2f} $\pi$")
        plt.legend()
        ax_plain.set_xlabel(r"$P_x$")
        ax_plain.set_ylabel(r"$P_y$")
        ax_plain.set_aspect("equal")

        plt.savefig(file("AngularPolar.png"))

    #%% PLOT ANGULAR PATTERN PROFILE FOR DIFFERENT AZIMUTHAL ANGLES

    if near2far and vm.parallel_assign(1, np_process, parallel):

        freq_index = np.argmin(np.abs(freqs - freq_center))
        index = [
            list(azimuthal_angle).index(alpha)
            for alpha in [0, .25, .5, .75, 1, 1.25, 1.5, 1.75, 2]
        ]

        plt.figure()
        plt.suptitle(
            'Angular Pattern of Au Sphere With {:.1f} nm Radius at {:.1f} nm'.
            format(r * from_um_factor * 1e3,
                   from_um_factor * 1e3 / freqs[freq_index]))
        ax_plain = plt.axes()
        for i in index:
            ax_plain.plot(poynting_x[i, :, freq_index],
                          poynting_z[i, :, freq_index],
                          ".-",
                          label=rf"$\phi$ = {azimuthal_angle[i]:.2f} $\pi$")
        plt.legend()
        ax_plain.set_xlabel(r"$P_x$")
        ax_plain.set_ylabel(r"$P_z$")

        plt.savefig(file("AngularAzimuthal.png"))

    if near2far and vm.parallel_assign(0, np_process, parallel):

        freq_index = np.argmin(np.abs(freqs - freq_center))
        index = [
            list(azimuthal_angle).index(alpha)
            for alpha in [0, .25, .5, .75, 1, 1.25, 1.5, 1.75, 2]
        ]

        plt.figure()
        plt.suptitle(
            'Angular Pattern of Au Sphere With {:.1f} nm Radius at {:.1f} nm'.
            format(r * from_um_factor * 1e3,
                   from_um_factor * 1e3 / freqs[freq_index]))
        ax_plain = plt.axes()
        for i in index:
            ax_plain.plot(np.sqrt(
                np.square(poynting_x[i, :, freq_index]) +
                np.square(poynting_y[i, :, freq_index])),
                          poynting_z[i, :, freq_index],
                          ".-",
                          label=rf"$\phi$ = {azimuthal_angle[i]:.2f} $\pi$")
        plt.legend()
        ax_plain.set_xlabel(r"$P_\rho$")
        ax_plain.set_ylabel(r"$P_z$")

        plt.savefig(file("AngularAzimuthalAbs.png"))
예제 #19
0
    def test_farfield(self):
        resolution = 50
        sxy = 4
        dpml = 1
        cell = mp.Vector3(sxy + 2 * dpml, sxy + 2 * dpml)

        pml_layers = mp.PML(dpml)

        fcen = 1.0
        df = 0.4

        sources = mp.Source(src=mp.GaussianSource(fcen, fwidth=df),
                            center=mp.Vector3(),
                            component=mp.Ez)

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

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

        nearfield_box = sim.add_near2far(
            fcen, 0, 1,
            mp.Near2FarRegion(mp.Vector3(y=0.5 * sxy), size=mp.Vector3(sxy)),
            mp.Near2FarRegion(mp.Vector3(y=-0.5 * sxy),
                              size=mp.Vector3(sxy),
                              weight=-1),
            mp.Near2FarRegion(mp.Vector3(0.5 * sxy), size=mp.Vector3(y=sxy)),
            mp.Near2FarRegion(mp.Vector3(-0.5 * sxy),
                              size=mp.Vector3(y=sxy),
                              weight=-1))

        flux_box = 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))

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

        near_flux = mp.get_fluxes(flux_box)[0]

        r = 1000 / fcen  # radius of far field circle
        npts = 100  # number of points in [0,2*pi) range of angles
        E = np.zeros((npts, 3), dtype=np.complex128)
        H = np.zeros((npts, 3), dtype=np.complex128)
        for n in range(npts):
            ff = sim.get_farfield(
                nearfield_box,
                mp.Vector3(r * math.cos(2 * math.pi * n / npts),
                           r * math.sin(2 * math.pi * n / npts)))
            E[n, :] = [np.conj(ff[j]) for j in range(3)]
            H[n, :] = [ff[j + 3] for j in range(3)]

        Px = np.real(E[:, 1] * H[:, 2] - E[:, 2] * H[:, 1])
        Py = np.real(E[:, 2] * H[:, 0] - E[:, 0] * H[:, 2])
        Pr = np.sqrt(np.square(Px) + np.square(Py))
        far_flux_circle = np.sum(Pr) * 2 * np.pi * r / len(Pr)

        rr = 20 / fcen  # length of far field square box
        far_flux_square = (
            nearfield_box.flux(
                mp.Y,
                mp.Volume(center=mp.Vector3(y=0.5 * rr), size=mp.Vector3(rr)),
                resolution)[0] - nearfield_box.flux(
                    mp.Y,
                    mp.Volume(center=mp.Vector3(y=-0.5 * rr),
                              size=mp.Vector3(rr)), resolution)[0] +
            nearfield_box.flux(
                mp.X,
                mp.Volume(center=mp.Vector3(0.5 * rr), size=mp.Vector3(y=rr)),
                resolution)[0] - nearfield_box.flux(
                    mp.X,
                    mp.Volume(center=mp.Vector3(-0.5 * rr),
                              size=mp.Vector3(y=rr)), resolution)[0])

        print("flux:, {:.6f}, {:.6f}, {:.6f}".format(near_flux,
                                                     far_flux_circle,
                                                     far_flux_square))

        self.assertAlmostEqual(near_flux, far_flux_circle, places=2)
        self.assertAlmostEqual(far_flux_circle, far_flux_square, places=2)
        self.assertAlmostEqual(far_flux_square, near_flux, places=2)
예제 #20
0
sim = mp.Simulation(resolution=resolution,
                    cell_size=cell_size,
                    boundary_layers=pml_layers,
                    sources=sources,
                    k_point=mp.Vector3())

box_flux = sim.add_flux(
    frq_cen, 0, 1,
    mp.FluxRegion(center=mp.Vector3(x=-2 * r),
                  size=mp.Vector3(0, 4 * r, 4 * r)))

nearfield_box = sim.add_near2far(
    frq_cen, 0, 1,
    mp.Near2FarRegion(center=mp.Vector3(x=-2 * r),
                      size=mp.Vector3(0, 4 * r, 4 * r),
                      weight=+1),
    mp.Near2FarRegion(center=mp.Vector3(x=+2 * r),
                      size=mp.Vector3(0, 4 * r, 4 * r),
                      weight=-1),
    mp.Near2FarRegion(center=mp.Vector3(y=-2 * r),
                      size=mp.Vector3(4 * r, 0, 4 * r),
                      weight=+1),
    mp.Near2FarRegion(center=mp.Vector3(y=+2 * r),
                      size=mp.Vector3(4 * r, 0, 4 * r),
                      weight=-1),
    mp.Near2FarRegion(center=mp.Vector3(z=-2 * r),
                      size=mp.Vector3(4 * r, 4 * r, 0),
                      weight=+1),
    mp.Near2FarRegion(center=mp.Vector3(z=+2 * r),
                      size=mp.Vector3(4 * r, 4 * r, 0),
예제 #21
0
def diff(ht,wvl_cen):
	import meep as mp
	import numpy as np
	import math
	import random
	
	#450	 1.674	
	#550     1.642
	#650     1.629
	
	if (wvl_cen == 0.45):
		photoresist = mp.Medium(index=1.674)   #波长为450nm时光刻胶的折射率 
	elif (wvl_cen == 0.55):
		photoresist = mp.Medium(index=1.642)   #波长为550nm时光刻胶的折射率 
	else:
		photoresist = mp.Medium(index=1.629)   #波长为650nm时光刻胶的折射率 
	
	
	## at least 8 pixels per smallest wavelength, i.e. np.floor(8/wvl_min)
	resolution = 25.0          

	dpml=1.0                                #PML厚度               
	dpad =2.0                               #透镜与PML间距
	dsub = 2.0                             # substrate thickness
	width = 0.5                            #环的宽度
	r= width*len(ht)                        #透镜的半径  50um
	focal_length = 100.0                      #焦距
	spot_length=100                         #far-field line length
	ff_res = 10.0                           #far-field resoluton
	h = 1.25
	
	NA = math.sin(math.atan(r/focal_length))
	NA = round(NA, 3)
	
	
	pml_layers = [mp.PML(thickness=dpml)]

	sr=r+dpad+dpml
	sz=dpml+dpad+h+dpad+dpml
	#sz=dpml+dsub+h+dpad+dpml
	cell_size =mp.Vector3(sr,0,sz) 

	#glass = mp.Medium(index=1.5)                    # substrate
	#geometry = [mp.Block(material=glass,
	#	             size=mp.Vector3(sr,0,dpml+dsub),
	#	             center=mp.Vector3(0.5*sr,0,-0.5*sz+0.5*(dpml+dsub)))]
	# 
	#for n in range (len(ht)):
	#	geometry.append(mp.Block(material=photoresist,
	#	             size=mp.Vector3(width,0,ht[n]),
	#	             center=mp.Vector3(width*n+0.5*width,0,-0.5*sz+dpml+dsub+0.5*ht[n])))  #透镜的结构
	#geometry = [mp.Block(material=photoresist,
	#     		size=mp.Vector3(width,0,ht[0]),
	#  		 center=mp.Vector3(0.5*width,0,-0.5*sz+dpml+dpad+0.5*ht[0]))]
	#for n in range (1,len(ht)):
	#	geometry.append(mp.Block(material=photoresist,
	#	     size=mp.Vector3(width,0,ht[n]),
	#	     center=mp.Vector3(width*n+0.5*width,0,-0.5*sz+dpml+dpad+0.5*ht[n])))  #透镜的结构
	
	geometry = [mp.Block(material=photoresist,
	     		size=mp.Vector3(sr,0,dpml+dsub),
	 		 center=mp.Vector3(0.5*sr,0,-0.5*sz+0.5*(dpml+dsub)))]
	for n in range (0,len(ht)):
		geometry.append(mp.Block(material=photoresist,
	                                 size=mp.Vector3(width,0,ht[n]),
		                          center=mp.Vector3((width*(n)+0.5*width),0,-0.5*sz+dpml+dsub+0.5*ht[n])))  #透镜的结构
	
	
	#wvl_cen = 0.5
	frq_cen = 1/wvl_cen
	dfrq = 0.2*frq_cen

	sources = [mp.Source(mp.GaussianSource(frq_cen,fwidth=dfrq,is_integrated=True),
		             component=mp.Er,
		             center=mp.Vector3(0.5*(sr),0,-0.5*sz+dpml),     
		             size=mp.Vector3(sr)),
		   mp.Source(mp.GaussianSource(frq_cen,fwidth=dfrq,is_integrated=True),
		             component=mp.Ep,
		             center=mp.Vector3(0.5*(sr),0,-0.5*sz+dpml),
		             size=mp.Vector3(sr),
		             amplitude=-1j)]

	sim = mp.Simulation(cell_size=cell_size,
		            boundary_layers=pml_layers,
		            resolution=resolution,
		            sources=sources,
		            geometry=geometry,
		            dimensions=mp.CYLINDRICAL,         
		            m=-1)

	## near-field monitor
	n2f_obj = sim.add_near2far(frq_cen, 0, 1,
		                   mp.Near2FarRegion(center=mp.Vector3(0.5*(sr-dpml),0,0.5*sz-dpml),size=mp.Vector3(sr-dpml)))
		                  # mp.Near2FarRegion(center=mp.Vector3(sr-dpml,0,0.5*sz-0.5*(dsub+zh+dpad)),size=mp.Vector3(z=dsub+zh+dpad)))
		                   
	sim.run(until_after_sources=100)

	ff_r = sim.get_farfields(n2f_obj, ff_res, center=mp.Vector3(0.5*(sr-dpml),0,-0.5*sz+dpml+dsub+h+focal_length),size=mp.Vector3(sr-dpml))
	E2_r = np.absolute(ff_r['Ex'])**2+np.absolute(ff_r['Ey'])**2+np.absolute(ff_r['Ez'])**2
	
	E_sum = sum(E2_r)
	n = round((1.5*(wvl_cen/(2*NA)))/(r/(len(E2_r)-1)))
	#print ('n = %d' % n)
	E = 0.0
	for i in range (n):
		E += E2_r[i]
	
	return E/E_sum  
예제 #22
0
if src_cmpt == mp.Ex:
    symmetries = [mp.Mirror(mp.Y)]
elif src_cmpt == mp.Ey:
    symmetries = [mp.Mirror(mp.X)]
elif src_cmpt == mp.Ez:
    symmetries = [mp.Mirror(mp.X), mp.Mirror(mp.Y)]

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

nearfield = sim.add_near2far(
    fcen, 0, 1,
    mp.Near2FarRegion(mp.Vector3(0, 0.5 * sxy), size=mp.Vector3(sxy)),
    mp.Near2FarRegion(mp.Vector3(0, -0.5 * sxy),
                      size=mp.Vector3(sxy),
                      weight=-1.0),
    mp.Near2FarRegion(mp.Vector3(0.5 * sxy), size=mp.Vector3(0, sxy)),
    mp.Near2FarRegion(mp.Vector3(-0.5 * sxy),
                      size=mp.Vector3(0, sxy),
                      weight=-1.0))

sim.run(until_after_sources=mp.stop_when_fields_decayed(
    50, src_cmpt, mp.Vector3(), 1e-8))

r = 1000 * (1 / fcen)  # 1000 wavelengths out from the source
npts = 100  # number of points in [0,2*pi) range of angles

for n in range(npts):
예제 #23
0
                    center=mp.Vector3())

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

sim = mp.Simulation(cell_size=cell,
                    geometry=geometry,
                    sources=[sources],
                    symmetries=symmetries,
                    boundary_layers=[pml_layers],
                    resolution=resolution)

d1 = 0.2

nearfield = sim.add_near2far(
    fcen, 0, 1,
    mp.Near2FarRegion(mp.Vector3(y=0.5 * w + d1),
                      size=mp.Vector3(sx - 2 * dpml)),
    mp.Near2FarRegion(mp.Vector3(-0.5 * sx + dpml, 0.5 * w + 0.5 * d1),
                      size=mp.Vector3(y=d1),
                      weight=-1.0),
    mp.Near2FarRegion(mp.Vector3(0.5 * sx - dpml, 0.5 * w + 0.5 * d1),
                      size=mp.Vector3(y=d1)))

sim.run(until_after_sources=mp.stop_when_fields_decayed(
    50, mp.Hz, mp.Vector3(0.12, -0.37), 1e-8))

print(sim.run_index)

# In[2]:

d2 = 20
h = 4
예제 #24
0
def main(from_um_factor, resolution_wlen, courant, submerged_index,
         displacement, surface_index, wlen_center, wlen_width, nfreq,
         air_wlen_factor, pml_wlen_factor, flux_wlen_factor, time_factor_cell,
         second_time_factor, series, folder, parallel, n_processes,
         split_chunks_evenly):

    #%% CLASSIC INPUT PARAMETERS
    """
    # Simulation size
    from_um_factor = 100e-3 # Conversion of 1 μm to my length unit (=100nm/1μm)
    resolution_wlen = 20 # >=8 pixels per smallest wavelength, i.e. np.floor(8/wvl_min)
    courant = 0.5
    
    # Nanoparticle specifications: Sphere in Vacuum :)
    paper = "R"
    reference = "Meep"
    displacement = 0 # Displacement of the surface from the bottom of the sphere in nm
    submerged_index = 1.33 # 1.33 for water
    surface_index = 1.54 # 1.54 for glass
    
    # Frequency and wavelength
    wlen_center = 650 # Main wavelength range in nm
    wlen_width = 200 # Wavelength band in nm
    nfreq = 100
    
    # Box dimensions
    pml_wlen_factor = 0.38
    air_wlen_factor = 0.15
    flux_wlen_factor = 0.1
    
    # Simulation time
    time_factor_cell = 1.2
    second_time_factor = 10
    
    # Saving directories
    series = "1stTest"
    folder = "Test/TestDipole/DipoleGlass"
    
    # Configuration
    parallel = False
    n_processes = 1
    split_chunks_evenly = True
    """

    #%% MORE INPUT PARAMETERS

    # Simulation size
    resolution = (from_um_factor * 1e3) * resolution_wlen / (wlen_center +
                                                             wlen_width / 2)
    resolution = int(np.ceil(resolution / 2)) * 2

    # Frequency and wavelength
    cutoff = 3.2  # Gaussian planewave source's parameter of shape
    nazimuthal = 16
    npolar = 20

    ### TREATED INPUT PARAMETERS

    # Nanoparticle specifications: Sphere in Vacuum :)
    displacement = displacement / (from_um_factor * 1e3)  # Now in Meep units

    # Frequency and wavelength
    wlen_center = wlen_center / (from_um_factor * 1e3)  # Now in Meep units
    wlen_width = wlen_width / (from_um_factor * 1e3)  # Now in Meep units
    freq_center = 1 / wlen_center  # Hz center frequency in Meep units
    freq_width = 1 / wlen_width  # Hz range in Meep units from highest to lowest

    # Space configuration
    pml_width = pml_wlen_factor * (wlen_center + wlen_width / 2
                                   )  # 0.5 * max(wlen_range)
    air_width = air_wlen_factor * (wlen_center + wlen_width / 2)
    flux_box_size = flux_wlen_factor * (wlen_center + wlen_width / 2)

    # Computation
    enlapsed = []
    if parallel:
        np_process = mp.count_processors()
    else:
        np_process = 1

    # Saving directories
    if series is None:
        series = "Test"
    if folder is None:
        folder = "Test"
    params_list = [
        "from_um_factor", "resolution_wlen", "resolution", "courant",
        "submerged_index", "displacement", "surface_index", "wlen_center",
        "wlen_width", "cutoff", "nfreq", "nazimuthal", "npolar",
        "flux_box_size", "cell_width", "pml_width", "air_width",
        "until_after_sources", "time_factor_cell", "second_time_factor",
        "enlapsed", "parallel", "n_processes", "split_chunks_evenly", "script",
        "sysname", "path"
    ]

    #%% GENERAL GEOMETRY SETUP

    air_width = air_width - air_width % (1 / resolution)

    pml_width = pml_width - pml_width % (1 / resolution)
    pml_layers = [mp.PML(thickness=pml_width)]

    # symmetries = [mp.Mirror(mp.Y),
    #               mp.Mirror(mp.Z, phase=-1)]
    # Two mirror planes reduce cell size to 1/4
    # Issue related that lead me to comment this lines:
    # https://github.com/NanoComp/meep/issues/1484

    cell_width = 2 * (pml_width + air_width)
    cell_width = cell_width - cell_width % (1 / resolution)
    cell_size = mp.Vector3(cell_width, cell_width, cell_width)

    # surface_center = r/4 - displacement/2 + cell_width/4
    # surface_center = surface_center - surface_center%(1/resolution)
    # displacement = r/2 + cell_width/2 - 2*surface_center

    displacement = displacement - displacement % (1 / resolution)

    flux_box_size = flux_box_size - flux_box_size % (1 / resolution)

    sources = [
        mp.Source(mp.GaussianSource(freq_center,
                                    fwidth=freq_width,
                                    is_integrated=True,
                                    cutoff=cutoff),
                  center=mp.Vector3(),
                  component=mp.Ez)
    ]
    # Ez-polarized point pulse
    # (its size parameter is null and it is centered at zero)
    # >> The planewave source extends into the PML
    # ==> is_integrated=True must be specified

    until_after_sources = time_factor_cell * cell_width * submerged_index
    # Enough time for the pulse to pass through all the cell
    # Originally: Aprox 3 periods of lowest frequency, using T=λ/c=λ in Meep units
    # Now: Aprox 3 periods of highest frequency, using T=λ/c=λ in Meep units

    # if surface_index != 1:
    #     geometry = [mp.Block(material=mp.Medium(index=surface_index),
    #                          center=mp.Vector3(
    #                              - displacement/2 + cell_width/4,
    #                              0, 0),
    #                          size=mp.Vector3(
    #                              cell_width/2 + displacement,
    #                              cell_width, cell_width))]
    # else:
    #     geometry = []
    # A certain material surface underneath it

    home = vs.get_home()
    sysname = vs.get_sys_name()
    path = os.path.join(home, folder, series)
    if not os.path.isdir(path) and vm.parallel_assign(0, n_processes,
                                                      parallel):
        os.makedirs(path)
    file = lambda f: os.path.join(path, f)

    #%% BASE SIMULATION: SETUP

    measure_ram()

    params = {}
    for p in params_list:
        params[p] = eval(p)

    sim = mp.Simulation(resolution=resolution,
                        cell_size=cell_size,
                        boundary_layers=pml_layers,
                        sources=sources,
                        k_point=mp.Vector3(),
                        Courant=courant,
                        default_material=mp.Medium(index=submerged_index),
                        output_single_precision=True,
                        split_chunks_evenly=split_chunks_evenly)

    measure_ram()

    near2far_box = sim.add_near2far(
        freq_center, freq_width, nfreq,
        mp.Near2FarRegion(center=mp.Vector3(x=-flux_box_size / 2),
                          size=mp.Vector3(0, flux_box_size, flux_box_size),
                          weight=-1),
        mp.Near2FarRegion(center=mp.Vector3(x=+flux_box_size / 2),
                          size=mp.Vector3(0, flux_box_size, flux_box_size),
                          weight=+1),
        mp.Near2FarRegion(center=mp.Vector3(y=-flux_box_size / 2),
                          size=mp.Vector3(flux_box_size, 0, flux_box_size),
                          weight=-1),
        mp.Near2FarRegion(center=mp.Vector3(y=+flux_box_size / 2),
                          size=mp.Vector3(flux_box_size, 0, flux_box_size),
                          weight=+1),
        mp.Near2FarRegion(center=mp.Vector3(z=-flux_box_size / 2),
                          size=mp.Vector3(flux_box_size, flux_box_size, 0),
                          weight=-1),
        mp.Near2FarRegion(center=mp.Vector3(z=+flux_box_size / 2),
                          size=mp.Vector3(flux_box_size, flux_box_size, 0),
                          weight=+1))
    measure_ram()
    # used_ram.append(used_ram[-1])

    #%% BASE SIMULATION: INITIALIZE

    temp = time()
    sim.init_sim()
    enlapsed.append(time() - temp)
    measure_ram()

    #%% BASE SIMULATION: SIMULATION :D

    step_ram_function = lambda sim: measure_ram()

    temp = time()
    sim.run(mp.at_beginning(step_ram_function),
            mp.at_time(int(second_time_factor * until_after_sources / 2),
                       step_ram_function),
            mp.at_end(step_ram_function),
            until_after_sources=second_time_factor * until_after_sources)
    #     mp.stop_when_fields_decayed(
    # np.mean(wlen_range), # dT = mean period of source
    # mp.Ez, # Component of field to check
    # mp.Vector3(0.5*cell_width - pml_width, 0, 0), # Where to check
    # 1e-3)) # Factor to decay
    enlapsed.append(time() - temp)
    del temp
    # Aprox 30 periods of lowest frequency, using T=λ/c=λ in Meep units

    #%% BASE SIMULATION: ANGULAR PATTERN ANALYSIS

    freqs = np.linspace(freq_center - freq_center / 2,
                        freq_center + freq_width / 2, nfreq)
    wlens = 1 / freqs

    # fraunhofer_distance = 8 * (r**2) / min(wlen_range)
    # radial_distance = max( 10 * fraunhofer_distance , 1.5 * cell_width/2 )
    # radius of far-field circle must be at least Fraunhofer distance

    radial_distance = cell_width
    azimuthal_angle = np.arange(0, 2 + 2 / nazimuthal,
                                2 / nazimuthal)  # in multiples of pi
    polar_angle = np.arange(0, 1 + 1 / npolar, 1 / npolar)

    poynting_x = []
    poynting_y = []
    poynting_z = []
    poynting_r = []

    for phi in azimuthal_angle:

        poynting_x.append([])
        poynting_y.append([])
        poynting_z.append([])
        poynting_r.append([])

        for theta in polar_angle:

            farfield_dict = sim.get_farfields(
                near2far_box,
                1,
                where=mp.Volume(center=mp.Vector3(
                    radial_distance * np.cos(np.pi * phi) *
                    np.sin(np.pi * theta),
                    radial_distance * np.sin(np.pi * phi) *
                    np.sin(np.pi *
                           theta), radial_distance * np.cos(np.pi * theta))))

            Px = farfield_dict["Ey"] * np.conjugate(farfield_dict["Hz"])
            Px -= farfield_dict["Ez"] * np.conjugate(farfield_dict["Hy"])
            Py = farfield_dict["Ez"] * np.conjugate(farfield_dict["Hx"])
            Py -= farfield_dict["Ex"] * np.conjugate(farfield_dict["Hz"])
            Pz = farfield_dict["Ex"] * np.conjugate(farfield_dict["Hy"])
            Pz -= farfield_dict["Ey"] * np.conjugate(farfield_dict["Hx"])

            Px = np.real(Px)
            Py = np.real(Py)
            Pz = np.real(Pz)

            poynting_x[-1].append(Px)
            poynting_y[-1].append(Py)
            poynting_z[-1].append(Pz)
            poynting_r[-1].append(
                np.sqrt(np.square(Px) + np.square(Py) + np.square(Pz)))

    del phi, theta, farfield_dict, Px, Py, Pz

    poynting_x = np.array(poynting_x)
    poynting_y = np.array(poynting_y)
    poynting_z = np.array(poynting_z)
    poynting_r = np.array(poynting_r)

    #%% BASE SIMULATION: SAVE DATA

    for p in params_list:
        params[p] = eval(p)

    os.chdir(path)
    sim.save_near2far("BaseNear2Far", near2far_box)
    if vm.parallel_assign(0, np_process, parallel):
        f = h5.File("BaseNear2Far.h5", "r+")
        for key, par in params.items():
            f[list(f.keys())[0]].attrs[key] = par
        f.close()
        del f
    os.chdir(syshome)

    if vm.parallel_assign(1, np_process, parallel):
        f = h5.File(file("BaseResults.h5"), "w")
        f["Px"] = poynting_x
        f["Py"] = poynting_y
        f["Pz"] = poynting_z
        f["Pr"] = poynting_r
        for dset in f.values():
            for key, par in params.items():
                dset.attrs[key] = par
        f.close()
        del f

    # if not split_chunks_evenly:
    #     vm.save_chunks(sim, params, path)

    if parallel:
        f = h5.File(file("BaseRAM.h5"),
                    "w",
                    driver='mpio',
                    comm=MPI.COMM_WORLD)
        current_process = mp.my_rank()
        f.create_dataset("RAM", (len(used_ram), np_process), dtype="float")
        f["RAM"][:, current_process] = used_ram
        for a in params:
            f["RAM"].attrs[a] = params[a]
        f.create_dataset("SWAP", (len(used_ram), np_process), dtype="int")
        f["SWAP"][:, current_process] = swapped_ram
        for a in params:
            f["SWAP"].attrs[a] = params[a]
    else:
        f = h5.File(file("BaseRAM.h5"), "w")
        f.create_dataset("RAM", data=used_ram)
        for a in params:
            f["RAM"].attrs[a] = params[a]
        f.create_dataset("SWAP", data=swapped_ram)
        for a in params:
            f["SWAP"].attrs[a] = params[a]
    f.close()
    del f

    sim.reset_meep()

    #%% FURTHER SIMULATION

    if surface_index != 1:

        #% FURTHER SIMULATION: SETUP

        measure_ram()

        params = {}
        for p in params_list:
            params[p] = eval(p)

        sim = mp.Simulation(resolution=resolution,
                            cell_size=cell_size,
                            boundary_layers=pml_layers,
                            sources=sources,
                            k_point=mp.Vector3(),
                            Courant=courant,
                            default_material=mp.Medium(index=surface_index),
                            output_single_precision=True,
                            split_chunks_evenly=split_chunks_evenly)

        measure_ram()

        near2far_box = sim.add_near2far(
            freq_center, freq_width, nfreq,
            mp.Near2FarRegion(center=mp.Vector3(x=-flux_box_size / 2),
                              size=mp.Vector3(0, flux_box_size, flux_box_size),
                              weight=-1),
            mp.Near2FarRegion(center=mp.Vector3(x=+flux_box_size / 2),
                              size=mp.Vector3(0, flux_box_size, flux_box_size),
                              weight=+1),
            mp.Near2FarRegion(center=mp.Vector3(y=-flux_box_size / 2),
                              size=mp.Vector3(flux_box_size, 0, flux_box_size),
                              weight=-1),
            mp.Near2FarRegion(center=mp.Vector3(y=+flux_box_size / 2),
                              size=mp.Vector3(flux_box_size, 0, flux_box_size),
                              weight=+1),
            mp.Near2FarRegion(center=mp.Vector3(z=-flux_box_size / 2),
                              size=mp.Vector3(flux_box_size, flux_box_size, 0),
                              weight=-1),
            mp.Near2FarRegion(center=mp.Vector3(z=+flux_box_size / 2),
                              size=mp.Vector3(flux_box_size, flux_box_size, 0),
                              weight=+1))
        measure_ram()
        # used_ram.append(used_ram[-1])

        #% FURTHER SIMULATION: INITIALIZE

        temp = time()
        sim.init_sim()
        enlapsed.append(time() - temp)
        measure_ram()

        #% FURTHER SIMULATION: SIMULATION :D

        step_ram_function = lambda sim: measure_ram()

        temp = time()
        sim.run(mp.at_beginning(step_ram_function),
                mp.at_time(int(second_time_factor * until_after_sources / 2),
                           step_ram_function),
                mp.at_end(step_ram_function),
                until_after_sources=second_time_factor * until_after_sources)
        #     mp.stop_when_fields_decayed(
        # np.mean(wlen_range), # dT = mean period of source
        # mp.Ez, # Component of field to check
        # mp.Vector3(0.5*cell_width - pml_width, 0, 0), # Where to check
        # 1e-3)) # Factor to decay
        enlapsed.append(time() - temp)
        del temp
        # Aprox 30 periods of lowest frequency, using T=λ/c=λ in Meep units

        #% FURTHER SIMULATION: ANGULAR PATTERN ANALYSIS

        poynting_x2 = []
        poynting_y2 = []
        poynting_z2 = []
        poynting_r2 = []

        for phi in azimuthal_angle:

            poynting_x2.append([])
            poynting_y2.append([])
            poynting_z2.append([])
            poynting_r2.append([])

            for theta in polar_angle:

                farfield_dict = sim.get_farfields(
                    near2far_box,
                    1,
                    where=mp.Volume(center=mp.Vector3(
                        radial_distance * np.cos(np.pi * phi) *
                        np.sin(np.pi * theta),
                        radial_distance * np.sin(np.pi * phi) *
                        np.sin(np.pi *
                               theta), radial_distance *
                        np.cos(np.pi * theta))))

                Px = farfield_dict["Ey"] * np.conjugate(farfield_dict["Hz"])
                Px -= farfield_dict["Ez"] * np.conjugate(farfield_dict["Hy"])
                Py = farfield_dict["Ez"] * np.conjugate(farfield_dict["Hx"])
                Py -= farfield_dict["Ex"] * np.conjugate(farfield_dict["Hz"])
                Pz = farfield_dict["Ex"] * np.conjugate(farfield_dict["Hy"])
                Pz -= farfield_dict["Ey"] * np.conjugate(farfield_dict["Hx"])

                Px = np.real(Px)
                Py = np.real(Py)
                Pz = np.real(Pz)

                poynting_x2[-1].append(Px)
                poynting_y2[-1].append(Py)
                poynting_z2[-1].append(Pz)
                poynting_r2[-1].append(
                    np.sqrt(np.square(Px) + np.square(Py) + np.square(Pz)))

        del phi, theta, farfield_dict, Px, Py, Pz

        poynting_x2 = np.array(poynting_x2)
        poynting_y2 = np.array(poynting_y2)
        poynting_z2 = np.array(poynting_z2)
        poynting_r2 = np.array(poynting_r2)

        #% FURTHER SIMULATION: SAVE DATA

        for p in params_list:
            params[p] = eval(p)

        os.chdir(path)
        sim.save_near2far("FurtherNear2Far", near2far_box)
        if vm.parallel_assign(0, np_process, parallel):
            f = h5.File("FurtherNear2Far.h5", "r+")
            for key, par in params.items():
                f[list(f.keys())[0]].attrs[key] = par
            f.close()
            del f
        os.chdir(syshome)

        if vm.parallel_assign(1, np_process, parallel):
            f = h5.File(file("FurtherResults.h5"), "w")
            f["Px"] = poynting_x2
            f["Py"] = poynting_y2
            f["Pz"] = poynting_z2
            f["Pr"] = poynting_r2
            for dset in f.values():
                for key, par in params.items():
                    dset.attrs[key] = par
            f.close()
            del f

        # if not split_chunks_evenly:
        #     vm.save_chunks(sim, params, path)

        if parallel:
            f = h5.File(file("FurtherRAM.h5"),
                        "w",
                        driver='mpio',
                        comm=MPI.COMM_WORLD)
            current_process = mp.my_rank()
            f.create_dataset("RAM", (len(used_ram), np_process), dtype="float")
            f["RAM"][:, current_process] = used_ram
            for a in params:
                f["RAM"].attrs[a] = params[a]
            f.create_dataset("SWAP", (len(used_ram), np_process), dtype="int")
            f["SWAP"][:, current_process] = swapped_ram
            for a in params:
                f["SWAP"].attrs[a] = params[a]
        else:
            f = h5.File(file("FurtherRAM.h5"), "w")
            f.create_dataset("RAM", data=used_ram)
            for a in params:
                f["RAM"].attrs[a] = params[a]
            f.create_dataset("SWAP", data=swapped_ram)
            for a in params:
                f["SWAP"].attrs[a] = params[a]
        f.close()
        del f

    #%% NORMALIZE AND REARANGE DATA

    if surface_index != 1:
        max_poynting_r = np.max(
            [np.max(np.abs(poynting_r)),
             np.max(np.abs(poynting_r2))])
    else:
        max_poynting_r = np.max(np.abs(poynting_r))

    poynting_x = np.array(poynting_x) / max_poynting_r
    poynting_y = np.array(poynting_y) / max_poynting_r
    poynting_z = np.array(poynting_z) / max_poynting_r
    poynting_r = np.array(poynting_r) / max_poynting_r

    if surface_index != 1:

        poynting_x0 = np.array(poynting_x)
        poynting_y0 = np.array(poynting_y)
        poynting_z0 = np.array(poynting_z)
        poynting_r0 = np.array(poynting_r)

        poynting_x2 = np.array(poynting_x2) / max_poynting_r
        poynting_y2 = np.array(poynting_y2) / max_poynting_r
        poynting_z2 = np.array(poynting_z2) / max_poynting_r
        poynting_r2 = np.array(poynting_r2) / max_poynting_r

    #%%
    """
    poynting_x = np.array(poynting_x0)
    poynting_y = np.array(poynting_y0)
    poynting_z = np.array(poynting_z0)
    poynting_r = np.array(poynting_r0)
    """

    if surface_index != 1:

        polar_limit = np.arcsin(displacement / radial_distance) + .5

        for i in range(len(polar_angle)):
            if polar_angle[i] > polar_limit:
                index_limit = i
                break

        poynting_x[:, index_limit:, :] = poynting_x2[:, index_limit:, :]
        poynting_y[:, index_limit:, :] = poynting_y2[:, index_limit:, :]
        poynting_z[:, index_limit:, :] = poynting_z2[:, index_limit:, :]
        poynting_r[:, index_limit:, :] = poynting_r2[:, index_limit:, :]

        poynting_x[:, index_limit - 1, :] = np.array([[
            np.mean([p2, p0]) for p2, p0 in zip(poy2, poy0)
        ] for poy2, poy0 in zip(poynting_x2[:, index_limit -
                                            1, :], poynting_x0[:, index_limit -
                                                               1, :])])
        poynting_y[:, index_limit - 1, :] = np.array([[
            np.mean([p2, p0]) for p2, p0 in zip(poy2, poy0)
        ] for poy2, poy0 in zip(poynting_y2[:, index_limit -
                                            1, :], poynting_y0[:, index_limit -
                                                               1, :])])
        poynting_z[:, index_limit - 1, :] = np.array([[
            np.mean([p2, p0]) for p2, p0 in zip(poy2, poy0)
        ] for poy2, poy0 in zip(poynting_z2[:, index_limit -
                                            1, :], poynting_z0[:, index_limit -
                                                               1, :])])
        poynting_r[:, index_limit - 1, :] = np.sqrt(
            np.squared(poynting_x[:, index_limit - 1, :]) +
            np.squared(poynting_y[:, index_limit - 1, :]) +
            np.squared(poynting_y[:, index_limit - 1, :]))

    #%% SAVE FINAL DATA

    if surface_index != 1 and vm.parallel_assign(0, np_process, parallel):

        os.remove(file("BaseRAM.h5"))
        os.rename(file("FurtherRAM.h5"), file("RAM.h5"))

    elif vm.parallel_assign(0, np_process, parallel):

        os.rename(file("BaseRAM.h5"), file("RAM.h5"))

    #%% PLOT ANGULAR PATTERN IN 3D

    if vm.parallel_assign(1, np_process, parallel):

        freq_index = np.argmin(np.abs(freqs - freq_center))

        fig = plt.figure()
        plt.suptitle(
            f'Angular Pattern of point dipole molecule at {from_um_factor * 1e3 * wlen_center:.0f} nm'
        )
        ax = fig.add_subplot(1, 1, 1, projection='3d')
        ax.plot_surface(poynting_x[:, :, freq_index],
                        poynting_y[:, :, freq_index],
                        poynting_z[:, :, freq_index],
                        cmap=plt.get_cmap('jet'),
                        linewidth=1,
                        antialiased=False,
                        alpha=0.5)
        ax.set_xlabel(r"$P_x$")
        ax.set_ylabel(r"$P_y$")
        ax.set_zlabel(r"$P_z$")

        plt.savefig(file("AngularPattern.png"))

    #%% PLOT ANGULAR PATTERN PROFILE FOR DIFFERENT POLAR ANGLES

    if vm.parallel_assign(0, np_process, parallel):

        freq_index = np.argmin(np.abs(freqs - freq_center))
        index = [
            list(polar_angle).index(alpha) for alpha in [0, .25, .5, .75, 1]
        ]

        plt.figure()
        plt.suptitle(
            f'Angular Pattern of point dipole molecule at {from_um_factor * 1e3 * wlen_center:.0f} nm'
        )
        ax_plain = plt.axes()
        for i in index:
            ax_plain.plot(poynting_x[:, i, freq_index],
                          poynting_y[:, i, freq_index],
                          ".-",
                          label=rf"$\theta$ = {polar_angle[i]:.2f} $\pi$")
        plt.legend()
        ax_plain.set_xlabel(r"$P_x$")
        ax_plain.set_ylabel(r"$P_y$")
        ax_plain.set_aspect("equal")

        plt.savefig(file("AngularPolar.png"))

    #%% PLOT ANGULAR PATTERN PROFILE FOR DIFFERENT AZIMUTHAL ANGLES

    if vm.parallel_assign(1, np_process, parallel):

        freq_index = np.argmin(np.abs(freqs - freq_center))
        index = [
            list(azimuthal_angle).index(alpha)
            for alpha in [0, .25, .5, .75, 1, 1.25, 1.5, 1.75, 2]
        ]

        plt.figure()
        plt.suptitle(
            f'Angular Pattern of point dipole molecule at {from_um_factor * 1e3 * wlen_center:.0f} nm'
        )
        ax_plain = plt.axes()
        for i in index:
            ax_plain.plot(poynting_x[i, :, freq_index],
                          poynting_z[i, :, freq_index],
                          ".-",
                          label=rf"$\phi$ = {azimuthal_angle[i]:.2f} $\pi$")
        plt.legend()
        ax_plain.set_xlabel(r"$P_x$")
        ax_plain.set_ylabel(r"$P_z$")

        plt.savefig(file("AngularAzimuthal.png"))

    if vm.parallel_assign(0, np_process, parallel):

        freq_index = np.argmin(np.abs(freqs - freq_center))
        index = [
            list(azimuthal_angle).index(alpha)
            for alpha in [0, .25, .5, .75, 1, 1.25, 1.5, 1.75, 2]
        ]

        plt.figure()
        plt.suptitle(
            f'Angular Pattern of point dipole molecule at {from_um_factor * 1e3 * wlen_center:.0f} nm'
        )
        ax_plain = plt.axes()
        for i in index:
            ax_plain.plot(np.sqrt(
                np.square(poynting_x[i, :, freq_index]) +
                np.square(poynting_y[i, :, freq_index])),
                          poynting_z[i, :, freq_index],
                          ".-",
                          label=rf"$\phi$ = {azimuthal_angle[i]:.2f} $\pi$")
        plt.legend()
        ax_plain.set_xlabel(r"$P_\rho$")
        ax_plain.set_ylabel(r"$P_z$")

        plt.savefig(file("AngularAzimuthalAbs.png"))
예제 #25
0
    else:
        os.system("convert " + outputdir + "/grating_validation-ez-*.png " +
                  outputdir + "/N=" + str(num_notches) +
                  "-NearfieldTransient.gif")

    os.system("rm " + outputdir + "/grating_validation-ez-*.png")

    # Delete after printing output
    refl1 = sim.add_flux(fcen, df, nfreq, refl_fr1)
    refl2 = sim.add_flux(fcen, df, nfreq, refl_fr2)
    tran = sim.add_flux(fcen, df, nfreq, tran_fr)
    su = sim.add_flux(fcen, df, nfreq, su_fr)
    sd = sim.add_flux(fcen, df, nfreq, sd_fr)

    nearfield = sim.add_near2far(fcen, 0, 1,
                                 mp.Near2FarRegion(mp.Vector3(0, 0.5 * sxy),
                                                   size=mp.Vector3(sxy)))  #

    old_refl1_flux = mp.get_fluxes(refl1)
    old_refl2_flux = mp.get_fluxes(refl2)
    old_tran_flux = mp.get_fluxes(tran)
    old_su_flux = mp.get_fluxes(su)
    old_sd_flux = mp.get_fluxes(sd)

    # Simulation run for STEADY state
    sim.run(mp.at_every(
        1,
        mp.output_png(
            mp.Ez, "-RZc bluered -A " + outputdir + "/grating_validation-" +
            epsform + ".h5 -a gray:.2")),
            until=19 * wavelength / 20)
    sim.run(until=19 * wavelength)
예제 #26
0
def pec_ground_plane_radiation(src_cmpt=mp.Hz):
    L = 8.0  # length of non-PML region
    dpml = 1.0  # thickness of PML
    sxy = dpml + L + dpml
    cell_size = mp.Vector3(sxy, sxy, 0)
    boundary_layers = [mp.PML(dpml)]

    fcen = 1 / wvl

    # The near-to-far field transformation feature only supports
    # homogeneous media which means it cannot explicitly take into
    # account the ground plane. As a workaround, we use two antennas
    # of opposite sign surrounded by a single near2far box which
    # encloses both antennas. We then use an odd mirror symmetry to
    # divide the computational cell in half which is effectively
    # equivalent to a PEC boundary condition on one side.
    # Note: This setup means that the radiation pattern can only
    # be measured in the top half above the dipole.
    sources = [
        mp.Source(src=mp.GaussianSource(fcen, fwidth=0.2 * fcen),
                  component=src_cmpt,
                  center=mp.Vector3(0, +h)),
        mp.Source(src=mp.GaussianSource(fcen, fwidth=0.2 * fcen),
                  component=src_cmpt,
                  center=mp.Vector3(0, -h),
                  amplitude=-1 if src_cmpt == mp.Ez else +1)
    ]

    symmetries = [
        mp.Mirror(direction=mp.X, phase=+1 if src_cmpt == mp.Ez else -1),
        mp.Mirror(direction=mp.Y, phase=-1 if src_cmpt == mp.Ez else +1)
    ]

    sim = mp.Simulation(resolution=resolution,
                        cell_size=cell_size,
                        boundary_layers=boundary_layers,
                        sources=sources,
                        symmetries=symmetries,
                        default_material=mp.Medium(index=n))

    nearfield_box = sim.add_near2far(
        fcen, 0, 1,
        mp.Near2FarRegion(center=mp.Vector3(0, 2 * h),
                          size=mp.Vector3(2 * h, 0),
                          weight=+1),
        mp.Near2FarRegion(center=mp.Vector3(0, -2 * h),
                          size=mp.Vector3(2 * h, 0),
                          weight=-1),
        mp.Near2FarRegion(center=mp.Vector3(h, 0),
                          size=mp.Vector3(0, 4 * h),
                          weight=+1),
        mp.Near2FarRegion(center=mp.Vector3(-h, 0),
                          size=mp.Vector3(0, 4 * h),
                          weight=-1))

    sim.plot2D()
    plt.savefig('antenna_pec_ground_plane.png', bbox_inches='tight')

    sim.run(until_after_sources=mp.stop_when_dft_decayed())

    Pr = radial_flux(sim, nearfield_box, r)

    return Pr
예제 #27
0
def grating(gp, gh, gdc_list):
    sx = dpml + dsub + gh + dpad + dpml
    src_pt = mp.Vector3(-0.5 * sx + dpml + 0.5 * dsub)
    mon_pt = mp.Vector3(0.5 * sx - dpml - 0.5 * dpad)
    geometry = [
        mp.Block(material=glass,
                 size=mp.Vector3(dpml + dsub, mp.inf, mp.inf),
                 center=mp.Vector3(-0.5 * sx + 0.5 * (dpml + dsub)))
    ]

    num_cells = len(gdc_list)
    if num_cells == 1:
        sy = gp
        cell_size = mp.Vector3(sx, sy, 0)

        sources = [
            mp.Source(mp.GaussianSource(fcen, fwidth=df),
                      component=mp.Ez,
                      center=src_pt,
                      size=mp.Vector3(y=sy))
        ]

        sim = mp.Simulation(resolution=resolution,
                            cell_size=cell_size,
                            boundary_layers=pml_layers,
                            k_point=k_point,
                            default_material=glass,
                            sources=sources,
                            symmetries=symmetries)

        flux_obj = sim.add_flux(
            fcen, 0, 1, mp.FluxRegion(center=mon_pt, size=mp.Vector3(y=sy)))

        sim.run(until_after_sources=50)

        input_flux = mp.get_fluxes(flux_obj)

        sim.reset_meep()

        geometry.append(
            mp.Block(material=glass,
                     size=mp.Vector3(gh, gdc_list[0] * gp, mp.inf),
                     center=mp.Vector3(-0.5 * sx + dpml + dsub + 0.5 * gh)))

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

        flux_obj = sim.add_flux(
            fcen, 0, 1, mp.FluxRegion(center=mon_pt, size=mp.Vector3(y=sy)))

        sim.run(until_after_sources=200)

        freqs = mp.get_eigenmode_freqs(flux_obj)
        res = sim.get_eigenmode_coefficients(flux_obj, [1],
                                             eig_parity=mp.ODD_Z + mp.EVEN_Y)
        coeffs = res.alpha

        mode_tran = abs(coeffs[0, 0, 0])**2 / input_flux[0]
        mode_phase = np.angle(coeffs[0, 0, 0])
        if mode_phase > 0:
            mode_phase -= 2 * np.pi

        return mode_tran, mode_phase

    else:
        sy = num_cells * gp
        cell_size = mp.Vector3(sx, sy, 0)

        sources = [
            mp.Source(mp.GaussianSource(fcen, fwidth=df),
                      component=mp.Ez,
                      center=src_pt,
                      size=mp.Vector3(y=sy))
        ]

        for j in range(num_cells):
            geometry.append(
                mp.Block(material=glass,
                         size=mp.Vector3(gh, gdc_list[j] * gp, mp.inf),
                         center=mp.Vector3(-0.5 * sx + dpml + dsub + 0.5 * gh,
                                           -0.5 * sy + (j + 0.5) * gp)))

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

        n2f_obj = sim.add_near2far(
            fcen, 0, 1, mp.Near2FarRegion(center=mon_pt,
                                          size=mp.Vector3(y=sy)))

        sim.run(until_after_sources=500)

        return abs(
            sim.get_farfields(n2f_obj,
                              ff_res,
                              center=mp.Vector3(-0.5 * sx + dpml + dsub + gh +
                                                focal_length),
                              size=mp.Vector3(spot_length))['Ez'])**2
예제 #28
0
                 size=mp.Vector3(r[n], 0, zh),
                 center=mp.Vector3(0.5 * r[n], 0,
                                   -0.5 * sz + dpml + dsub + 0.5 * zh)))

sim = mp.Simulation(cell_size=cell_size,
                    boundary_layers=pml_layers,
                    resolution=resolution,
                    sources=sources,
                    geometry=geometry,
                    dimensions=mp.CYLINDRICAL,
                    m=-1)

## near-field monitor
n2f_obj = sim.add_near2far(
    frq_cen, 0, 1,
    mp.Near2FarRegion(center=mp.Vector3(0.5 * (sr - dpml), 0, 0.5 * sz - dpml),
                      size=mp.Vector3(sr - dpml)),
    mp.Near2FarRegion(center=mp.Vector3(sr - dpml, 0,
                                        0.5 * sz - 0.5 * (dsub + zh + dpad)),
                      size=mp.Vector3(z=dsub + zh + dpad)))

f = plt.figure(dpi=150)
sim.plot2D()
# plt.show()
plt.savefig('2Dstructure.png')

sim.run(until_after_sources=100)

ff_r = sim.get_farfields(n2f_obj,
                         ff_res,
                         center=mp.Vector3(
                             0.5 * (sr - dpml), 0,
예제 #29
0
    def run_test(self, nfreqs):
        eps = 13
        w = 1.2
        r = 0.36
        d = 1.4
        N = 3
        sy = 6
        pad = 2
        dpml = 1
        sx = 2 * (pad + dpml + N) + d - 1

        cell = mp.Vector3(sx, sy, 0)

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

        for i in range(N):
            geometry.append(mp.Cylinder(r, center=mp.Vector3(d / 2 + i)))
            geometry.append(mp.Cylinder(r, center=mp.Vector3(d / -2 - i)))

        pml_layers = mp.PML(dpml)
        resolution = 10

        fcen = 0.25
        df = 0.2

        sources = mp.Source(src=mp.GaussianSource(fcen, fwidth=df), component=mp.Hz, center=mp.Vector3())

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

        d1 = 0.2

        sim = mp.Simulation(cell_size=cell,
                            geometry=geometry,
                            sources=[sources],
                            symmetries=symmetries,
                            boundary_layers=[pml_layers],
                            resolution=resolution)

        nearfield = sim.add_near2far(
            fcen, 0.1, nfreqs,
            mp.Near2FarRegion(mp.Vector3(0, 0.5 * w + d1), size=mp.Vector3(2 * dpml - sx)),
            mp.Near2FarRegion(mp.Vector3(-0.5 * sx + dpml, 0.5 * w + 0.5 * d1), size=mp.Vector3(0, d1), weight=-1.0),
            mp.Near2FarRegion(mp.Vector3(0.5 * sx - dpml, 0.5 * w + 0.5 * d1), size=mp.Vector3(0, d1))
        )
        sim.run(until=200)
        d2 = 20
        h = 4
        vol = mp.Volume(mp.Vector3(0, (0.5 * w) + d2 + (0.5 * h)), size=mp.Vector3(sx - 2 * dpml, h))
        result = sim.get_farfields(nearfield, resolution, where=vol)
        fname = 'cavity-farfield.h5' if nfreqs == 1 else 'cavity-farfield-4-freqs.h5'
        ref_file = os.path.join(self.data_dir, fname)

        with h5py.File(ref_file, 'r') as f:
            # Get reference data into memory
            ref_ex = mp.complexarray(f['ex.r'][()], f['ex.i'][()])
            ref_ey = mp.complexarray(f['ey.r'][()], f['ey.i'][()])
            ref_ez = mp.complexarray(f['ez.r'][()], f['ez.i'][()])
            ref_hx = mp.complexarray(f['hx.r'][()], f['hx.i'][()])
            ref_hy = mp.complexarray(f['hy.r'][()], f['hy.i'][()])
            ref_hz = mp.complexarray(f['hz.r'][()], f['hz.i'][()])

            np.testing.assert_allclose(ref_ex, result['Ex'])
            np.testing.assert_allclose(ref_ey, result['Ey'])
            np.testing.assert_allclose(ref_ez, result['Ez'])
            np.testing.assert_allclose(ref_hx, result['Hx'])
            np.testing.assert_allclose(ref_hy, result['Hy'])
            np.testing.assert_allclose(ref_hz, result['Hz'])
예제 #30
0
def run():
    #G1 params in 10^-10m
    gp = 1000.  # grating period
    gh = 1027.1  # grating height
    lw = 540.4  #line width
    tr = 162.7  #top radius
    br = 157.9  #bottom radius
    sa = 90.91  #sidewall angle (deg)
    #G2 params in 10^-10m
    gp = 1500.  # grating period
    gh = 1195.0  # grating height
    lw = 673.0  #line width
    tr = 91.6  #top radius
    br = 130.2  #bottom radius
    sa = 84.73  #sidewall angle (deg)

    #params for spacing above and below grating
    dsub = 300
    dpad = 300
    dpml = 50
    resolution = 4.5 / 20
    S = 0.49  #courant parameter
    alpha = 0.86 * np.pi / 180  #from Fig. 4, in radians
    k_point = mp.Vector3(0, 0, 0)

    sx = 2 * gp  #simulation width
    sy = dsub + gh + dpad  #simulation height
    cell = mp.Vector3(sx, sy + 2 * dpml)

    #only absorb in Y direction so that we can have periodic boundaries in X
    pml_layers = [mp.PML(thickness=dpml, direction=mp.Y)]

    #params for light
    e = 0
    Energies = [5.5, 5.55, 5.6]
    wavelengths = [2.25, 2.23, 2.21]
    #corresponding params for Si at these energies
    delta = [1.1676e-5, 1.6068e-5, 1.5779e-5]
    beta = [3.9765e-7, 7.3314e-7, 7.082e-7]
    E = Energies[e]
    wvl = wavelengths[e]
    f = 1 / wvl

    src = build_src(sx=sx, sy=sy, f=f * np.sin(alpha),
                    alpha=alpha)  #use frequency in 2d slice of infinite plane
    mat = build_mat(delta=delta[e], beta=beta[e],
                    f=f)  #use base frequency to get material params right
    geom = build_geom(sx=sx,
                      sy=sy,
                      dsub=dsub,
                      gp=gp,
                      gh=gh,
                      lw=lw,
                      tr=tr,
                      br=br,
                      sa=sa,
                      material=mat)

    #first run empty sim for the background
    sim = mp.Simulation(cell_size=cell,
                        resolution=resolution,
                        Courant=S,
                        k_point=k_point,
                        boundary_layers=pml_layers,
                        geometry=[],
                        sources=src,
                        force_complex_fields=True,
                        eps_averaging=True)

    #nearfield needs to be specified in a region of homogenous space
    nearfield = sim.add_near2far(
        f, 0, 1,
        mp.Near2FarRegion(mp.Vector3(y=-sy / 2),
                          size=mp.Vector3(sx),
                          weight=-1,
                          direction=mp.Y),
        mp.Near2FarRegion(mp.Vector3(-sx / 2, -dsub),
                          size=mp.Vector3(y=sy - dsub),
                          weight=-1,
                          direction=mp.X),
        mp.Near2FarRegion(mp.Vector3(sx / 2, -dsub),
                          size=mp.Vector3(y=sy - dsub),
                          weight=1,
                          direction=mp.X))

    #run til things settle
    sim.run(until=5000)

    _eps, _I = localfield(sim=sim, sx=sx, sy=sy)

    _inten = _I / np.amax(_I)
    plt.imshow(_eps.transpose(), cmap='binary')
    plt.imshow(_inten.transpose(), cmap='gist_heat', alpha=0.9)
    plt.colorbar()
    plt.show()

    #calculate far field approximation through meep
    d = 1.7e10  #min detector distance in paper
    steps = 50
    neighbors = 4
    _q, _farI = farfield(sim=sim,
                         nearfield=nearfield,
                         sx=sx,
                         alpha=alpha,
                         wavelength=wvl,
                         d=d,
                         steps=steps,
                         neighbors=neighbors)

    #plot far field (compare to Fig. 6)
    plt.plot(_q, _farI / np.amax(_farI))
    plt.title('Far Field of E = ' + str(E) + 'keV')
    plt.xlabel('$\\Delta q_x (nm^{-1})$')
    plt.ylabel('Relative Intensity')
    plt.axis('on')
    plt.xlim(-0.4, 0.4)
    plt.show()

    #now run the same simulation with the gratings
    sim.reset_meep()

    sim = mp.Simulation(cell_size=cell,
                        resolution=resolution,
                        Courant=S,
                        k_point=k_point,
                        boundary_layers=pml_layers,
                        geometry=geom,
                        sources=src,
                        force_complex_fields=True,
                        eps_averaging=True)

    #nearfield needs to be specified in a region of homogenous space
    nearfield = sim.add_near2far(
        f, 0, 1,
        mp.Near2FarRegion(mp.Vector3(y=-sy / 2),
                          size=mp.Vector3(sx),
                          weight=-1,
                          direction=mp.Y),
        mp.Near2FarRegion(mp.Vector3(-sx / 2, -dsub),
                          size=mp.Vector3(y=sy - dsub),
                          weight=-1,
                          direction=mp.X),
        mp.Near2FarRegion(mp.Vector3(sx / 2, -dsub),
                          size=mp.Vector3(y=sy - dsub),
                          weight=1,
                          direction=mp.X))

    #run til things settle
    sim.run(until=5000)

    #calculate near field
    eps, I = localfield(sim=sim, sx=sx, sy=sy)

    #plot near field (compare to Fig. 4)
    inten = I / np.amax(I)
    plt.imshow(eps.transpose(), cmap='binary')
    plt.imshow(inten.transpose(), cmap='gist_heat', alpha=0.9)
    plt.colorbar()
    plt.show()

    #calculate far field approximation through meep
    d = 1.7e10  #min detector distance in paper
    steps = 50
    neighbors = 4
    q, farI = farfield(sim=sim,
                       nearfield=nearfield,
                       sx=sx,
                       alpha=alpha,
                       wavelength=wvl,
                       d=d,
                       steps=steps,
                       neighbors=neighbors)

    #plot far field (compare to Fig. 6)
    plt.plot(q, farI / np.amax(farI))
    plt.title('Far Field of E = ' + str(E) + 'keV')
    plt.xlabel('$\\Delta q_x (nm^{-1})$')
    plt.ylabel('Relative Intensity')
    plt.axis('on')
    plt.xlim(-0.4, 0.4)
    plt.show()

    plt.plot(q, (farI - _farI) / np.amax(farI - _farI))
    plt.title('Far Field of E = ' + str(E) + 'keV')
    plt.xlabel('$\\Delta q_x (nm^{-1})$')
    plt.ylabel('Relative Intensity')
    plt.axis('on')
    plt.xlim(-0.4, 0.4)
    plt.show()