예제 #1
0
    def run_mode_coeffs(self, mode_num, kpoint_func):

        resolution = 15

        w = 1  # width of waveguide
        L = 10  # length of waveguide

        Si = mp.Medium(epsilon=12.0)

        dair = 3.0
        dpml = 3.0

        sx = dpml + L + dpml
        sy = dpml + dair + w + dair + dpml
        cell_size = mp.Vector3(sx, sy, 0)

        prism_x = sx + 1
        prism_y = w / 2
        vertices = [
            mp.Vector3(-prism_x, prism_y),
            mp.Vector3(prism_x, prism_y),
            mp.Vector3(prism_x, -prism_y),
            mp.Vector3(-prism_x, -prism_y)
        ]

        geometry = [mp.Prism(vertices, height=mp.inf, material=Si)]

        boundary_layers = [mp.PML(dpml)]

        # mode frequency
        fcen = 0.20  # > 0.5/sqrt(11) to have at least 2 modes

        sources = [
            mp.EigenModeSource(src=mp.GaussianSource(fcen, fwidth=0.5 * fcen),
                               eig_band=mode_num,
                               size=mp.Vector3(0, sy - 2 * dpml, 0),
                               center=mp.Vector3(-0.5 * sx + dpml, 0, 0),
                               eig_match_freq=True,
                               eig_resolution=32)
        ]

        sim = mp.Simulation(
            resolution=resolution,
            cell_size=cell_size,
            boundary_layers=boundary_layers,
            geometry=geometry,
            sources=sources,
            symmetries=[mp.Mirror(mp.Y, phase=1 if mode_num % 2 == 1 else -1)])

        xm = 0.5 * sx - dpml  # x-coordinate of monitor
        mflux = sim.add_mode_monitor(
            fcen, 0, 1,
            mp.ModeRegion(center=mp.Vector3(xm, 0),
                          size=mp.Vector3(0, sy - 2 * dpml)))
        mode_flux = sim.add_flux(
            fcen, 0, 1,
            mp.FluxRegion(center=mp.Vector3(xm, 0),
                          size=mp.Vector3(0, sy - 2 * dpml)))

        # sim.run(until_after_sources=mp.stop_when_fields_decayed(50, mp.Ez, mp.Vector3(-0.5*sx+dpml,0), 1e-10))
        sim.run(until_after_sources=100)

        modes_to_check = [
            1, 2
        ]  # indices of modes for which to compute expansion coefficients
        res = sim.get_eigenmode_coefficients(mflux,
                                             modes_to_check,
                                             kpoint_func=kpoint_func)

        self.assertTrue(res.kpoints[0].close(mp.Vector3(0.604301, 0, 0)))
        self.assertTrue(res.kpoints[1].close(mp.Vector3(0.494353, 0, 0),
                                             tol=1e-2))
        self.assertTrue(res.kdom[0].close(mp.Vector3(0.604301, 0, 0)))
        self.assertTrue(res.kdom[1].close(mp.Vector3(0.494353, 0, 0),
                                          tol=1e-2))

        mode_power = mp.get_fluxes(mode_flux)[0]

        TestPassed = True
        TOLERANCE = 5.0e-3
        c0 = res.alpha[
            mode_num - 1, 0,
            0]  # coefficient of forward-traveling wave for mode #mode_num
        for nm in range(1, len(modes_to_check) + 1):
            if nm != mode_num:
                cfrel = np.abs(res.alpha[nm - 1, 0, 0]) / np.abs(c0)
                cbrel = np.abs(res.alpha[nm - 1, 0, 1]) / np.abs(c0)
                if cfrel > TOLERANCE or cbrel > TOLERANCE:
                    TestPassed = False

        self.sim = sim

        # test 1: coefficient of excited mode >> coeffs of all other modes
        self.assertTrue(TestPassed,
                        msg="cfrel: {}, cbrel: {}".format(cfrel, cbrel))
        # test 2: |mode coeff|^2 = power
        self.assertAlmostEqual(mode_power / abs(c0**2), 1.0, places=1)

        return res
예제 #2
0
def main(args):
    # Some parameters to describe the geometry:
    eps = 13  # dielectric constant of waveguide
    w = 1.2  # width of waveguide
    r = 0.36  # radius of holes
    d = 1.4  # defect spacing (ordinary spacing = 1)
    N = args.N  # number of holes on either side of defect

    # The cell dimensions
    sy = args.sy  # size of cell in y direction (perpendicular to wvg.)
    pad = 2  # padding between last hole and PML edge
    dpml = 1  # PML thickness

    sx = 2 * (pad + dpml + N) + d - 1  # size of cell in x direction

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

    blk = mp.Block(size=mp.Vector3(1e20, w, 1e20),
                   material=mp.Medium(epsilon=eps))

    geometry = [blk]

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

    fcen = args.fcen  # pulse center frequency
    df = args.df  # pulse frequency width

    nfreq = 500  # number of frequencies at which to compute flux

    sim = mp.Simulation(cell_size=cell,
                        geometry=geometry,
                        sources=[],
                        boundary_layers=[mp.PML(dpml)],
                        resolution=20)

    if args.resonant_modes:
        sim.sources.append(
            mp.Source(mp.GaussianSource(fcen, fwidth=df), mp.Hz, mp.Vector3()))

        sim.symmetries.append(mp.Mirror(mp.Y, phase=-1))
        sim.symmetries.append(mp.Mirror(mp.X, phase=-1))

        sim.run(  # mp.at_beginning(mp.output_epsilon),
            mp.after_sources(mp.Harminv(mp.Hz, mp.Vector3(), fcen, df)),
            until_after_sources=400)

        # sim.run(mp.at_every(1 / fcen / 20, mp.output_hfield_z), until=1 / fcen)

    else:
        sim.sources.append(
            mp.Source(mp.GaussianSource(fcen, fwidth=df),
                      mp.Ey,
                      mp.Vector3(dpml + (-0.5 * sx)),
                      size=mp.Vector3(0, w)))

        sim.symmetries.append(mp.Mirror(mp.Y, phase=-1))

        freg = mp.FluxRegion(center=mp.Vector3((0.5 * sx) - dpml - 0.5),
                             size=mp.Vector3(0, 2 * w))

        # transmitted flux
        trans = sim.add_flux(fcen, df, nfreq, freg)

        vol = mp.Volume(mp.Vector3(), size=mp.Vector3(sx))

        sim.run(mp.at_beginning(mp.output_epsilon),
                mp.during_sources(
                    mp.in_volume(
                        vol,
                        mp.to_appended("hz-slice",
                                       mp.at_every(0.4, mp.output_hfield_z)))),
                until_after_sources=mp.stop_when_fields_decayed(
                    50, mp.Ey, mp.Vector3((0.5 * sx) - dpml - 0.5, 0), 1e-3))

        sim.display_fluxes(trans)  # print out the flux spectrum
예제 #3
0
def main(args=None):
    fcen = 1 / 1.54
    df = 0.1
    wvg_width = .7
    wvg_height = .22
    dpml = 1
    dpad = 2
    sim2d = False
    time_after_source = 500
    eps_only = False
    subz = True
    resolution = 30
    _nSi = 3.45
    mode = get_excitation_mode("Ey")

    # we want to investigate tuning. Change this to add a different material instead of air:
    cover_material = mp.Medium(index=1.11)

    if args is not None:
        hx = args.diameter
        hy = args.diameter
        h_rel = args.h_rel
        n = args.n
        _nSi = args.n_si

    nSi = mp.Medium(index=_nSi)

    wvg = waveguide_1d(
        wvg_width=wvg_width,
        wvg_height=wvg_height,
        material=nSi,
    )
    cav, cav_length = quadratic_radius_1d_symmetric(
        n_segments=n,
        hx=hx,
        hy=hy,
        h_rel=h_rel,
        material_tuning=cover_material)

    sx = dpml + dpad + cav_length + dpad + dpml
    sy = dpml + dpad + wvg_width + dpad + dpml
    sz = dpml + dpad + wvg_height + dpad + dpml

    subs_height = (sz - wvg_height) / 2
    subs = substrate(substrate_height=subs_height,
                     center=mp.Vector3(0, 0, -sz / 2 + subs_height / 2))

    geometry = wvg + cav

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

    if subz:
        geometry = wvg + cav + subs
        symmetries = [mp.Mirror(mp.X, +1), mp.Mirror(mp.Y, -1)]

    boundary = get_boundary_layer(dpml, sim2d=sim2d)

    if sim2d:
        sz = 0

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

    sources = [
        mp.Source(mp.GaussianSource(fcen, fwidth=df),
                  component=mode,
                  center=mp.Vector3())
    ]

    sim = mp.Simulation(cell_size=cell_size,
                        geometry=geometry,
                        sources=sources,
                        boundary_layers=boundary,
                        symmetries=symmetries,
                        resolution=resolution,
                        progress_interval=100,
                        default_material=cover_material)

    f = plt.figure(figsize=(10, 10))
    sim.plot2D(ax=f.gca(),
               output_plane=mp.Volume(center=mp.Vector3(0, 0, 0),
                                      size=mp.Vector3(sx, sy, 0)))
    f.savefig("xy_plane.pdf", format="PDF")

    f = plt.figure(figsize=(10, 10))
    sim.plot2D(ax=f.gca(),
               output_plane=mp.Volume(center=mp.Vector3(0, 0, 0),
                                      size=mp.Vector3(sx, 0, sz)))

    f.savefig("xz_plane.pdf", format="PDF")

    f = plt.figure(figsize=(10, 10))
    sim.plot2D(ax=f.gca(),
               output_plane=mp.Volume(center=mp.Vector3(0, 0, 0),
                                      size=mp.Vector3(0, sy, sz)))

    f.savefig("yz_plane.pdf", format="PDF")

    h = mp.Harminv(mode, mp.Vector3(0, 0, 0), fcen, df)

    # h_displaced = mp.Harminv(mode, mp.Vector3(0.05, 0.1, 0.02), fcen, df)

    if eps_only:
        sim.run(mp.at_beginning(mp.output_epsilon), until=0)

    else:
        # Don't output eps anymore to save disk space
        sim.run(
            mp.after_sources(h),
            # mp.after_sources(h_displaced),
            until_after_sources=time_after_source)
