コード例 #1
0
ファイル: simulation.py プロジェクト: ahmed-shafqat/meep
    def test_get_array_output(self):
        sim = self.init_simple_simulation()
        sim.symmetries = []
        sim.geometry = [mp.Cylinder(0.2, material=mp.Medium(index=3))]
        sim.filename_prefix = 'test_get_array_output'
        sim.run(until=20)

        mp.output_epsilon(sim)
        mp.output_efield_z(sim)
        mp.output_tot_pwr(sim)
        mp.output_efield(sim)

        eps_arr = sim.get_epsilon()
        efield_z_arr = sim.get_efield_z()
        energy_arr = sim.get_tot_pwr()
        efield_arr = sim.get_efield()

        fname_fmt = "test_get_array_output-{}-000020.00.h5"

        with h5py.File(fname_fmt.format('eps'), 'r') as f:
            eps = f['eps'].value

        with h5py.File(fname_fmt.format('ez'), 'r') as f:
            efield_z = f['ez'].value

        with h5py.File(fname_fmt.format('energy'), 'r') as f:
            energy = f['energy'].value

        with h5py.File(fname_fmt.format('e'), 'r') as f:
            ex = f['ex'].value
            ey = f['ey'].value
            ez = f['ez'].value
            efield = np.stack([ex, ey, ez], axis=-1)

        np.testing.assert_allclose(eps, eps_arr)
        np.testing.assert_allclose(efield_z, efield_z_arr)
        np.testing.assert_allclose(energy, energy_arr)
        np.testing.assert_allclose(efield, efield_arr)
コード例 #2
0
    def test_load_dump_structure(self):
        resolution = 10
        cell = mp.Vector3(10, 10)
        pml_layers = mp.PML(1.0)
        fcen = 1.0
        df = 1.0
        sources = mp.Source(src=mp.GaussianSource(fcen, fwidth=df),
                            center=mp.Vector3(),
                            component=mp.Hz)
        geometry = mp.Cylinder(0.2, material=mp.Medium(index=3))

        sim = mp.Simulation(resolution=resolution,
                            cell_size=cell,
                            default_material=mp.Medium(index=1),
                            geometry=[geometry],
                            boundary_layers=[pml_layers],
                            sources=[sources])

        sim.run(until=200)
        ref_field = sim.get_field_point(mp.Hz, mp.Vector3(z=2))
        dump_fn = 'test_load_dump_structure.h5'
        sim.dump_structure(dump_fn)

        sim = mp.Simulation(resolution=resolution,
                            cell_size=cell,
                            default_material=mp.Medium(index=1),
                            geometry=[],
                            boundary_layers=[pml_layers],
                            sources=[sources],
                            load_structure=dump_fn)
        sim.run(until=200)
        field = sim.get_field_point(mp.Hz, mp.Vector3(z=2))

        self.assertAlmostEqual(ref_field, field)

        mp.all_wait()
        if mp.am_master():
            os.remove(dump_fn)
コード例 #3
0
ファイル: mpb.py プロジェクト: fesc3555/meep
    def init_solver(self, geom=True):
        num_bands = 8
        k_points = [
            mp.Vector3(),
            mp.Vector3(0.5),
            mp.Vector3(0.5, 0.5),
            mp.Vector3()
        ]

        geometry = [mp.Cylinder(0.2, material=mp.Medium(
            epsilon=12))] if geom else []
        k_points = mp.interpolate(4, k_points)
        geometry_lattice = mp.Lattice(size=mp.Vector3(1, 1))
        resolution = 32

        return mpb.ModeSolver(num_bands=num_bands,
                              k_points=k_points,
                              geometry=geometry,
                              geometry_lattice=geometry_lattice,
                              resolution=resolution,
                              filename_prefix=self.filename_prefix,
                              deterministic=True,
                              tolerance=1e-12)
コード例 #4
0
    def test_set_materials(self):

        def change_geom(sim):
            t = sim.meep_time()
            fn = t * 0.02
            geom = [mp.Cylinder(radius=3, material=mp.Medium(index=3.5), center=mp.Vector3(fn, fn)),
                    mp.Ellipsoid(size=mp.Vector3(1, 2, mp.inf), center=mp.Vector3(fn, fn))]

            sim.set_materials(geometry=geom)

        c = mp.Cylinder(radius=3, material=mp.Medium(index=3.5))
        e = mp.Ellipsoid(size=mp.Vector3(1, 2, mp.inf))

        sources = mp.Source(src=mp.GaussianSource(1, fwidth=0.1), component=mp.Hz, center=mp.Vector3())
        symmetries = [mp.Mirror(mp.X, -1), mp.Mirror(mp.Y, -1)]

        sim = mp.Simulation(cell_size=mp.Vector3(10, 10),
                            geometry=[c, e],
                            boundary_layers=[mp.PML(1.0)],
                            sources=[sources],
                            symmetries=symmetries,
                            resolution=16)

        eps = {'arr1': None, 'arr2': None}

        def get_arr1(sim):
            eps['arr1'] = sim.get_array(mp.Volume(mp.Vector3(), mp.Vector3(10, 10)),
                                        component=mp.Dielectric)

        def get_arr2(sim):
            eps['arr2'] = sim.get_array(mp.Volume(mp.Vector3(), mp.Vector3(10, 10)),
                                        component=mp.Dielectric)

        sim.run(mp.at_time(50, get_arr1), mp.at_time(100, change_geom),
                mp.at_end(get_arr2), until=200)

        self.assertFalse(np.array_equal(eps['arr1'], eps['arr2']))
コード例 #5
0
    def test_geometric_objects_duplicates(self):
        rad = 1
        s = mp.Sphere(rad)
        c = mp.Cylinder(rad)

        res = mp.geometric_objects_duplicates(mp.Vector3(1, 1, 1), 1, 5, [s, c])

        expected = [
            mp.Sphere(rad, center=mp.Vector3(5, 5, 5)),
            mp.Sphere(rad, center=mp.Vector3(4, 4, 4)),
            mp.Sphere(rad, center=mp.Vector3(3, 3, 3)),
            mp.Sphere(rad, center=mp.Vector3(2, 2, 2)),
            mp.Sphere(rad, center=mp.Vector3(1, 1, 1)),
            mp.Cylinder(rad, center=mp.Vector3(5, 5, 5)),
            mp.Cylinder(rad, center=mp.Vector3(4, 4, 4)),
            mp.Cylinder(rad, center=mp.Vector3(3, 3, 3)),
            mp.Cylinder(rad, center=mp.Vector3(2, 2, 2)),
            mp.Cylinder(rad, center=mp.Vector3(1, 1, 1)),
        ]
        for r, e in zip(res, expected):
            self.assertEqual(r.center, e.center)
コード例 #6
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'])
コード例 #7
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(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))))

    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
コード例 #8
0
    pt = mp.Vector3(0.5 * cxs - pmlsize - 0.5)

    sim.run(
        until_after_sources=mp.stop_when_fields_decayed(50, mp.Ez, pt, 1e-3))

    # for normalization run, save flux fields data for reflection plane
    straight_refl_data = sim.get_flux_data(refl)

    # save incident power for transmission plane
    straight_tran_flux = mp.get_fluxes(tran)
    print(straight_tran_flux)
    sim.reset_meep()
    geometry = [
        mp.Cylinder(material=mp.Medium(index=6.9),
                    radius=r,
                    center=mp.Vector3(0, 0, 0))
    ]

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

    refl = sim.add_flux(1 / cwl, 1 / ww, nfreq, refl_fr)

    tran_fr = mp.FluxRegion(center=mp.Vector3(0.5 * cxs - pmlsize - 0.5, 0, 0),
                            size=mp.Vector3(0, 2 * r, 0))
    tran = sim.add_flux(1 / cwl, 1 / ww, nfreq, tran_fr)
コード例 #9
0
d = 1.4                            # defect spacing (ordinary spacing = 1)
N = 3                              # number of holes on either side of defect

# size of cell in y direction (perpendicular to wvg.)
sy = 6
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)

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 = 20

fcen = 0.25                        # pulse center frequency
df = 0.2                           # pulse width (in frequency)

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
コード例 #10
0
ファイル: solve-cw.py プロジェクト: tnakaicode/PlotGallery

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

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

pml_layers = [mp.PML(dpml)]

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

src = [mp.Source(mp.ContinuousSource(fcen),
                 component=mp.Ez,
                 center=mp.Vector3(r+0.1)),
       mp.Source(mp.ContinuousSource(fcen),
                 component=mp.Ez,
                 center=mp.Vector3(-(r+0.1)),
                 amplitude=-1)]

symmetries = [mp.Mirror(mp.X,phase=-1),
              mp.Mirror(mp.Y,phase=+1)]
コード例 #11
0
ファイル: mpb_tutorial.py プロジェクト: davito0203/MEEP

# Our First Band Structure

print_heading("Square lattice of rods in air")

num_bands = 8
k_points = [
    mp.Vector3(),  # Gamma
    mp.Vector3(0.5),  # X
    mp.Vector3(0.5, 0.5),  # M
    mp.Vector3()
]  # Gamma

k_points = mp.interpolate(4, k_points)
geometry = [mp.Cylinder(0.2, material=mp.Medium(epsilon=12))]
geometry_lattice = mp.Lattice(size=mp.Vector3(1, 1))
resolution = 32

ms = mpb.ModeSolver(num_bands=num_bands,
                    k_points=k_points,
                    geometry=geometry,
                    geometry_lattice=geometry_lattice,
                    resolution=resolution)

print_heading("Square lattice of rods: TE bands")
ms.run_te()

print_heading("Square lattice of rods: TM bands")
ms.run_tm()
コード例 #12
0
import numpy as np
import meep as mp
import matplotlib.pyplot as plt

eps = 13
w = 1.2
r = 0.36

# cell dimensions
sy = 12
dpml = 1
# here the periodicity equals to 1
cell = mp.Vector3(1, sy)

b = mp.Block(size=mp.Vector3(mp.inf, w, mp.inf), material=mp.Medium(epsilon=eps))
c = mp.Cylinder(radius=r, material=mp.Medium(index=1))

resolution = 50

pml_layers = mp.PML(dpml, direction=mp.Y)

fcen = 0.8838
df = 0.1



# TODO:  why a Hz-polarized odd-symmetry modes (recalling the pseudovector subtlety discussed above) ???
sym = mp.Mirror(direction=mp.Y, phase=-1)