예제 #4
0
lcen = 0.5              # center wavelength
fcen = 1/lcen           # center frequency
df = 0.2*fcen           # frequency width

focal_length = 200      # focal length of metalens
spot_length = 100       # far field line length
ff_res = 10             # far field resolution (points/μm)

k_point = mp.Vector3(0,0,0)

glass = mp.Medium(index=1.5)

pml_layers = [mp.PML(thickness=dpml,direction=mp.X)]

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

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),
예제 #5
0
    ]
else:
    sources = [
        mp.Source(src=mp.GaussianSource(fsrc, fwidth=0.2 * fsrc)
                  if compute_flux else mp.ContinuousSource(fsrc),
                  center=mp.Vector3(),
                  size=mp.Vector3(y=3 * w),
                  component=mp.Ez)
    ]

sim = mp.Simulation(cell_size=cell_size,
                    resolution=resolution,
                    boundary_layers=pml_layers,
                    sources=sources,
                    geometry=geometry,
                    symmetries=[mp.Mirror(mp.Y)] if rot_angle == 0 else [])

if compute_flux:
    tran = sim.add_flux(
        fsrc, 0, 1, mp.FluxRegion(center=mp.Vector3(x=5),
                                  size=mp.Vector3(y=14)))
    sim.run(until_after_sources=50)
    res = sim.get_eigenmode_coefficients(
        tran, [1],
        eig_parity=mp.EVEN_Y + mp.ODD_Z if rot_angle == 0 else mp.ODD_Z,
        direction=mp.NO_DIRECTION,
        kpoint_func=lambda f, n: kpoint)
    print("flux:, {:.6f}, {:.6f}".format(
        mp.get_fluxes(tran)[0],
        abs(res.alpha[0, 0, 0])**2))
else:
예제 #6
0
 def test_3d_with_symmetry(self):
     self._test_3d([mp.Mirror(mp.X), mp.Mirror(mp.Y), mp.Mirror(mp.Z)])
예제 #7
0
    def pec_ground_plane_radiation(self):
        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 / self.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
        # cut 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=self.src_cmpt,
                      center=mp.Vector3(0, +self.h)),
            mp.Source(src=mp.GaussianSource(fcen, fwidth=0.2 * fcen),
                      component=self.src_cmpt,
                      center=mp.Vector3(0, -self.h),
                      amplitude=-1 if self.src_cmpt == mp.Ez else +1)
        ]

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

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

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

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

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

        return Pr
예제 #8
0
dpml = 1
cell = mp.Vector3(sxy + 2 * dpml, sxy + 2 * dpml)

pml_layers = [mp.PML(dpml)]

fcen = 1.0
df = 0.4
src_cmpt = mp.Ez
sources = [
    mp.Source(src=mp.GaussianSource(fcen, fwidth=df),
              center=mp.Vector3(),
              component=src_cmpt)
]

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