s = mp.Source(src=mp.GaussianSource(fcen, fwidth=df),
              size=mp.Vector3(1, 0, 0),
コード例 #13
0
    mp.Vector3(0.3, 0.0, 0.0),
    mp.Vector3(0.4, 0.0, 0.0),
    mp.Vector3(0.5, 0, 0),
    mp.Vector3(0.5, 0.1, 0.0),
    mp.Vector3(0.5, 0.2, 0.0),
    mp.Vector3(0.5, 0.3, 0.0),
    mp.Vector3(0.5, 0.4, 0.0),
    mp.Vector3(0.5, 0.5, 0),
    mp.Vector3(0.4, 0.4, 0.0),
    mp.Vector3(0.3, 0.3, 0.0),
    mp.Vector3(0.2, 0.2, 0.0),
    mp.Vector3(0.1, 0.1, 0.0),
    mp.Vector3(0, 0, 0)
]

geometry = [mp.Cylinder(0.2, material=mp.Medium(epsilon=12))]

geometry_lattice = mp.Lattice(size=mp.Vector3(1, 1))

resolution = 32

ms = mpb.ModeSolver(num_bands=num_bands,
                    k_points=k_points,
                    geometry=geometry,
                    geometry_lattice=geometry_lattice,
                    resolution=resolution)

#import sys
#sys.exit(0)

#print_heading("Square lattice of rods: TE bands")
コード例 #14
0
sy = 6  # 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)
pml_layers = mp.PML(dpml)

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(0.5 * d + i)))
    geometry.append(mp.Cylinder(r, center=mp.Vector3(-0.5 * d - i)))

fcen = 0.25  # pulse center frequency
df = 0.2  # pulse width (in frequency)

sources = mp.Source(src=mp.GaussianSource(fcen, fwidth=df),
                    component=mp.Hz,
                    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,
コード例 #15
0
ファイル: mpb_tri_holes.py プロジェクト: woodlee123/meep-1
    mp.Vector3(z=kz),               # Gamma
    mp.Vector3(0, 0.5, kz),         # M
    mp.Vector3(1 / -3, 1 / 3, kz),  # K
    mp.Vector3(z=kz)                # Gamma
]

k_interp = 4
k_points = mp.interpolate(k_interp, k_points)

# Now, define the geometry, etcetera:

eps = 12  # the dielectric constant of the background
r = 0.45  # the hole radius

default_material = mp.Medium(epsilon=eps)
geometry = [mp.Cylinder(r, material=mp.air)]

resolution = 32
num_bands = 8

ms = mpb.ModeSolver(
    geometry_lattice=geometry_lattice,
    geometry=geometry,
    k_points=k_points,
    default_material=default_material,
    resolution=resolution,
    num_bands=num_bands
)


def main():
コード例 #16
0
X, Y = np.meshgrid(x, y)
x = X.flatten()
y = Y.flatten()

theta = np.linspace(0, np.pi / 2, 9)
phi = np.linspace(0, 2 * np.pi, 9)

geometry = []
for i in range(9):
    axis = meep.Vector3(
        np.sin(theta[i]) * np.cos(phi[i]),
        np.sin(theta[i]) * np.sin(phi[i]), np.cos(theta[i]))
    geometry.append(
        meep.Cylinder(center=meep.Vector3(x[i], y[i], z[i]),
                      radius=radius,
                      height=height,
                      material=material,
                      axis=axis))

box = [2 * radius + 2 * np.max(x)] * 2 + [2 * radius + 2 * np.max(z)]
resolution = 1 / (4 * nm)
medium = meep.Medium(index=1)

fcen, df = meep_ext.freq_data(1 / (400 * nm), 1 / (1000 * nm))
nfreq = 40
polarization = 'x'

src_time = meep.GaussianSource(frequency=1.3 / um, fwidth=4.0 / um)
if polarization == 'x':
    source = lambda sim: meep_ext.x_polarized_plane_wave(sim, src_time)
    decay = meep.Ex
コード例 #17
0
    incedent = sim.add_flux(fcen, df, nfreq, incedent_fr)
    upperside = sim.add_flux(fcen, df, nfreq, upperside_fr)
    pt = mp.Vector3(0.5 * sx - dpml - 0.01, 0)
    sim.run(
        until_after_sources=mp.stop_when_fields_decayed(50, mp.Ez, pt, 1e-9))
    lightside_without_flux_data = sim.get_flux_data(lightside)
    upperside_without_flux_data = sim.get_flux_data(upperside)
    otherside_without_flux_data = sim.get_flux_data(otherside)
    indecentflux = np.append(indecentflux, mp.get_fluxes(incedent))
    a = mp.get_fluxes(otherside)
    #a=a[(74+12):(249-75+12)]
    otherside_without_flux = np.append(otherside_without_flux, a)
    upperside_without_flux = np.append(upperside_without_flux,
                                       mp.get_fluxes(upperside))
    sim.reset_meep()
    geometrys = [mp.Cylinder(material=Au, radius=r, center=mp.Vector3())]
    sim = mp.Simulation(cell_size=cell,
                        geometry=geometrys,
                        boundary_layers=pml_layers,
                        sources=sources,
                        resolution=resolution)

    lightside = sim.add_flux(fcen, df, nfreq, lightside_fr)
    upperside = sim.add_flux(fcen, df, nfreq, upperside_fr)
    otherside = sim.add_flux(fcen, df, nfreq, otherside_fr)
    #sim.load_minus_flux_data(otherside,otherside_without_flux_data)
    #sim.load_minus_flux_data(lightside,lightside_without_flux_data)
    #sim.load_minus_flux_data(upperside,upperside_without_flux_data)
    pt = mp.Vector3(0.5 * sx - dpml - 0.01, 0)
    sim.run(
        until_after_sources=mp.stop_when_fields_decayed(50, mp.Ez, pt, 1e-9))