nearfield_box = sim.add_near2far(
    fcen, 0, 1,
    mp.Near2FarRegion(center=mp.Vector3(0, +0.5 * sxy),
                      size=mp.Vector3(sxy, 0)),
예제 #9
0
    def test_get_point(self):
        sxy = 6                 # cell size
        dpml = 1                # thickness of PML

        def sinusoid(p):
            r = (p.x**2+p.y**2)**0.5
            return mp.Medium(index=1.0+math.sin(2*math.pi*r)**2)

        geometry = [mp.Block(center=mp.Vector3(),
                             size=mp.Vector3(sxy,sxy),
                             material=sinusoid)]

        src = [mp.Source(mp.GaussianSource(1.0, fwidth=0.1),
                         component=mp.Ez,
                         center=mp.Vector3())]

        sim = mp.Simulation(cell_size=mp.Vector3(sxy,sxy),
                            geometry=geometry,
                            sources=src,
                            k_point=mp.Vector3(),
                            resolution=20,
                            symmetries=[mp.Mirror(mp.X),mp.Mirror(mp.Y)],
                            boundary_layers=[mp.PML(dpml)])

        sim.run(until_after_sources=100)

        ## reference values for Ez and epsilon from serial run
        ez_ref = [ -0.0002065983,
                   -0.0001954795,
                   -0.0000453570,
                   0.0000311267,
                   -0.0000121473,
                   -0.0000410032,
                   -0.0000341301,
                   -0.0000275021,
                   -0.0000397990,
                   -0.0000351730,
                   0.0000079602,
                   0.0000227437,
                   -0.0001092821,
                   -0.0002202751,
                   -0.0001408186,
                   0.0006325076,
                   0.0024890489,
                   0.0027476069,
                   0.0014815873,
                   0.0004714913,
                   -0.0004332029,
                   -0.0007101315,
                   -0.0003818581,
                   -0.0000748507,
                   0.0001408819,
                   0.0001119776,
                   0.0000395008,
                   0.0000078844,
                   -0.0000010431 ]

        eps_ref = [ 1.6458346134,
                    1.2752837068,
                    1.0974010956,
                    1.0398089537,
                    1.0465784716,
                    1.0779924737,
                    1.1059439286,
                    1.1135579291,
                    1.0971979186,
                    1.0653178566,
                    1.0391657283,
                    1.0513779677,
                    1.1466009312,
                    1.3882154483,
                    1.8496939317,
                    2.5617731415,
                    3.3788212533,
                    3.9019494270,
                    3.6743431894,
                    2.7285622651,
                    1.6635165033,
                    1.0891237010,
                    1.1485969863,
                    1.9498398061,
                    3.3100416367,
                    3.9038800599,
                    2.8471862395,
                    1.4742605488,
                    1.0370162714 ]

        x = np.linspace(-0.865692,2.692867,29)
        places = 5 if mp.is_single_precision() else 10
        for j in range(x.size):
            self.assertAlmostEqual(np.real(sim.get_field_point(mp.Ez, mp.Vector3(x[j],-0.394862))),
                                   ez_ref[j],
                                   places=places)
            self.assertAlmostEqual(sim.get_epsilon_point(mp.Vector3(x[j],2.967158)),
                                   eps_ref[j],
                                   places=places)
예제 #10
0
frq_min = 1/wvl_max
frq_max = 1/wvl_min
frq_cen = 0.5*(frq_min+frq_max)
dfrq = frq_max-frq_min
nfrq = 100

## at least 8 pixels per smallest wavelength, i.e. np.floor(8/wvl_min)
resolution = 25

dpml = 0.5*wvl_max
dair = 0.5*wvl_max

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

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

s = 2*(dpml+dair+r)
cell_size = mp.Vector3(s,s,s)

# is_integrated=True necessary for any planewave source extending into PML
sources = [mp.Source(mp.GaussianSource(frq_cen,fwidth=dfrq,is_integrated=True),
                     center=mp.Vector3(-0.5*s+dpml),
                     size=mp.Vector3(0,s,s),
                     component=mp.Ez)]

sim = mp.Simulation(resolution=resolution,
                    cell_size=cell_size,
                    boundary_layers=pml_layers,
                    sources=sources,
예제 #11
0
# moving point charge with superluminal phase velocity in dielectric media emitting Cherenkov radiation

import meep as mp

sx = 60
sy = 60
cell_size = mp.Vector3(sx, sy, 0)

dpml = 1.0
pml_layers = [mp.PML(thickness=dpml)]

v = 0.7  # velocity of point charge

symmetries = [mp.Mirror(direction=mp.Y)]

sim = mp.Simulation(resolution=10,
                    cell_size=cell_size,
                    default_material=mp.Medium(index=1.5),
                    symmetries=symmetries,
                    boundary_layers=pml_layers)


def move_source(sim):
    sim.change_sources([
        mp.Source(mp.ContinuousSource(frequency=1e-10),
                  component=mp.Ex,
                  center=mp.Vector3(-0.5 * sx + dpml + v * sim.meep_time()))
    ])


sim.run(move_source,
예제 #12
0
    def run_mode_coeffs(self, mode_num, kpoint_func, nf=1, resolution=15):

        w = 1  # width of waveguide
        L = 10  # length of waveguide

        Si = mp.Medium(epsilon=12.0)

        dair = 3.0
        dpml = 3.0

        sx = dpml + L + dpml
        sy = dpml + dair + w + dair + dpml
        cell_size = mp.Vector3(sx, sy, 0)

        prism_x = sx + 1
        prism_y = w / 2
        vertices = [
            mp.Vector3(-prism_x, prism_y),
            mp.Vector3(prism_x, prism_y),
            mp.Vector3(prism_x, -prism_y),
            mp.Vector3(-prism_x, -prism_y)
        ]

        geometry = [mp.Prism(vertices, height=mp.inf, material=Si)]

        boundary_layers = [mp.PML(dpml)]

        # mode frequency
        fcen = 0.20  # > 0.5/sqrt(11) to have at least 2 modes
        df = 0.5 * fcen

        source = mp.EigenModeSource(src=mp.GaussianSource(fcen, fwidth=df),
                                    eig_band=mode_num,
                                    size=mp.Vector3(0, sy - 2 * dpml, 0),
                                    center=mp.Vector3(-0.5 * sx + dpml, 0, 0),
                                    eig_match_freq=True,
                                    eig_resolution=2 * resolution)

        sim = mp.Simulation(
            resolution=resolution,
            cell_size=cell_size,
            boundary_layers=boundary_layers,
            geometry=geometry,
            sources=[source],
            symmetries=[mp.Mirror(mp.Y, phase=1 if mode_num % 2 == 1 else -1)])

        xm = 0.5 * sx - dpml  # x-coordinate of monitor
        mflux = sim.add_mode_monitor(
            fcen, df, nf,
            mp.ModeRegion(center=mp.Vector3(xm, 0),
                          size=mp.Vector3(0, sy - 2 * dpml)))
        mode_flux = sim.add_flux(
            fcen, df, nf,
            mp.FluxRegion(center=mp.Vector3(xm, 0),
                          size=mp.Vector3(0, sy - 2 * dpml)))

        # sim.run(until_after_sources=mp.stop_when_fields_decayed(50, mp.Ez, mp.Vector3(-0.5*sx+dpml,0), 1e-10))
        sim.run(until_after_sources=200)

        ##################################################
        # If the number of analysis frequencies is >1, we
        # are testing the unit-power normalization
        # of the eigenmode source: we observe the total
        # power flux through the mode_flux monitor (which
        # equals the total power emitted by the source as
        # there is no scattering in this ideal waveguide)
        # and check that it agrees with the prediction
        # of the eig_power() class method in EigenmodeSource.
        ##################################################
        if nf > 1:
            power_observed = mp.get_fluxes(mode_flux)
            freqs = mp.get_flux_freqs(mode_flux)
            power_expected = [source.eig_power(f) for f in freqs]
            return freqs, power_expected, power_observed

        modes_to_check = [
            1, 2
        ]  # indices of modes for which to compute expansion coefficients
        res = sim.get_eigenmode_coefficients(mflux,
                                             modes_to_check,
                                             kpoint_func=kpoint_func)

        self.assertTrue(res.kpoints[0].close(mp.Vector3(0.604301, 0, 0)))
        self.assertTrue(res.kpoints[1].close(mp.Vector3(0.494353, 0, 0),
                                             tol=1e-2))
        self.assertTrue(res.kdom[0].close(mp.Vector3(0.604301, 0, 0)))
        self.assertTrue(res.kdom[1].close(mp.Vector3(0.494353, 0, 0),
                                          tol=1e-2))
        self.assertAlmostEqual(res.cscale[0], 0.50000977, places=5)
        self.assertAlmostEqual(res.cscale[1], 0.50096888, places=5)
        mode_power = mp.get_fluxes(mode_flux)[0]

        TestPassed = True
        TOLERANCE = 5.0e-3
        c0 = res.alpha[
            mode_num - 1, 0,
            0]  # coefficient of forward-traveling wave for mode #mode_num
        for nm in range(1, len(modes_to_check) + 1):
            if nm != mode_num:
                cfrel = np.abs(res.alpha[nm - 1, 0, 0]) / np.abs(c0)
                cbrel = np.abs(res.alpha[nm - 1, 0, 1]) / np.abs(c0)
                if cfrel > TOLERANCE or cbrel > TOLERANCE:
                    TestPassed = False

        self.sim = sim

        # test 1: coefficient of excited mode >> coeffs of all other modes
        self.assertTrue(TestPassed,
                        msg="cfrel: {}, cbrel: {}".format(cfrel, cbrel))
        # test 2: |mode coeff|^2 = power
        self.assertAlmostEqual(mode_power / abs(c0**2), 1.0, places=1)

        return res
예제 #13
0
    def wvg_flux(self, res, att_coeff):
        """
        Computes the Poynting flux in a single-mode waveguide at two
        locations (5 and 10 μm) downstream from the source given the
        grid resolution res (pixels/μm) and material attenuation
        coefficient att_coeff (dB/cm).
        """

        cell_size = mp.Vector3(14., 14.)

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

        w = 1.  # width of waveguide

        fsrc = 0.15  # frequency (in vacuum)

        # note: MPB can only compute modes of lossless material systems.
        #       The imaginary part of ε is ignored and the launched
        #       waveguide mode is therefore inaccurate. For small values
        #       of imag(ε) (which is proportional to att_coeff), this
        #       inaccuracy tends to be insignificant.
        sources = [
            mp.EigenModeSource(src=mp.GaussianSource(fsrc, fwidth=0.2 * fsrc),
                               center=mp.Vector3(-5.),
                               size=mp.Vector3(y=10.),
                               eig_parity=mp.EVEN_Y + mp.ODD_Z)
        ]

        # ref: https://en.wikipedia.org/wiki/Mathematical_descriptions_of_opacity
        # Note that this is the loss of a planewave, which is only approximately
        # the loss of a waveguide mode.  In principle, we could compute the latter
        # semi-analytically if we wanted to run this unit test to greater accuracy
        # (e.g. to test convergence with resolution).
        n_eff = np.sqrt(12.) + 1j * (1 / fsrc) * (dB_cm_to_dB_um *
                                                  att_coeff) / (4 * np.pi)
        eps_eff = n_eff * n_eff
        # ref: https://meep.readthedocs.io/en/latest/Materials/#conductivity-and-complex
        sigma_D = 2 * np.pi * fsrc * np.imag(eps_eff) / np.real(eps_eff)

        geometry = [
            mp.Block(center=mp.Vector3(),
                     size=mp.Vector3(mp.inf, w, mp.inf),
                     material=mp.Medium(epsilon=np.real(eps_eff),
                                        D_conductivity=sigma_D))
        ]

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

        tran1 = sim.add_flux(
            fsrc, 0, 1,
            mp.FluxRegion(center=mp.Vector3(x=0.), size=mp.Vector3(y=10.)))

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

        sim.run(until_after_sources=20)

        return mp.get_fluxes(tran1)[0], mp.get_fluxes(tran2)[0]
예제 #14
0
    def test_mode_decomposition(self):
        resolution = 10
        w1 = 1
        w2 = 2
        Lw = 2
        dair = 3.0
        dpml = 5.0
        sy = dpml + dair + w2 + dair + dpml
        half_w1 = 0.5 * w1
        half_w2 = 0.5 * w2
        Si = mp.Medium(epsilon=12.0)
        boundary_layers = [mp.PML(dpml)]
        lcen = 6.67
        fcen = 1 / lcen
        symmetries = [mp.Mirror(mp.Y)]
        Lt = 2
        sx = dpml + Lw + Lt + Lw + dpml
        cell_size = mp.Vector3(sx, sy, 0)
        prism_x = sx + 1
        half_Lt = 0.5 * Lt
        src_pt = mp.Vector3(-0.5 * sx + dpml + 0.2 * Lw, 0, 0)
        sources = [
            mp.EigenModeSource(src=mp.GaussianSource(fcen, fwidth=0.2 * fcen),
                               component=mp.Ez,
                               center=src_pt,
                               size=mp.Vector3(0, sy - 2 * dpml, 0),
                               eig_match_freq=True,
                               eig_parity=mp.ODD_Z + mp.EVEN_Y)
        ]

        vertices = [
            mp.Vector3(-prism_x, half_w1),
            mp.Vector3(prism_x, half_w1),
            mp.Vector3(prism_x, -half_w1),
            mp.Vector3(-prism_x, -half_w1)
        ]

        sim = mp.Simulation(
            resolution=resolution,
            cell_size=cell_size,
            boundary_layers=boundary_layers,
            geometry=[mp.Prism(vertices, height=mp.inf, material=Si)],
            sources=sources,
            symmetries=symmetries)

        mon_pt = mp.Vector3(-0.5 * sx + dpml + 0.5 * Lw, 0, 0)
        flux = sim.add_flux(
            fcen, 0, 1,
            mp.FluxRegion(center=mon_pt, size=mp.Vector3(0, sy - 2 * dpml, 0)))

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

        incident_coeffs, vgrp, kpoints = sim.get_eigenmode_coefficients(
            flux, [1], eig_parity=mp.ODD_Z + mp.EVEN_Y)
        incident_flux = mp.get_fluxes(flux)
        incident_flux_data = sim.get_flux_data(flux)

        sim.reset_meep()

        vertices = [
            mp.Vector3(-prism_x, half_w1),
            mp.Vector3(-half_Lt, half_w1),
            mp.Vector3(half_Lt, half_w2),
            mp.Vector3(prism_x, half_w2),
            mp.Vector3(prism_x, -half_w2),
            mp.Vector3(half_Lt, -half_w2),
            mp.Vector3(-half_Lt, -half_w1),
            mp.Vector3(-prism_x, -half_w1)
        ]

        sim = mp.Simulation(
            resolution=resolution,
            cell_size=cell_size,
            boundary_layers=boundary_layers,
            geometry=[mp.Prism(vertices, height=mp.inf, material=Si)],
            sources=sources,
            symmetries=symmetries)

        refl_flux = sim.add_flux(
            fcen, 0, 1,
            mp.FluxRegion(center=mon_pt, size=mp.Vector3(0, sy - 2 * dpml, 0)))
        sim.load_minus_flux_data(refl_flux, incident_flux_data)

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

        coeffs, vgrp, kpoints = sim.get_eigenmode_coefficients(
            refl_flux, [1], eig_parity=mp.ODD_Z + mp.EVEN_Y)
        taper_flux = mp.get_fluxes(refl_flux)

        self.assertAlmostEqual(abs(coeffs[0, 0, 1])**2 /
                               abs(incident_coeffs[0, 0, 0])**2,
                               -taper_flux[0] / incident_flux[0],
                               places=4)
예제 #15
0
            wvl_min = 0.400
            wvl_max = 0.700
            frq_min = 1 / wvl_max
            frq_max = 1 / wvl_min
            frq_cen = 0.5 * (frq_min + frq_max)
            dfrq = frq_max - frq_min
            nfrq = 100
            Material = Au
            resolution = 300
            dpml = 0.11
            pml_layers = [
                mp.PML(dpml, direction=mp.X, side=mp.High),
                mp.Absorber(dpml, direction=mp.X, side=mp.Low)
            ]
            if (k == mp.Ey):
                symmetries = [mp.Mirror(mp.Y, phase=-1)]
            else:
                symmetries = [mp.Mirror(mp.Y)]

            celly = (spacing_thickness + block_thicknessy)
            cellx = block_thicknessx + 2 * dpml + 2 * offsetx

            sources = [
                mp.Source(mp.GaussianSource(frq_cen,
                                            fwidth=dfrq,
                                            is_integrated=True),
                          center=mp.Vector3(-0.5 * cellx + dpml + 0.01),
                          size=mp.Vector3(0, celly),
                          component=k)
            ]
예제 #16
0
def main(args):

    resolution = 20  # pixels/um

    eps = 13  # dielectric constant of waveguide
    w = 1.2  # width of waveguide
    r = 0.36  # radius of holes
    d = 1.4  # defect spacing (ordinary spacing = 1)
    N = args.N  # number of holes on either side of defect

    sy = args.sy  # size of cell in y direction (perpendicular to wvg.)
    pad = 2  # padding between last hole and PML edge
    dpml = 1  # PML thickness

    sx = 2 * (pad + dpml + N) + d - 1  # size of cell in x direction

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

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

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

    pml_layers = [mp.PML(1.0)]

    fcen = args.fcen  # pulse center frequency
    df = args.df  # pulse frequency width

    src = [
        mp.Source(mp.GaussianSource(fcen, fwidth=df),
                  component=mp.Ey,
                  center=mp.Vector3(-0.5 * sx + dpml),
                  size=mp.Vector3(0, w))
    ]

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

    sim = mp.Simulation(cell_size=cell,
                        geometry=geometry,
                        boundary_layers=pml_layers,
                        sources=src,
                        symmetries=sym,
                        resolution=resolution)
    freg = mp.FluxRegion(center=mp.Vector3(0.5 * sx - dpml - 0.5),
                         size=mp.Vector3(0, 2 * w))

    nfreq = 500  # number of frequencies at which to compute flux

    # transmitted flux
    trans = sim.add_flux(fcen, df, nfreq, freg)

    vol = mp.Volume(mp.Vector3(0), size=mp.Vector3(sx))

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

    sim.run(mp.at_beginning(mp.output_epsilon),
            mp.during_sources(
                mp.in_volume(
                    vol,
                    mp.to_appended("hz-slice",
                                   mp.at_every(0.4, mp.output_hfield_z)))),
            until_after_sources=mp.stop_when_fields_decayed(
                50, mp.Ey, mp.Vector3(0.5 * sx - dpml - 0.5), 1e-3))

    sim.display_fluxes(trans)  # print out the flux spectrum
예제 #17
0
 def test_1d_with_symmetry(self):
     self._test_1d([mp.Mirror(mp.X)])
예제 #18
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 if nfreqs == 1 else 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'])
예제 #19
0
    def test_poynting_theorem(self):
        """Unit test for near-to-far field transformation in 2d.

        Verifies that the Poynting flux of an Ez-polarized point
        dipole source in vacuum is independent of the shape of the
        enclosing measurement box due to Poynting's theorem by
        considering three arrangements:
             (1) bounding box of thenear fields,
             (2) bounding circle of the far fields, and
             (3) bounding box of the far fields.
        """
        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
        Pr = self.radial_flux(sim, nearfield_box, r)
        far_flux_circle = 4 * np.sum(Pr) * 0.5 * np.pi * r / len(Pr)

        rr = 20 / fcen  # length of far-field square box
        res_far = 20  # resolution 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)), res_far)[0] -
                           nearfield_box.flux(
                               mp.Y,
                               mp.Volume(center=mp.Vector3(y=-0.5 * rr),
                                         size=mp.Vector3(rr)), res_far)[0] +
                           nearfield_box.flux(
                               mp.X,
                               mp.Volume(center=mp.Vector3(0.5 * rr),
                                         size=mp.Vector3(y=rr)), res_far)[0] -
                           nearfield_box.flux(
                               mp.X,
                               mp.Volume(center=mp.Vector3(-0.5 * rr),
                                         size=mp.Vector3(y=rr)), res_far)[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
def main(args):

    resolution = 30
    nSi = 3.45
    Si = mp.Medium(index=nSi)
    dpml = 1.0
    sx = 5
    sy = 3

    cell = mp.Vector3(sx + 2 * dpml, sy + 2 * dpml)
    pml_layers = mp.PML(dpml)

    a = 1.0  # waveguide width
    s = args.s  # waveguide separation distance

    geometry = [
        mp.Block(center=mp.Vector3(-0.5 * (s + a)),
                 size=mp.Vector3(a, a, mp.inf),
                 material=Si),
        mp.Block(center=mp.Vector3(0.5 * (s + a)),
                 size=mp.Vector3(a, a, mp.inf),
                 material=Si)
    ]

    xodd = args.xodd
    symmetries = [
        mp.Mirror(mp.X, phase=-1.0 if xodd else 1.0),
        mp.Mirror(mp.Y, phase=-1.0)
    ]

    beta = 0.5
    k_point = mp.Vector3(z=beta)

    fcen = 0.22
    df = 0.06
    sources = [
        mp.Source(src=mp.GaussianSource(fcen, fwidth=df),
                  component=mp.Ey,
                  center=mp.Vector3(-0.5 * (s + a)),
                  size=mp.Vector3(a, a)),
        mp.Source(src=mp.GaussianSource(fcen, fwidth=df),
                  component=mp.Ey,
                  center=mp.Vector3(0.5 * (s + a)),
                  size=mp.Vector3(a, a),
                  amplitude=-1.0 if xodd else 1.0)
    ]

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

    h = mp.Harminv(mp.Ey, mp.Vector3(0.5 * (s + a)), fcen, df)

    sim.run(mp.after_sources(h), until_after_sources=200)

    f = h.modes[0].freq
    print("freq:, {}, {}".format(s, f))

    sim.reset_meep()

    new_sources = [
        mp.EigenModeSource(src=mp.GaussianSource(f, fwidth=df),
                           component=mp.Ey,
                           size=mp.Vector3(a, a),
                           center=mp.Vector3(-0.5 * (s + a)),
                           eig_kpoint=k_point,
                           eig_match_freq=True,
                           eig_parity=mp.ODD_Y),
        mp.EigenModeSource(src=mp.GaussianSource(f, fwidth=df),
                           component=mp.Ey,
                           size=mp.Vector3(a, a),
                           center=mp.Vector3(0.5 * (s + a)),
                           eig_kpoint=k_point,
                           eig_match_freq=True,
                           eig_parity=mp.ODD_Y,
                           amplitude=-1.0 if xodd else 1.0)
    ]

    sim.change_sources(new_sources)

    flx_reg = mp.FluxRegion(direction=mp.Z,
                            center=mp.Vector3(),
                            size=mp.Vector3(1.2 * (2 * a + s), 1.2 * a))
    wvg_pwr = sim.add_flux(f, 0, 1, flx_reg)

    frc_reg1 = mp.ForceRegion(mp.Vector3(0.5 * s),
                              mp.X,
                              weight=1.0,
                              size=mp.Vector3(y=a))
    frc_reg2 = mp.ForceRegion(mp.Vector3(0.5 * s + a),
                              mp.X,
                              weight=-1.0,
                              size=mp.Vector3(y=a))
    wvg_force = sim.add_force(f, 0, 1, frc_reg1, frc_reg2)

    runtime = 5000
    sim.run(until_after_sources=runtime)
    sim.display_fluxes(wvg_pwr)
    sim.display_forces(wvg_force)
def grating(gp, gh, gdc, oddz):
    sx = dpml + dsub + gh + dpad + dpml
    sy = gp

    cell_size = mp.Vector3(sx, sy, 0)
    pml_layers = [mp.PML(thickness=dpml, direction=mp.X)]

    src_pt = mp.Vector3(-0.5 * sx + dpml + 0.5 * dsub, 0, 0)
    sources = [
        mp.Source(mp.GaussianSource(fcen, fwidth=df),
                  component=mp.Ez if oddz else mp.Hz,
                  center=src_pt,
                  size=mp.Vector3(0, sy, 0))
    ]

    symmetries = [mp.Mirror(mp.Y, phase=+1 if oddz else -1)]

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

    mon_pt = mp.Vector3(0.5 * sx - dpml - 0.5 * dpad, 0, 0)
    flux_mon = sim.add_flux(
        fcen, df, nfreq, mp.FluxRegion(center=mon_pt,
                                       size=mp.Vector3(0, sy, 0)))

    sim.run(until_after_sources=100)

    input_flux = mp.get_fluxes(flux_mon)

    sim.reset_meep()

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

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

    mode_mon = sim.add_flux(
        fcen, df, nfreq, mp.FluxRegion(center=mon_pt,
                                       size=mp.Vector3(0, sy, 0)))

    sim.run(until_after_sources=300)

    freqs = mp.get_eigenmode_freqs(mode_mon)
    res = sim.get_eigenmode_coefficients(
        mode_mon, [1],
        eig_parity=mp.ODD_Z + mp.EVEN_Y if oddz else mp.EVEN_Z + mp.ODD_Y)
    coeffs = res.alpha

    mode_wvl = [1 / freqs[nf] for nf in range(nfreq)]
    mode_tran = [
        abs(coeffs[0, nf, 0])**2 / input_flux[nf] for nf in range(nfreq)
    ]
    mode_phase = [np.angle(coeffs[0, nf, 0]) for nf in range(nfreq)]

    return mode_wvl, mode_tran, mode_phase
예제 #22
0
# The source will now be the usual Gaussian pulse centered at `fcen`, located at one edge of the cell just outside the PML, at `x = - 0.5 * sx + dpml`. Ideally, we would excite exactly the fundamental mode of the waveguide, but it is good enough to just excite it with a line source. Moreover, since we are interested in the $P$ polarization (electric field in the plane), we will excite it with a $J_y$ current source (transverse to the propagation direction), which is specified as $E_y$:

# In[8]:

src = [
    mp.Source(mp.GaussianSource(fcen, fwidth=df),
              component=mp.Ey,
              center=mp.Vector3(-0.5 * sx + dpml),
              size=mp.Vector3(0, w))
]

# The structure has mirror symmetry planes through the $X$ and $Y$ axes. The source breaks the mirror symmetry through the $Y$ axis, but we still have odd mirror symmetry through the $Z$ axis:

# In[9]:

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

# Note that we specify the plane by its normal, the $Y$ direction. See also Exploiting Symmetry. Putting all these objects together via the `Simulation` object:

# In[10]:

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

# We need to compute the flux spectrum at the other end of the computational cell, after the holes but before the PML:

# In[11]:
예제 #23
0
def main(args):

    resolution = 20 # pixels/unit length (1 um)

    h = args.hh
    w = args.w
    a = args.a
    d = args.d
    N = args.N
    N = N + 1

    nSi = 3.45
    Si = mp.Medium(index=nSi)
    nSiO2 = 1.45
    SiO2 = mp.Medium(index=nSiO2)

    sxy = 16
    sz = 4
    cell_size = mp.Vector3(sxy, sxy, sz)

    geometry = []

    # rings of Bragg grating
    for n in range(N,0,-1):
        geometry.append(mp.Cylinder(material=Si, center=mp.Vector3(0,0,0), radius=n*a, height=h))
        geometry.append(mp.Cylinder(material=mp.air, center=mp.Vector3(0,0,0), radius=n*a-d, height=h))

    # remove left half of Bragg grating rings to form semi circle
    geometry.append(mp.Block(material=mp.air, center=mp.Vector3(-0.5*N*a,0,0), size=mp.Vector3(N*a,2*N*a,h)))
    geometry.append(mp.Cylinder(material=Si, center=mp.Vector3(0,0,0), radius=a-d, height=h))

    # angle sides of Bragg grating
    
    # rotation angle of sides relative to Y axis (degrees)
    rot_theta = -1*math.radians(args.rot_theta)
    
    pvec = mp.Vector3(0, 0.5*w, 0)
    cvec = mp.Vector3(-0.5*N*a, 0.5*N*a+0.5*w, 0)
    rvec = cvec-pvec
    rrvec = rvec.rotate(mp.Vector3(0,0,1), rot_theta)
    
    geometry.append(mp.Block(material=mp.air, center=pvec+rrvec, size=mp.Vector3(N*a,N*a,h),
                             e1=mp.Vector3(0.9396926207859084,-0.3420201433256687,0),
                             e2=mp.Vector3(0.3420201433256687,0.9396926207859084,0),
                             e3=mp.Vector3(0,0,1)))

    pvec = mp.Vector3(0, -0.5*w, 0)
    cvec = mp.Vector3(-0.5*N*a, -1*(0.5*N*a+0.5*w), 0)
    rvec = cvec-pvec
    rrvec = rvec.rotate(mp.Vector3(0,0,1), -1*rot_theta)

    geometry.append(mp.Block(material=mp.air, center=pvec+rrvec, size=mp.Vector3(N*a,N*a,h),
                             e1=mp.Vector3(0.9396926207859084,0.3420201433256687,0),
                             e2=mp.Vector3(-0.3420201433256687,0.9396926207859084,0),
                             e3=mp.Vector3(0,0,1)))
    
    # input waveguide
    geometry.append(mp.Block(material=mp.air, center=mp.Vector3(-0.25*sxy,0.5*w+0.5*a,0), size=mp.Vector3(0.5*sxy,a,h)))
    geometry.append(mp.Block(material=mp.air, center=mp.Vector3(-0.25*sxy,-1*(0.5*w+0.5*a),0), size=mp.Vector3(0.5*sxy,a,h)))
    geometry.append(mp.Block(material=Si, center=mp.Vector3(-0.25*sxy,0,0), size=mp.Vector3(0.5*sxy,w,h)))

    # substrate
    geometry.append(mp.Block(material=SiO2, center=mp.Vector3(0,0,-0.5*sz+0.25*(sz-h)), size=mp.Vector3(mp.inf,mp.inf,0.5*(sz-h))))

    dpml = 1.0
    boundary_layers = [ mp.PML(dpml) ]

    # mode frequency
    fcen = 1/1.55
    
    sources = [ mp.EigenModeSource(src=mp.GaussianSource(fcen, fwidth=0.2*fcen),
                                   component=mp.Ey,
                                   size=mp.Vector3(0,sxy-2*dpml,sz-2*dpml),
                                   center=mp.Vector3(-0.5*sxy+dpml,0,0),
                                   eig_match_freq=True,
                                   eig_parity=mp.ODD_Y,
                                   eig_kpoint=mp.Vector3(1.5,0,0),
                                   eig_resolution=32) ]
    
    
    symmetries = [ mp.Mirror(mp.Y,-1) ]
    
    sim = mp.Simulation(resolution=resolution,
                        cell_size=cell_size,
                        boundary_layers=boundary_layers,
                        geometry=geometry,
                        sources=sources,
                        dimensions=3,
                        symmetries=symmetries)

    nearfield = sim.add_near2far(fcen, 0, 1, mp.Near2FarRegion(mp.Vector3(0,0,0.5*sz-dpml), size=mp.Vector3(sxy-2*dpml,sxy-2*dpml,0)))
    
    sim.run(until_after_sources=mp.stop_when_fields_decayed(50, mp.Ey, mp.Vector3(), 1e-6))

    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):
        ff = sim.get_farfield(nearfield, mp.Vector3(r * math.cos(math.pi * (n / npts)), 0, r * math.sin(math.pi * (n / npts))))
        print("farfield: {}, {}, ".format(n, math.pi * n / npts), end='')
        print(", ".join([str(f).strip('()').replace('j', 'i') for f in ff]))
예제 #24
0
def simulate_metalens(metalens):
    # Setup the MEEP objects
    cell = mp.Vector3(metalens['sim_cell_width'], metalens['sim_cell_height'])
    # All around the simulation cell
    pml_layers = [mp.PML(metalens['pml_width'])]
    # Set up the sources
    sources = [
        mp.Source(src=mp.ContinuousSource(wavelength=metalens['wavelength'],
                                          width=metalens['source_width']),
                  component=mp.Ez,
                  center=mp.Vector3(0, metalens['source_coordinate']),
                  size=mp.Vector3(2 * metalens['ws'], 0),
                  amp_func=out_of_plane_dip_amp_func_Ez(metalens)),
        mp.Source(src=mp.ContinuousSource(wavelength=metalens['wavelength'],
                                          width=metalens['source_width']),
                  component=mp.Hx,
                  center=mp.Vector3(0, metalens['source_coordinate']),
                  size=mp.Vector3(2 * metalens['ws'], 0),
                  amp_func=out_of_plane_dip_amp_func_Hx(metalens))
    ]
    # Set up the symmetries
    syms = []
    if metalens['x_mirror_symmetry']:
        syms.append(mp.Mirror(mp.X))
    sim = mp.Simulation(cell_size=cell,
                        boundary_layers=pml_layers,
                        geometry=metalens['geometry'],
                        force_complex_fields=metalens['complex_fields'],
                        symmetries=syms,
                        sources=sources,
                        resolution=metalens['resolution'])
    start_time = time.time()
    metalens['run_date'] = (
        datetime.datetime.now().strftime("%b %d %Y at %H:%M:%S"))
    mp.quiet(metalens['quiet'])
    sim.init_sim()

    # Branch if saving for making an animation
    if metalens['save_output']:
        sim.run(mp.to_appended(
            "ez-{sim_id}".format(**metalens),
            mp.at_every(metalens['simulation_time'] / 1000.,
                        mp.output_efield_z)),
                until=metalens['simulation_time'])
    else:
        sim.run(until=metalens['simulation_time'])

    # Compute the clock run time and grab the fields
    metalens['array_metadata'] = sim.get_array_metadata()
    metalens['run_time_in_s'] = time.time() - start_time
    metalens['fields'] = {
        'Ez': sim.get_array(component=mp.Ez).transpose(),
        'Hx': sim.get_array(component=mp.Hx).transpose(),
        'Hy': sim.get_array(component=mp.Hy).transpose()
    }
    metalens['eps'] = sim.get_epsilon().transpose()
    # Dump the result to disk
    if metalens['log_to_pkl'][0]:
        if metalens['log_to_pkl'][1] == '':
            pkl_fname = '%smetalens-%s.pkl' % (datadir, metalens['sim_id'])
        else:
            pkl_fname = metalens['log_to_pkl'][1]
        print(pkl_fname)
        pickle.dump(metalens, open(pkl_fname, 'wb'))
    return metalens
예제 #25
0
    def test_transmission_spectrum(self):
        expected = [
            (0.15, 7.218492264696595e-6),
            (0.1504008016032064, 6.445696315927592e-6),
            (0.1508016032064128, 5.140949243632777e-6),
            (0.15120240480961922, 3.6159747936427164e-6),
            (0.15160320641282563, 2.263940553705969e-6),
            (0.15200400801603203, 1.4757165844336744e-6),
            (0.15240480961923844, 1.5491803919142815e-6),
            (0.15280561122244485, 2.612053246626972e-6),
            (0.15320641282565126, 4.577504371188737e-6),
            (0.15360721442885766, 7.1459089162998185e-6),
            (0.15400801603206407, 9.856622013418823e-6),
            (0.15440881763527048, 1.2182309227954296e-5),
            (0.1548096192384769, 1.3647726444709649e-5),
            (0.1552104208416833, 1.3947420613633674e-5),
            (0.1556112224448897, 1.303466755716231e-5),
            (0.1560120240480961, 1.115807915037775e-5),
            (0.15641282565130252, 8.832335196969796e-6),
            (0.15681362725450892, 6.743645773127985e-6),
            (0.15721442885771533, 5.605913756087576e-6),
            (0.15761523046092174, 5.996668564026961e-6),
            (0.15801603206412815, 8.209400611614078e-6),
            (0.15841683366733456, 1.2158641936828497e-5),
            (0.15881763527054096, 1.73653230513453e-5),
            (0.15921843687374737, 2.303382576477893e-5),
            (0.15961923847695378, 2.821180350795834e-5),
            (0.1600200400801602, 3.200359292911769e-5),
            (0.1604208416833666, 3.3792624373001934e-5),
            (0.160821643286573, 3.342171394788991e-5),
            (0.1612224448897794, 3.1284866146526904e-5),
            (0.16162324649298582, 2.830022088581398e-5),
            (0.16202404809619222, 2.5758413657344014e-5),
            (0.16242484969939863, 2.506899997971769e-5),
            (0.16282565130260504, 2.7453508915303887e-5),
            (0.16322645290581145, 3.365089813497114e-5),
            (0.16362725450901786, 4.370486834112e-5),
            (0.16402805611222426, 5.689050715055283e-5),
            (0.16442885771543067, 7.181133157470506e-5),
            (0.16482965931863708, 8.666168027415369e-5),
            (0.16523046092184349, 9.961094123261317e-5),
            (0.1656312625250499, 1.0923388232657953e-4),
            (0.1660320641282563, 1.1489334204708105e-4),
            (0.1664328657314627, 1.1698318060032011e-4),
            (0.16683366733466912, 1.169621456132733e-4),
            (0.16723446893787552, 1.1714995241571987e-4),
            (0.16763527054108193, 1.2030783847222252e-4),
            (0.16803607214428834, 1.2907652919660887e-4),
        ]

        self.sim.sources = [
            mp.Source(mp.GaussianSource(self.fcen, fwidth=self.df),
                      mp.Ey,
                      mp.Vector3(self.dpml + (-0.5 * self.sx)),
                      size=mp.Vector3(0, self.w))
        ]

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

        freg = mp.FluxRegion(center=mp.Vector3((0.5 * self.sx) - self.dpml -
                                               0.5),
                             size=mp.Vector3(0, 2 * self.w))

        trans = self.sim.add_flux(self.fcen,
                                  self.df,
                                  self.nfreq,
                                  freg,
                                  decimation_factor=1)

        self.sim.run(until_after_sources=mp.stop_when_fields_decayed(
            50, mp.Ey, mp.Vector3((0.5 * self.sx) - self.dpml - 0.5, 0), 1e-1))

        res = zip(mp.get_flux_freqs(trans), mp.get_fluxes(trans))

        tol = 1e-8 if mp.is_single_precision() else 1e-10
        for e, r in zip(expected, res):
            self.assertClose(e, r, epsilon=tol)
예제 #26
0
    def test_array_metadata(self):
        resolution = 25

        n = 3.4
        w = 1
        r = 1
        pad = 4
        dpml = 2

        sxy = 2 * (r + w + pad + dpml)
        cell_size = mp.Vector3(sxy, sxy)

        nonpml_vol = mp.Volume(mp.Vector3(),
                               size=mp.Vector3(sxy - 2 * dpml, sxy - 2 * dpml))

        geometry = [
            mp.Cylinder(radius=r + w, material=mp.Medium(index=n)),
            mp.Cylinder(radius=r)
        ]

        fcen = 0.118
        df = 0.08

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

        pml_layers = [mp.PML(dpml)]

        # CW source
        src = [
            mp.Source(mp.ContinuousSource(fcen, fwidth=df), mp.Ez,
                      mp.Vector3(r + 0.1)),
            mp.Source(mp.ContinuousSource(fcen, fwidth=df),
                      mp.Ez,
                      mp.Vector3(-(r + 0.1)),
                      amplitude=-1)
        ]

        sim = mp.Simulation(cell_size=cell_size,
                            geometry=geometry,
                            sources=src,
                            resolution=resolution,
                            force_complex_fields=True,
                            symmetries=symmetries,
                            boundary_layers=pml_layers)

        sim.init_sim()
        sim.solve_cw(1e-5 if mp.is_single_precision() else 1e-6, 1000, 10)

        def electric_energy(r, ez, eps):
            return np.real(eps * np.conj(ez) * ez)

        def vec_func(r):
            return r.x**2 + 2 * r.y**2

        electric_energy_total = sim.integrate_field_function(
            [mp.Ez, mp.Dielectric], electric_energy, nonpml_vol)
        electric_energy_max = sim.max_abs_field_function(
            [mp.Ez, mp.Dielectric], electric_energy, nonpml_vol)
        vec_func_total = sim.integrate_field_function([], vec_func, nonpml_vol)
        cw_modal_volume = (electric_energy_total /
                           electric_energy_max) * vec_func_total

        sim.reset_meep()

        # pulsed source
        src = [
            mp.Source(mp.GaussianSource(fcen, fwidth=df), mp.Ez,
                      mp.Vector3(r + 0.1)),
            mp.Source(mp.GaussianSource(fcen, fwidth=df),
                      mp.Ez,
                      mp.Vector3(-(r + 0.1)),
                      amplitude=-1)
        ]

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

        dft_obj = sim.add_dft_fields([mp.Ez], fcen, 0, 1, where=nonpml_vol)
        sim.run(until_after_sources=100)

        Ez = sim.get_dft_array(dft_obj, mp.Ez, 0)
        (X, Y, Z, W) = sim.get_array_metadata(dft_cell=dft_obj)
        Eps = sim.get_array(vol=nonpml_vol, component=mp.Dielectric)
        EpsE2 = np.real(Eps * np.conj(Ez) * Ez)
        xm, ym = np.meshgrid(X, Y)
        vec_func_sum = np.sum(W * (xm**2 + 2 * ym**2))
        pulse_modal_volume = np.sum(W * EpsE2) / np.max(EpsE2) * vec_func_sum

        tol = 5e-2 if mp.is_single_precision() else 1e-2
        self.assertClose(cw_modal_volume / pulse_modal_volume,
                         1.0,
                         epsilon=tol)
예제 #27
0
]
resolution = 200
wvl = 825 / 1000  #convert args.wvl from nm to μm
fcen = 1 / wvl
df = 0
nfreq = 1
print("wavelength =", wvl, "μm")
print("center frequency =", fcen, "1/μm")

source = [
    mp.Source(mp.GaussianSource(fcen, df, nfreq),
              component=mp.Ey,
              center=mp.Vector3(0, -0.705, 0))
]

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

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

pt = mp.Vector3(0, -0.705, 0)

sim.run(mp.dft_ldos(fcen, 0, nfreq),
        until_after_sources=mp.stop_when_fields_decayed(20, mp.Ey, pt, 1e-3))
eps_data = sim.get_array(center=mp.Vector3(),
                         size=cell,
                         component=mp.Dielectric)
ey_data = sim.get_array(center=mp.Vector3(), size=cell, component=mp.Ey)
예제 #28
0
def main(args):

    resolution = args.res

    w1 = 1  # width of waveguide 1
    w2 = args.w2  # width of waveguide 2
    Lw = 10  # length of waveguide 1 and 2
    Lt = args.Lt  # taper length

    Si = mp.Medium(epsilon=12.0)

    dair = 3.0
    dpml = 3.0

    sx = dpml + Lw + Lt + Lw + dpml
    sy = dpml + dair + w2 + dair + dpml
    cell_size = mp.Vector3(sx, sy, 0)

    geometry = [
        mp.Block(material=Si,
                 center=mp.Vector3(0, 0, 0),
                 size=mp.Vector3(mp.inf, w1, mp.inf)),
        mp.Block(material=Si,
                 center=mp.Vector3(0.5 * sx - 0.5 * (Lt + Lw + dpml), 0, 0),
                 size=mp.Vector3(Lt + Lw + dpml, w2, mp.inf))
    ]

    # form linear taper

    hh = w2
    ww = 2 * Lt

    # taper angle (CCW, relative to +X axis)
    rot_theta = math.atan(0.5 * (w2 - w1) / Lt)

    pvec = mp.Vector3(-0.5 * sx + dpml + Lw, 0.5 * w1, 0)
    cvec = mp.Vector3(-0.5 * sx + dpml + Lw + 0.5 * ww, 0.5 * hh + 0.5 * w1, 0)
    rvec = cvec - pvec
    rrvec = rvec.rotate(mp.Vector3(0, 0, 1), rot_theta)

    geometry.append(
        mp.Block(material=mp.air,
                 center=pvec + rrvec,
                 size=mp.Vector3(ww, hh, mp.inf),
                 e1=mp.Vector3(1, 0, 0).rotate(mp.Vector3(0, 0, 1), rot_theta),
                 e2=mp.Vector3(0, 1, 0).rotate(mp.Vector3(0, 0, 1), rot_theta),
                 e3=mp.Vector3(0, 0, 1)))

    pvec = mp.Vector3(-0.5 * sx + dpml + Lw, -0.5 * w1, 0)
    cvec = mp.Vector3(-0.5 * sx + dpml + Lw + 0.5 * ww, -(0.5 * hh + 0.5 * w1),
                      0)
    rvec = cvec - pvec
    rrvec = rvec.rotate(mp.Vector3(0, 0, 1), -rot_theta)

    geometry.append(
        mp.Block(material=mp.air,
                 center=pvec + rrvec,
                 size=mp.Vector3(ww, hh, mp.inf),
                 e1=mp.Vector3(1, 0, 0).rotate(mp.Vector3(0, 0, 1),
                                               -rot_theta),
                 e2=mp.Vector3(0, 1, 0).rotate(mp.Vector3(0, 0, 1),
                                               -rot_theta),
                 e3=mp.Vector3(0, 0, 1)))

    boundary_layers = [mp.PML(dpml)]

    # mode frequency
    fcen = 0.15

    sources = [
        mp.EigenModeSource(src=mp.GaussianSource(fcen, fwidth=0.5 * fcen),
                           component=mp.Ez,
                           size=mp.Vector3(0, sy - 2 * dpml, 0),
                           center=mp.Vector3(-0.5 * sx + dpml, 0, 0),
                           eig_match_freq=True,
                           eig_parity=mp.ODD_Z,
                           eig_kpoint=mp.Vector3(0.4, 0, 0),
                           eig_resolution=32)
    ]

    symmetries = [mp.Mirror(mp.Y, +1)]

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

    xm = -0.5 * sx + dpml + 0.5 * Lw  # x-coordinate of monitor
    mflux = sim.add_eigenmode(
        fcen, 0, 1,
        mp.FluxRegion(center=mp.Vector3(xm, 0),
                      size=mp.Vector3(0, sy - 2 * dpml)))

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

    bands = [1]  # indices of modes for which to compute expansion coefficients
    alpha = sim.get_eigenmode_coefficients(mflux, bands)

    alpha0Plus = alpha[2 * 0 +
                       0]  # coefficient of forward-traveling fundamental mode
    alpha0Minus = alpha[
        2 * 0 + 1]  # coefficient of backward-traveling fundamental mode

    print("refl:, {}, {:.8f}".format(Lt, abs(alpha0Minus)**2))
예제 #29
0
def main(args):
    sx = 8.0  #spatial extent along x including pmls (μm)
    sy = 4
    sz = 0
    dpml = 1.0
    cell = mp.Vector3(sx, sy, sz)
    pml_layers = [mp.PML(dpml)]
    resolution = args.res
    wvl = args.wvl  #source wavelength
    fcen = 1 / wvl  #center frequency
    df = 0  #frequency bandwidth
    nfreq = 1  #number of frequencies
    dw = args.dw  #  slab thickness increment(um)
    w_init = args.w_init  # initial slab thickness(μm)
    n = args.n
    w = w_init + n * dw  #next slab thicknessw
    slab_center_y = 0.5 * w  #slab center y coordinate
    sfor_y = w + 0.005  #sfor_y = y coordinate of the slit_flux_output_region
    s = 0.030  #slit width
    print("wavelength =", wvl, "μm")
    print("slab size =", w, "μm")
    print("center frequency =", fcen, "1/μm")
    print("slit_flux_output_region y coordinate =", sfor_y, "μm")
    print("slab center y coordinate =", slab_center_y, "μm")

    geometry = [
        mp.Block(mp.Vector3(mp.inf, w, mp.inf),
                 center=mp.Vector3(0, slab_center_y),
                 material=Ag)
    ]
    source = [
        mp.Source(mp.GaussianSource(fcen, df, nfreq),
                  component=mp.Ex,
                  center=mp.Vector3(0, -0.5 * (sy - 2.1), 0),
                  size=mp.Vector3(sx - 2.0, 0, 0))
    ]
    symmetries = [mp.Mirror(mp.X), mp.Mirror(mp.Z)]
    sim = mp.Simulation(cell_size=cell,
                        geometry=geometry,
                        sources=source,
                        resolution=resolution,
                        boundary_layers=pml_layers,
                        filename_prefix='slab_noslit')
    sim.use_output_directory()

    pt = mp.Vector3(
        0, -0.5 * (sy - 2.1), 0
    )  #point where field intensity is measured (usually at source position)

    slab_flux_in_region = mp.FluxRegion(
        center=mp.Vector3(0, -0.005, 0),
        size=mp.Vector3(sx, 0, 0))  #incident flux monitor 5nm above slab.
    slab_flux_in = sim.add_flux(fcen, df, nfreq, slab_flux_in_region)
    slab_flux_in_data = sim.get_flux_data(
        slab_flux_in)  #data are the E and H fields used to calculate S=ExH
    slab_flux_out_region = mp.FluxRegion(
        center=mp.Vector3(0, sfor_y, 0),
        size=mp.Vector3(sx, 0, 0))  #trans flux monitor 5nm below slab.
    slab_flux_out = sim.add_flux(fcen, df, nfreq, slab_flux_out_region)
    slab_flux_out_data = sim.get_flux_data(slab_flux_out)

    sim.run(mp.dft_ldos(fcen, df, nfreq),
            mp.at_beginning(mp.output_epsilon),
            until_after_sources=mp.stop_when_fields_decayed(
                10, mp.Hz, pt, 1e-5))

    slab_flux_input = []
    slab_flux_output = []
    slab_flux_input = mp.get_fluxes(slab_flux_in)
    slab_flux_output = mp.get_fluxes(slab_flux_out)

    print('incident flux slab =', slab_flux_input, ' ',
          'transmitted flux slab =', slab_flux_output, ' ',
          'normed transmitted flux=',
          np.divide(slab_flux_output, slab_flux_input))

    eps_data_slab = sim.get_array(center=mp.Vector3(0, 0, 0),
                                  size=mp.Vector3(sx, sy, sz),
                                  component=mp.Dielectric)
    ex_data_slab = sim.get_array(center=mp.Vector3(0, 0, 0),
                                 size=mp.Vector3(sx, sy, sz),
                                 component=mp.Ex)
    hz_data_slab = sim.get_array(center=mp.Vector3(0, 0, 0),
                                 size=mp.Vector3(sx, sy, sz),
                                 component=mp.Hz)

    sim.reset_meep()

    geometry = [
        mp.Block(mp.Vector3(mp.inf, w, mp.inf),
                 center=mp.Vector3(0, 0.5 * (w)),
                 material=Ag),
        mp.Block(mp.Vector3(s, w, 0),
                 center=mp.Vector3(0, 0.5 * (w), 0),
                 material=mp.Medium(epsilon=1))
    ]

    sim = mp.Simulation(cell_size=cell,
                        geometry=geometry,
                        sources=source,
                        resolution=resolution,
                        boundary_layers=pml_layers,
                        filename_prefix="slab_slit")
    sim.use_output_directory()

    slit_flux_in_region = mp.FluxRegion(center=mp.Vector3(0, -0.005, 0),
                                        size=mp.Vector3(
                                            sx, 0,
                                            0))  #same as slab_flux_in_region
    slit_flux_in = sim.add_flux(fcen, df, nfreq, slit_flux_in_region)
    slit_flux_in_data = sim.get_flux_data(slit_flux_in)
    slit_flux_out_region = mp.FluxRegion(center=mp.Vector3(0, w + 0.005, 0),
                                         size=mp.Vector3(
                                             sx, 0,
                                             0))  #same as slab_flux_out_region
    slit_flux_out = sim.add_flux(fcen, df, nfreq, slit_flux_out_region)
    slit_flux_out_data = sim.get_flux_data(slit_flux_out)

    sim.load_minus_flux_data(slit_flux_out, slab_flux_out_data)
    #subract  transmitted slab flux data (slab_flux_out_data) from slit_flux_out.  This is a correction so that flux only
    #from the slit is registered in slit_flux_out.

    sim.run(mp.dft_ldos(fcen, 0, nfreq),
            mp.at_beginning(mp.output_epsilon),
            until_after_sources=mp.stop_when_fields_decayed(
                10, mp.Hz, pt, 1e-4))

    slit_flux_input = []
    slit_flux_output = []
    slit_flux_input = mp.get_fluxes(slit_flux_in)
    slit_flux_output = mp.get_fluxes(slit_flux_out)
    print('slit flux net =', slit_flux_output, '  ', 'slit_flux_normed =',
          np.divide(slit_flux_output, slab_flux_input))
    eps_data_slit = sim.get_array(center=mp.Vector3(0, 0, 0),
                                  size=mp.Vector3(sx, sy, sz),
                                  component=mp.Dielectric)
    ex_data_slit = sim.get_array(center=mp.Vector3(0, 0, 0),
                                 size=mp.Vector3(sx, sy, sz),
                                 component=mp.Ex)
    hz_data_slit = sim.get_array(center=mp.Vector3(0, 0, 0),
                                 size=mp.Vector3(sx, sy, sz),
                                 component=mp.Hz)

    slabFlux = []
    slabFlux = np.append(slabFlux, slab_flux_input)
    slitFlux = []
    slitFlux = np.append(slitFlux, slit_flux_output)
    fracFlux = np.divide(slitFlux, slabFlux)
    print('normalised slit flux,',
          end=" ")  #suppress the print newline function with end=" "
    np.savetxt(
        sys.stdout, fracFlux, fmt='%7.5f'
    )  #print to stdout transmitted slit flux normalised to input flux.
    print('slab thickness,', end=" ")
    print(w)

    #-------------------------------- Next three lines ok for data file in mp meep, but writes data np times (np no. processors) in pmp.
    #f=open('fracFL.dat','ab')
    #np.savetxt(f,fracFl,fmt='%6.5f')
    #f.close()
    #----------------------------------------------------

    eps_data_slit = sim.get_array(center=mp.Vector3(0, 0, 0),
                                  size=mp.Vector3(sx, sy, sz),
                                  component=mp.Dielectric)
    hz_data_slit = sim.get_array(center=mp.Vector3(0, 0, 0),
                                 size=mp.Vector3(sx, sy, sz),
                                 component=mp.Hz)
    hz_scat = hz_data_slit - hz_data_slab
예제 #30
0
def parallel_waveguide(s, xodd):
    geometry = [
        mp.Block(center=mp.Vector3(-0.5 * (s + a)),
                 size=mp.Vector3(a, a, mp.inf),
                 material=Si),
        mp.Block(center=mp.Vector3(0.5 * (s + a)),
                 size=mp.Vector3(a, a, mp.inf),
                 material=Si)
    ]

    symmetries = [
        mp.Mirror(mp.X, phase=-1.0 if xodd else 1.0),
        mp.Mirror(mp.Y, phase=-1.0)
    ]

    sources = [
        mp.Source(src=mp.GaussianSource(fcen, fwidth=df),
                  component=mp.Ey,
                  center=mp.Vector3(-0.5 * (s + a)),
                  size=mp.Vector3(a, a)),
        mp.Source(src=mp.GaussianSource(fcen, fwidth=df),
                  component=mp.Ey,
                  center=mp.Vector3(0.5 * (s + a)),
                  size=mp.Vector3(a, a),
                  amplitude=-1.0 if xodd else 1.0)
    ]

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

    h = mp.Harminv(mp.Ey, mp.Vector3(0.5 * (s + a)), fcen, df)

    sim.run(mp.after_sources(h), until_after_sources=200)

    f = h.modes[0].freq
    print("freq:, {}, {}".format(s, f))

    sim.reset_meep()

    eig_sources = [
        mp.EigenModeSource(src=mp.GaussianSource(f, fwidth=df),
                           size=mp.Vector3(a, a),
                           center=mp.Vector3(-0.5 * (s + a)),
                           direction=mp.Z,
                           eig_kpoint=k_point,
                           eig_match_freq=True,
                           eig_parity=mp.ODD_Y),
        mp.EigenModeSource(src=mp.GaussianSource(f, fwidth=df),
                           size=mp.Vector3(a, a),
                           center=mp.Vector3(0.5 * (s + a)),
                           direction=mp.Z,
                           eig_kpoint=k_point,
                           eig_match_freq=True,
                           eig_parity=mp.ODD_Y,
                           amplitude=-1.0 if xodd else 1.0)
    ]

    sim.change_sources(eig_sources)

    flux_reg = mp.FluxRegion(direction=mp.Z,
                             center=mp.Vector3(),
                             size=mp.Vector3(1.2 * (2 * a + s), 1.2 * a))
    wvg_flux = sim.add_flux(f, 0, 1, flux_reg)

    force_reg1 = mp.ForceRegion(mp.Vector3(0.5 * s),
                                direction=mp.X,
                                weight=1.0,
                                size=mp.Vector3(y=a))
    force_reg2 = mp.ForceRegion(mp.Vector3(0.5 * s + a),
                                direction=mp.X,
                                weight=-1.0,
                                size=mp.Vector3(y=a))
    wvg_force = sim.add_force(f, 0, 1, force_reg1, force_reg2)

    sim.run(until_after_sources=500)

    flux = mp.get_fluxes(wvg_flux)[0]
    force = mp.get_forces(wvg_force)[0]

    sim.reset_meep()
    return flux, force