コード例 #18
0
ファイル: mpb_tutorial.py プロジェクト: davito0203/MEEP
def first_tm_gap(r):
    ms.geometry = [mp.Cylinder(r, material=mp.Medium(epsilon=12))]
    ms.run_tm()
    return -1 * ms.retrieve_gap(1)
コード例 #19
0
ファイル: setup.py プロジェクト: xj361685640/topology-meep
eps_amor_5200 = 3.1978**2
eps_crys_5200 = 4.63**2

eps_si_1515 = 3.479**2
eps_amor_1515 = 3.334**2
eps_crys_1515 = 5.105**2
radius_percentage = 0.95

cell = mp.Vector3(sx, sy, 0)
geometry = []
for iterx in range(2 * Nx):
    for itery in range(2 * Ny):
        geometry += [
            mp.Cylinder(radius=r,
                        center=mp.Vector3((-Nx + iterx + 7 / 2) * a0 +
                                          1 / 3 * radius_percentage,
                                          (-Ny + itery + 1 / 2) * 3**0.5 * a0 +
                                          0 * radius_percentage),
                        material=mp.Medium(epsilon=eps_si_5200)),
            mp.Cylinder(radius=r,
                        center=mp.Vector3((-Nx + iterx + 7 / 2) * a0 +
                                          1 / 6 * radius_percentage,
                                          (-Ny + itery + 1 / 2) * 3**0.5 * a0 +
                                          3**0.5 / 6 * radius_percentage),
                        material=mp.Medium(epsilon=eps_si_5200)),
            mp.Cylinder(radius=r,
                        center=mp.Vector3((-Nx + iterx + 7 / 2) * a0 -
                                          1 / 6 * radius_percentage,
                                          (-Ny + itery + 1 / 2) * 3**0.5 * a0 +
                                          3**0.5 / 6 * radius_percentage),
                        material=mp.Medium(epsilon=eps_si_5200)),
            mp.Cylinder(radius=r,
コード例 #20
0
ファイル: array_metadata.py プロジェクト: zzzzz9527/meep
    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-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

        self.assertAlmostEqual(cw_modal_volume/pulse_modal_volume, 1.00, places=2)
コード例 #21
0
        #  cadmium selineid QD
        geometry.append(
            mp.Block(mp.Vector3(1, cell.z, cell.z),
                     center=mp.Vector3(-1),
                     material=mp.Medium(index=2.52)))

        numberof = int(cell.y // (2 * fingersize)) + 1

        for i in range(numberof):
            for j in range(numberof):
                geometry.append(
                    mp.Cylinder(height=1,
                                radius=fingersize / 2,
                                axis=mp.Vector3(1, 0, 0),
                                center=mp.Vector3(0,
                                                  (cell.y / 2) + fingersize -
                                                  (2 * fingersize) * (i + 1),
                                                  (cell.z / 2) + fingersize -
                                                  (2 * fingersize) * (j + 1)),
                                material=ZnO))

        sources = [
            mp.Source(mp.ContinuousSource(wavelength=0.550, end_time=10),
                      component=mp.Ez,
                      center=mp.Vector3(-1, 0, 0))
        ]

        sim = mp.Simulation(cell_size=cell,
                            k_point=mp.Vector3(),
                            boundary_layers=pml_layers,
                            geometry=geometry,
コード例 #22
0
def main(args):
    print("\nstart time:", datetime.now())

    # --------------------------------------------------------------------------
    # physical parameters characterizing light source and interface characteris-
    # tics (must be adjusted - eihter here or via command line interface (CLI))
    # --------------------------------------------------------------------------
    interface = args.interface
    s_pol = args.s_pol
    ref_medium = args.ref_medium

    n1 = args.n1
    n2 = args.n2

    kw_0 = args.kw_0
    kr_w = args.kr_w
    kr_c = args.kr_c

    # angle of incidence
    chi_deg = args.chi_deg
    #chi_deg = 1.0*Critical(n1, n2)
    #chi_deg = 0.95*Brewster(n1, n2)

    test_output = args.test_output

    # --------------------------------------------------------------------------
    # specific Meep parameters (may need to be adjusted)
    # --------------------------------------------------------------------------
    sx = 5   # size of cell including PML in x-direction
    sy = 5   # size of cell including PML in y-direction
    pml_thickness = 0.25   # thickness of PML layer
    freq = 12      # vacuum frequency of source (5 to 12 is good)
    runtime = 10   # runs simulation for 10 times freq periods

    # number of pixels per wavelength in the denser medium (at least 10,
    # 20 to 30 is a good choice)
    pixel = 10

    # source position with respect to the center (point of impact) in Meep
    # units (-2.15 good); if equal -r_w, then source position coincides with
    # waist position
    source_shift = -2.15

    # --------------------------------------------------------------------------
    # derived (Meep) parameters (do not change)
    # --------------------------------------------------------------------------
    k_vac = 2 * math.pi * freq
    k1 = n1 * k_vac
    n_ref = (1  if ref_medium == 0 else
             n1 if ref_medium == 1 else
             n2 if ref_medium == 2 else math.nan)
    r_w = kr_w / (n_ref * k_vac)
    w_0 = kw_0 / (n_ref * k_vac)
    r_c = kr_c / (n_ref * k_vac)
    shift = source_shift + r_w
    chi_rad = math.radians(chi_deg)

    params = dict(W_y=w_0, k=k1)

    # --------------------------------------------------------------------------
    # placement of the dielectric interface within the computational cell
    # --------------------------------------------------------------------------
    # helper functions
    def alpha(chi_rad):
        """Angle of inclined plane with y-axis in radians."""
        return math.pi/2 - chi_rad

    def Delta_x(alpha):
        """Inclined plane offset to the center of the cell."""
        sin_alpha = math.sin(alpha)
        cos_alpha = math.cos(alpha)
        return (sx/2) * (((math.sqrt(2) - cos_alpha) - sin_alpha) / sin_alpha)

    cell = mp.Vector3(sx, sy, 0)  # geometry-lattice

    if interface == "planar":
        default_material = mp.Medium(index=n1)
        # located at lower right edge for 45 degree
        geometry = [mp.Block(size=mp.Vector3(mp.inf, sx*math.sqrt(2), mp.inf),
                             center=mp.Vector3(+sx/2 + Delta_x(alpha(chi_rad)),
                                               -sy/2),
                             e1=mp.Vector3(1/math.tan(alpha(chi_rad)), 1, 0),
                             e2=mp.Vector3(-1, 1/math.tan(alpha(chi_rad)), 0),
                             e3=mp.Vector3(0, 0, 1),
                             material=mp.Medium(index=n2))]
    elif interface == "concave":
        default_material = mp.Medium(index=n2)
        # move center to the right in order to ensure that the point of impact
        # is always centrally placed
        geometry = [mp.Cylinder(center=mp.Vector3(-r_c*math.cos(chi_rad),
                                                  +r_c*math.sin(chi_rad)),
                                height=mp.inf,
                                radius=r_c,
                                material=mp.Medium(index=n1))]
    elif interface == "convex":
        default_material = mp.Medium(index=n1)
        # move center to the right in order to ensure that the point of impact
        # is always centrally placed
        geometry = [mp.Cylinder(center=mp.Vector3(+r_c*math.cos(chi_rad),
                                                  -r_c*math.sin(chi_rad)),
                                height=mp.inf,
                                radius=r_c,
                                material=mp.Medium(index=n2))]

    # --------------------------------------------------------------------------
    # add absorbing boundary conditions and discretize structure
    # --------------------------------------------------------------------------
    pml_layers = [mp.PML(pml_thickness)]
    resolution = pixel * (n1 if n1 > n2 else n2) * freq
    # set Courant factor (mandatory if either n1 or n2 is smaller than 1)
    Courant = (n1 if n1 < n2 else n2) / 2

    # --------------------------------------------------------------------------
    # beam profile distribution (field amplitude) at the waist of the beam
    # --------------------------------------------------------------------------
    def Gauss(r, params):
        """Gauss profile."""
        W_y = params['W_y']

        return math.exp(-(r.y / W_y)**2)

    # --------------------------------------------------------------------------
    # spectrum amplitude distribution
    # --------------------------------------------------------------------------
    def f_Gauss(k_y, params):
        """Gaussian spectrum amplitude."""
        W_y = params['W_y']

        return math.exp(-(k_y*W_y/2)**2)

    if test_output:
        print("Gauss spectrum:", f_Gauss(0.2, params))

    # --------------------------------------------------------------------------
    # plane wave decomposition
    # (purpose: calculate field amplitude at light source position if not
    #           coinciding with beam waist)
    # --------------------------------------------------------------------------
    def psi(r, x, params):
        """Field amplitude function."""
        try:
            getattr(psi, "called")
        except AttributeError:
            psi.called = True
            print("Calculating inital field configuration. "
                  "This will take some time...")

        def phase(k_y, x, y):
            """Phase function."""
            return x*math.sqrt(k1**2 - k_y**2) + k_y*y

        try:
            (result,
             real_tol,
             imag_tol) = complex_quad(lambda k_y:
                                      f_Gauss(k_y, params) *
                                      cmath.exp(1j*phase(k_y, x, r.y)),
                                      -k1, k1)
        except Exception as e:
            print(type(e).__name__ + ":", e)
            sys.exit()

        return result

    # --------------------------------------------------------------------------
    # some test outputs (uncomment if needed)
    # --------------------------------------------------------------------------
    if test_output:
        x, y, z = -2.15, 0.3, 0.5
        r = mp.Vector3(0, y, z)

        print()
        print("psi :", psi(r, x, params))
        sys.exit()

    # --------------------------------------------------------------------------
    # display values of physical variables
    # --------------------------------------------------------------------------
    print()
    print("Specified variables and derived values:")
    print("n1:", n1)
    print("n2:", n2)
    print("chi:  ", chi_deg, " [degree]")
    print("incl.:", 90 - chi_deg, " [degree]")
    print("kw_0: ", kw_0)
    if interface != "planar":
        print("kr_c: ", kr_c)
    print("kr_w: ", kr_w)
    print("k_vac:", k_vac)
    print("polarisation:", "s" if s_pol else "p")
    print("interface:", interface)
    print()

    # --------------------------------------------------------------------------
    # specify current source, output functions and run simulation
    # --------------------------------------------------------------------------
    force_complex_fields = False          # default: False
    eps_averaging = True                  # default: True
    filename_prefix = None

    sources = [mp.Source(src=mp.ContinuousSource(frequency=freq, width=0.5),
                         component=mp.Ez if s_pol else mp.Ey,
                         size=mp.Vector3(0, 2, 0),
                         center=mp.Vector3(source_shift, 0, 0),
                         #amp_func=lambda r: Gauss(r, params)
                         amp_func=lambda r: psi(r, shift, params)
                         )
               ]

    sim = mp.Simulation(cell_size=cell,
                        boundary_layers=pml_layers,
                        default_material=default_material,
                        Courant=Courant,
                        geometry=geometry,
                        sources=sources,
                        resolution=resolution,
                        force_complex_fields=force_complex_fields,
                        eps_averaging=eps_averaging,
                        filename_prefix=filename_prefix
                        )

    sim.use_output_directory(interface)  # put output files in a separate folder

    def eSquared(r, ex, ey, ez):
        """Calculate |E|^2.

        With |.| denoting the complex modulus if 'force_complex_fields?'
        is set to true, otherwise |.| gives the Euclidean norm.
        """
        return mp.Vector3(ex, ey, ez).norm()**2

    def output_efield2(sim):
        """Output E-field intensity."""
        name = "e2_s" if s_pol else "e2_p"
        func = eSquared
        cs = [mp.Ex, mp.Ey, mp.Ez]
        return sim.output_field_function(name, cs, func, real_only=True)

    sim.run(mp.at_beginning(mp.output_epsilon),
            mp.at_end(mp.output_efield_z if s_pol else mp.output_efield_y),
            mp.at_end(output_efield2),
            until=runtime)

    print("\nend time:", datetime.now())
コード例 #23
0
def main(args):
    sx = 3.0  #spatial extent along x including pmls (μm)
    sy = 3.0
    sz = 3.0
    dpml = 1.0

    cell = mp.Vector3(sx, sy, sy)
    pml_layers = [mp.PML(dpml)]
    geometry = [
        mp.Cylinder(center=mp.Vector3(0, 0, 0),
                    height=mp.inf,
                    radius=0.505,
                    axis=mp.Vector3(0, 0, 1),
                    material=Graph),
        mp.Cylinder(center=mp.Vector3(0, 0, 0),
                    height=mp.inf,
                    radius=0.5,
                    axis=mp.Vector3(0, 0, 1),
                    material=mp.Medium(epsilon=3.9))
    ]
    resolution = args.res
    wvlmax = 40
    fmin = 1 / 40
    wvlmin = 20
    fmax = 1 / 20
    wvl = args.wvl
    fcen = 1 / wvl
    df = fmax - fmin
    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.510, 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.510, 0)

    sim.run(mp.dft_ldos(fcen, df, 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)

    #plot eps_data

    plt.figure(dpi=160)
    plt.imshow(eps.data.transpose(), interpolation='spline36', cmap='binary')
    plt.axis('off')
    plt.show
コード例 #24
0



N = coupler_width//(circle_diameter+spacing_circles)
M = (coupler_length-spacing_circles)//(circle_diameter+spacing_circles)

geometry_circles = []
#matrices = np.zeros((int(N),int(M)))
matrices = np.ones((int(N),int(M)))
i=0
k=0
while (i<M):
    while (k<N):
        geometry_circles = geometry_circles + [mp.Cylinder(radius=circle_diameter/2, 
                                           center=mp.Vector3(-0.5*coupler_length+(i+1)*spacing_circles+circle_diameter*0.5+i*circle_diameter,
                                                             0.5*((N-1)*circle_diameter+(N-1)*spacing_circles)-k*(circle_diameter+spacing_circles),0),
                                           material=Si3N4_neff_TM if matrices[k][i]==1 else SiO2)]
        k = k+1
    i = i+1
    k=0


geometry = [mp.Block(size=mp.Vector3(mp.inf,waveguide_width,mp.inf),
                     center=mp.Vector3(),
                     material=Si3N4_neff_TM)]


# aqui define la fuente gaussiana, pensando en capturar el espectro
fcen = 1/0.632 # pulse center freq (es 1.58 para wavelength de 632nm )
df = 0.1*fcen    # pulse width freq
rot_angle = np.radians(0)
コード例 #25
0
n = 3.4  # index of waveguide
w = 1  # width of waveguide
r = 1  # inner radius of ring

pad = 4  # padding between waveguide and edge of PML
dpml = 2  # thickness of PML

sxy = 2 * (r + w + pad + dpml)  # cell size
cell = mp.Vector3(sxy, sxy)

# Create a ring waveguide by two overlapping cylinders - later objects
# take precedence over earlier objects, so we put the outer cylinder first.
# and the inner (air) cylinder second.
geometry = [
    mp.Cylinder(radius=r + w, height=mp.inf, material=mp.Medium(index=n)),
    mp.Cylinder(radius=r, height=mp.inf, material=mp.air)
]

pml_layers = [mp.PML(dpml)]
resolution = 20

# If we don't want to excite a specific mode symmetry, we can just
# put a single point source at some arbitrary place, pointing in some
# arbitrary direction.  We will only look for TM modes (E out of the plane).

fcen = 0.118  # pulse center frequency
df = 0.010  # pulse width (in frequency)
sources = [
    mp.Source(src=mp.GaussianSource(fcen, fwidth=df),
              component=mp.Ez,
コード例 #26
0
import meep as mp

cell_size = mp.Vector3(6, 6, 0)

geometry1 = [
    mp.Cylinder(center=mp.Vector3(), radius=1.0, material=mp.Medium(index=3.5))
]

sim1 = mp.Simulation(cell_size=cell_size, geometry=geometry1, resolution=20)

sim1.init_sim()

geometry2 = [
    mp.Cylinder(center=mp.Vector3(1, 1),
                radius=1.0,
                material=mp.Medium(index=3.5))
]

sim2 = mp.Simulation(cell_size=cell_size, geometry=geometry2, resolution=20)

sim2.init_sim()

sim1.fields.phase_in_material(sim2.structure, 10.0)

sim1.run(mp.at_beginning(mp.output_epsilon),
         mp.at_every(0.5, mp.output_epsilon),
         until=10)
コード例 #27
0
import meep as mp
import numpy as np
from numpy import linalg as LA
import matplotlib.pyplot as plt

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

sxy = 2 * (r + w + pad + dpml)
vol = mp.Volume(mp.Vector3(), size=mp.Vector3(sxy - 2 * dpml, sxy - 2 * dpml))

c1 = mp.Cylinder(radius=r + w, material=mp.Medium(index=n))
c2 = mp.Cylinder(radius=r)

fcen = 0.118
df = 0.08
src = [
    mp.Source(mp.ContinuousSource(fcen, fwidth=df),
              component=mp.Ez,
              center=mp.Vector3(r + 0.1))
]

sim = mp.Simulation(cell_size=mp.Vector3(sxy, sxy),
                    geometry=[c1, c2],
                    sources=src,
                    resolution=10,
                    force_complex_fields=True,
                    symmetries=[mp.Mirror(mp.Y)],
コード例 #28
0
ファイル: MPB_test.py プロジェクト: d-a-v/drive-meep-mad
resolution = 64

## Definition discretisation traits horizontaux
nbr_points_x = 4
nbr_points_y = 4

## Repere direct carree 45
geometry_lattice = mp.Lattice()
geometry_lattice.basis_size = mp.Vector3(1, 1, 1)
geometry_lattice.size = mp.Vector3(1, 1, 0)
geometry_lattice.basis1 = mp.Vector3(math.sqrt(2) / 2, -math.sqrt(2) / 2)
geometry_lattice.basis2 = mp.Vector3(math.sqrt(2) / 2, +math.sqrt(2) / 2)

## Definition motif
default_material = mp.Medium(index=n_hi)
C_0 = [mp.Cylinder(ra, material=mp.Medium(index=n_lo))]

## Limites IBZ REPERE RECIPROQUE
k_point_gamma = mp.Vector3(0, 0)
k_point_M_rec = mp.Vector3(1 / 2, 1 / 2)
k_point_K_rec = mp.Vector3(1 / 2, 0)
k_point_K_cart = mp.Vector3(math.sqrt(2) / 2, 0)
k_point_M_cart = mp.Vector3(math.sqrt(2) / 4, math.sqrt(2) / 4)

dk_x = (math.sqrt(2) / 2) / (nbr_points_x + 1)
dk_y = (math.sqrt(2) / 4) / (nbr_points_y + 1)

seg = []

for j in range(0, nbr_points_y + 2):
    k_point_gamma_dk_cart = k_point_gamma + mp.Vector3(0, j * dk_y)
コード例 #29
0
# rods (c.f. tri_rods.ctl), formed by a row of missing rods along the
# "x" direction.  (Here, "x" and "y" refer to the first and second
# basis directions.)  This structure supports a single guided band
# within the band gap, much like the analogous waveguide in a square
# lattice of rods (see "Photonic Crystals" by Joannopoulos et al.).

supercell_y = 7  # the (odd) number of lateral supercell periods

geometry_lattice = mp.Lattice(size=mp.Vector3(1, supercell_y),
                              basis1=mp.Vector3(math.sqrt(3) / 2, 0.5),
                              basis2=mp.Vector3(math.sqrt(3) / 2, -0.5))

eps = 12  # the dielectric constant of the rods
r = 0.2  # the rod radius in the bulk crystal

geometry = [mp.Cylinder(r, material=mp.Medium(epsilon=eps))]

# duplicate the bulk crystal rods over the supercell:
geometry = mp.geometric_objects_lattice_duplicates(geometry_lattice, geometry)

# add a rod of air, to erase a row of rods and form a waveguide:
geometry += [mp.Cylinder(r, material=mp.air)]

Gamma = mp.Vector3()
K_prime = mp.lattice_to_reciprocal(mp.Vector3(0.5),
                                   geometry_lattice)  # edge of Brillouin zone.
k_points = mp.interpolate(4, [Gamma, K_prime])

# the bigger the supercell, the more bands you need to compute to get
# to the defect modes (the lowest band is "folded" supercell_y times):
extra_bands = 5  # number of extra bands to compute above the gap
コード例 #30
0
def build_geom(sx, sy, dsub, gp, gh, lw, tr, br, sa, material):
    tw = gh / np.tan(
        sa * 2 * np.pi / 360)  # part to subtract from top of grating width
    a = (gh - tr) / np.tan(
        sa * 2 * np.pi / 360)  # intermediate for vertex calculation

    #vertices for trapezoids approximating grating cross-section
    vtx = [
        mp.Vector3(-0.5 * lw - 0.5 * a + gp / 2, -1 * (-0.5 * gh), 0),
        mp.Vector3(0.5 * lw + 0.5 * a + gp / 2, -1 * (-0.5 * gh), 0),
        mp.Vector3(0.5 * lw - 0.5 * a + gp / 2, -1 * (0.5 * gh - tr), 0),
        mp.Vector3(-0.5 * lw + 0.5 * a + gp / 2, -1 * (0.5 * gh - tr), 0)
    ]

    vtx2 = [
        mp.Vector3(-0.5 * lw - 0.5 * a - gp / 2, -1 * (-0.5 * gh), 0),
        mp.Vector3(0.5 * lw + 0.5 * a - gp / 2, -1 * (-0.5 * gh), 0),
        mp.Vector3(0.5 * lw - 0.5 * a - gp / 2, -1 * (0.5 * gh - tr), 0),
        mp.Vector3(-0.5 * lw + 0.5 * a - gp / 2, -1 * (0.5 * gh - tr), 0)
    ]

    #rounded corners for top of trapezoids
    c1 = mp.Cylinder(radius=tr,
                     height=mp.inf,
                     axis=mp.Vector3(0, 0, 1),
                     center=mp.Vector3(-gp / 2 - lw / 2 + tw / 2 + tr,
                                       -1 * (-sy / 2 + dsub + gh - tr), 0),
                     material=material)
    c2 = mp.Cylinder(radius=tr,
                     height=mp.inf,
                     axis=mp.Vector3(0, 0, 1),
                     center=mp.Vector3(-gp / 2 + lw / 2 - tw / 2 - tr,
                                       -1 * (-sy / 2 + dsub + gh - tr), 0),
                     material=material)
    c3 = mp.Cylinder(radius=tr,
                     height=mp.inf,
                     axis=mp.Vector3(0, 0, 1),
                     center=mp.Vector3(gp / 2 - lw / 2 + tw / 2 + tr,
                                       -1 * (-sy / 2 + dsub + gh - tr), 0),
                     material=material)
    c4 = mp.Cylinder(radius=tr,
                     height=mp.inf,
                     axis=mp.Vector3(0, 0, 1),
                     center=mp.Vector3(gp / 2 + lw / 2 - tw / 2 - tr,
                                       -1 * (-sy / 2 + dsub + gh - tr), 0),
                     material=material)

    #blocks for top of trapezoids inbetween rounded corners
    b1 = mp.Block(center=mp.Vector3(-gp / 2,
                                    -1 * (-sy / 2 + dsub + gh - tr / 2)),
                  size=mp.Vector3(lw - tw - 2 * tr, tr, mp.inf),
                  material=material)
    b2 = mp.Block(center=mp.Vector3(gp / 2,
                                    -1 * (-sy / 2 + dsub + gh - tr / 2)),
                  size=mp.Vector3(lw - tw - 2 * tr, tr, mp.inf),
                  material=material)

    #ellipsoid cutout to make bottom of grating round
    e1 = mp.Ellipsoid(center=mp.Vector3(0, -1 * (-sy / 2 + dsub), 0),
                      size=mp.Vector3(gp - lw - a, br, mp.inf),
                      material=mp.Medium(epsilon=1))
    e2 = mp.Ellipsoid(center=mp.Vector3(-gp, -1 * (-sy / 2 + dsub), 0),
                      size=mp.Vector3(gp - lw - a, br, mp.inf),
                      material=mp.Medium(epsilon=1))
    e3 = mp.Ellipsoid(center=mp.Vector3(gp, -1 * (-sy / 2 + dsub), 0),
                      size=mp.Vector3(gp - lw - a, br, mp.inf),
                      material=mp.Medium(epsilon=1))

    geometry = [
        mp.Block(material=material,
                 size=mp.Vector3(sx, dsub, mp.inf),
                 center=mp.Vector3(0, -1 * (-0.5 * sy + 0.5 * dsub), 0)),
        mp.Prism(vtx,
                 height=mp.inf,
                 center=mp.Vector3(0, -1 * (-0.5 * sy + dsub + 0.5 * gh), 0),
                 material=material),
        mp.Prism(vtx2,
                 height=mp.inf,
                 center=mp.Vector3(0, -1 * (-0.5 * sy + dsub + 0.5 * gh), 0),
                 material=material), c1, c2, c3, c4, b1, b2, e1, e2, e3
    ]

    return geometry