예제 #1
0
def _a_poly_tapering(geom=None, n_segments=20, material_holes=mp.vacuum):
    if geom is None:
         geom = []
    material_holes = index_to_material(material_holes)
    hx = 0.143
    hy = 0.315
    w = 0.65
    a_cen = 0.313
    a_mirror = 0.361
    Lx = 20
    _cavity = OneDLattice(Lx = Lx)
    _n_taper = 10
    h  = 0.25
    _cavity.polynomial_elliptical_hole_taper(_n_taper, hx, hy, w, a_cen, a_mirror )
    _cavity.apply_poly_spacing()
    print("--------------------------------------------------------------------------------------------------------")
    print(" Poly Tapering : hx = {}, hy = {}, w = {}, h= {}, a_cen  = {},  a_mirror = {}, n_taper = {}, Lx = {}".format(hx, hy,w, h, a_cen,a_mirror,_n_taper,Lx))
    print("--------------------------------------------------------------------------------------------------------")
#print(_cavity.coordinates)
    # cavity holes
    for x, y, z, hx, hy in _cavity.coordinates:
        # holes are completely filled with tuning material:
        geom.append(mp.Ellipsoid(material=material_holes,
                                         center=mp.Vector3(x, y, z),
                                         size=mp.Vector3(hx, hy, mp.inf)))

        geom.append(mp.Ellipsoid(material=material_holes,
                                         center=mp.Vector3(-x, y, z),
                                         size=mp.Vector3(hx, hy, mp.inf)))

    length = 2 * max(_cavity.coordinates[:, 0])

    return geom, length
예제 #2
0
def _a_tapering(geom=None, n_segments=20, material_holes=mp.vacuum):
    """
    Returns the geometry objects for a the air holes of 1D phc cavity with tapered lattice constants.
    TODO; allow change of resonant frequency to be able to make sweeps.
    """
    if geom is None:
        geom = []
    material_holes = index_to_material(material_holes)

    print(os.getcwd())

    _cavity = Lattice(Lx=n_segments)
    _n_taper = 10
    _cavity.polynomial_elliptical_hole_taper(_n_taper, 0.25, 0.25, 0.65, 0.349,
                                             0.4)
    _cavity.apply_poly_spacing()
    print(_cavity.coordinates)
    # cavity holes
    for x, y, z, hx, hy in _cavity.coordinates:
        # holes are completely filled with tuning material:
        geom.append(
            mp.Ellipsoid(material=material_holes,
                         center=mp.Vector3(x, y, z),
                         size=mp.Vector3(hx, hy, mp.inf)))

        geom.append(
            mp.Ellipsoid(material=material_holes,
                         center=mp.Vector3(-x, y, z),
                         size=mp.Vector3(hx, hy, mp.inf)))

    length = 2 * max(_cavity.coordinates[:, 0])

    return geom, length
예제 #3
0
def main():

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

    src_cmpt = mp.Hz
    sources = mp.Source(src=mp.GaussianSource(1, fwidth=0.1),
                        component=src_cmpt,
                        center=mp.Vector3())

    if src_cmpt == mp.Ez:
        symmetries = [mp.Mirror(mp.X), mp.Mirror(mp.Y)]

    if src_cmpt == mp.Hz:
        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=100)

    def print_stuff(sim_obj):
        v = mp.Vector3(4.13, 3.75, 0)
        p = sim.get_field_point(src_cmpt, v)
        print("t, Ez: {} {}+{}i".format(sim.round_time(), p.real, p.imag))

    sim.run(mp.at_beginning(mp.output_epsilon),
            mp.at_every(0.25, print_stuff),
            mp.at_end(print_stuff),
            mp.at_end(mp.output_efield_z),
            until=23)

    print("stopped at meep time = {}".format(sim.round_time()))
예제 #4
0
        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)
예제 #5
0
    def init(self):

        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=self.src_cmpt,
                            center=mp.Vector3())

        if self.src_cmpt == mp.Ez:
            symmetries = [mp.Mirror(mp.X), mp.Mirror(mp.Y)]

        if self.src_cmpt == mp.Hz:
            symmetries = [mp.Mirror(mp.X, -1), mp.Mirror(mp.Y, -1)]

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

        self.sim.use_output_directory(self.temp_dir)

        def print_stuff(sim_obj):
            v = mp.Vector3(4.13, 3.75, 0)
            p = self.sim.get_field_point(self.src_cmpt, v)
            print("t, Ez: {} {}+{}i".format(self.sim.round_time(), p.real,
                                            p.imag))

        self.print_stuff = print_stuff
예제 #6
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.Dielectric, mp.Volume(mp.Vector3(), mp.Vector3(10, 10)))

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

        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']))
예제 #7
0
def get_freqs_interpolate(hx=0.24, hy=0.24, a=0.33, wy=0.7, h=0.22):
    '''
    Useless 
    '''

    import meep as mp
    from meep import mpb

    mode = "zEyO"
    resolution = 20  # pixels/a, taken from simpetus example

    a = round(a, 3)  # units of um
    h = round(h, 3)  # units of um
    w = round(wy, 3)  # units of um
    hx = round(hx, 3)
    hy = round(hy, 3)

    h = h / a  # units of "a"
    w = w / a  # units of "a"
    hx = hx / a  # units of "a"
    hy = hy / a  # units of "a"

    nSi = 3.45
    Si = mp.Medium(index=nSi)

    geometry_lattice = mp.Lattice(size=mp.Vector3(
        1, 4, 4))  # dimensions of lattice taken from simpetus example

    geometry = [
        mp.Block(center=mp.Vector3(),
                 size=mp.Vector3(mp.inf, w, h),
                 material=Si),
        mp.Ellipsoid(material=mp.air,
                     center=mp.Vector3(),
                     size=mp.Vector3(hx, hy, mp.inf))
    ]

    num_k = 20  # from simpetus example, no. of k_points to evaluate the eigen frequency at
    k_points = mp.interpolate(
        num_k,
        [mp.Vector3(0, 0, 0), mp.Vector3(0.5, 0, 0)])

    num_bands = 2  # from simpetus example

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

    if mode == "te":

        ms.run_te()  # running for all modes and extracting parities

    if mode == "zEyO":

        ms.run_yodd_zeven()

    return ms.freqs
예제 #8
0
def get_freqs(hx=0.24, hy=0.24, a=0.33, w=0.7, h=0.22):
    '''
    Returns tuple of dielectric and air band edge frequencies for input parameters
    '''

    import meep as mp
    from meep import mpb

    res = 20
    mode = "zEyO"
    resolution = res  # pixels/a, taken from simpetus example

    a = round(a, 3)  # units of um
    h = round(h, 3)  # units of um
    w = round(w, 3)  # units of um
    hx = round(hx, 3)
    hy = round(hy, 3)

    h = h / a  # units of "a"
    w = w / a  # units of "a"
    hx = hx / a  # units of "a"
    hy = hy / a  # units of "a"

    nSi = 3.45
    Si = mp.Medium(index=nSi)

    geometry_lattice = mp.Lattice(size=mp.Vector3(
        1, 4, 4))  # dimensions of lattice taken from simpetus example

    geometry = [
        mp.Block(center=mp.Vector3(),
                 size=mp.Vector3(mp.inf, w, h),
                 material=Si),
        mp.Ellipsoid(material=mp.air,
                     center=mp.Vector3(),
                     size=mp.Vector3(hx, hy, mp.inf))
    ]

    k_points = [mp.Vector3(0.5, 0, 0)]
    num_bands = 2  # from simpetus example

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

    if mode == "te":

        ms.run_te()  # running for all modes and extracting parities

    if mode == "zEyO":

        ms.run_yodd_zeven()

    return ms.freqs
예제 #9
0
def _a_normal_tapering(geom=None, n_segments=20, material_holes=mp.vacuum):
     
    if geom is None:
        geom = []
    material_holes = index_to_material(material_holes)

    _cavity = OneDLattice(Lx = n_segments)
    _cavity.normal_spacing(a = 0.303, hx = 0.143, hy = 0.315)
    
    for x, y, z, hx, hy in _cavity.coordinates:
        # holes are completely filled with tuning material:
        geom.append(mp.Ellipsoid(material=material_holes,
                                         center=mp.Vector3(x, y, z),
                                         size=mp.Vector3(hx, hy, mp.inf)))
        geom.append(mp.Ellipsoid(material=material_holes,
                                         center=mp.Vector3(-x, y, z),
                                         size=mp.Vector3(hx, hy, mp.inf)))
    length = 10                             
    return geom, length
예제 #10
0
def get_freqs(hx, hy, a, w):

    wz = 0.22
    res = 20
    mode = "zEyO"
    resolution = res  # pixels/a, taken from simpetus example

    #     a = round(a,3)        # units of um
    #     h = round(wz, 3)         # units of um
    #     w = round(wy, 3)         # units of um
    #     hx = round(hx, 3)
    #     hy = round(hy, 3)
    h = wz
    h = h / a  # units of "a"
    w = w / a  # units of "a"
    hx = hx / a  # units of "a"
    hy = hy / a  # units of "a"

    nSi = 3.45
    Si = mp.Medium(index=nSi)

    geometry_lattice = mp.Lattice(size=mp.Vector3(
        1, 4, 4))  # dimensions of lattice taken from simpetus example

    geometry = [
        mp.Block(center=mp.Vector3(),
                 size=mp.Vector3(mp.inf, w, h),
                 material=Si),
        mp.Ellipsoid(material=mp.air,
                     center=mp.Vector3(),
                     size=mp.Vector3(hx, hy, mp.inf))
    ]

    k_points = [mp.Vector3(0.5, 0, 0)]
    num_bands = 2  # from simpetus example

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

    if mode == "te":

        ms.run_te()  # running for all modes and extracting parities

    if mode == "zEyO":

        ms.run_yodd_zeven()

    return ms.freqs
예제 #11
0
def quadratic_radius_1d_symmetric(n_segments=20,
                                  a=.33,
                                  hx=.21,
                                  hy=.21,
                                  h_rel=.7,
                                  z_center=0,
                                  d_tuning=0,
                                  material_holes=mp.vacuum):
    """
    Returns the geometry objects for a the air holes of 1D phc cavity with quadraticly tapered radii.

    TODO: change between Ellipsoids and Cylinders if hx==hy.
    """

    material_holes = index_to_material(material_holes)

    cavity = Lattice(n_segments)
    cavity.set_z(z_center)
    cavity.quadratic_hole_taper(h_rel)

    cavity_holes = []

    # cavity holes
    for x, y, z, hx, hy in cavity.coordinates:
        # holes are completely filled with tuning material:
        cavity_holes.append(
            mp.Ellipsoid(material=material_holes,
                         center=mp.Vector3(x, y, z),
                         size=mp.Vector3(hx, hy, mp.inf)))

        cavity_holes.append(
            mp.Ellipsoid(material=material_holes,
                         center=mp.Vector3(-x, y, z),
                         size=mp.Vector3(hx, hy, mp.inf)))

    length = 2 * max(cavity.coordinates[:, 0])

    return cavity_holes, length
예제 #12
0
def geo2D_ellipsoid_pc(n_matrix,
                       n_substrate,
                       film_xsize,
                       substrate_xsize,
                       film_ysize,
                       n_layers,
                       film_base_x,
                       ellipsex,
                       ellipsey,
                       ellipse_spacing,
                       layer_offset,
                       ellipse_x_offset=0):
    """
    Generate a layered structure with spheres. Within a layer the spheres are hexagonally packed
    """
    matrix_block = mp.Block(size=mp.Vector3(film_xsize, film_ysize, 1e20),
                            center=mp.Vector3(film_base_x - film_xsize / 2),
                            material=mp.Medium(epsilon=n_matrix**2))

    si_block = mp.Block(size=mp.Vector3(substrate_xsize, film_ysize, 1e20),
                        center=mp.Vector3(film_base_x + substrate_xsize / 2, 0,
                                          0),
                        material=mp.Medium(epsilon=n_substrate**2))

    print(n_substrate)

    spheres = [si_block, matrix_block]
    #spheres = []

    for n in range(n_layers):
        x = film_base_x - film_xsize * (n + 0.5) / n_layers + ellipse_x_offset
        offset = layer_offset[n]
        num_spheres = int(film_ysize / ellipse_spacing)
        sphere_layer = [
            mp.Ellipsoid(size=mp.Vector3(ellipsex, ellipsey, 1e20),
                         center=mp.Vector3(x, y + offset - film_ysize / 2, 0),
                         material=mp.Medium(epsilon=1))
            for y in np.linspace(0, film_ysize, num_spheres)
        ]
        spheres = spheres + sphere_layer

    return spheres
예제 #13
0
def _a_poly_tapering(geom=None, n_segments=20, material_holes=mp.vacuum):
    
    filename = "bandstructure_data/sweep_data.hdf5"
    
    hf = h5py.File(filename, 'r')
    gamma_data = np.array( hf.get("gamma"))
    freq_data = np.array( hf.get("freq"))
    hf.close()
    
    if geom is None:
         geom = []
            
    material_holes = index_to_material(material_holes)
    
    #--------------- These are the parameters for DESIGNED geometry, which we want to perturb ------------ #
               
    
    hx = 0.225
    hy = 0.4
    a_mirror = 0.414
    a_cen = 0.385
    w = 0.65
    h  = 0.19
    mode = "zEyO"
    
    substrate = True
    
    Lx = 20
    _n_taper = 10
    
    _cavity = OneDLattice(Lx = Lx)
    
    # ------------------------------ PERTURBATION HERE -------------------------------------------- #
    # Essentially how this works is that at the end of all the repetitive code, you get 4 values:
    # (1) lower_param : the value of the parameter that gives a resonant frequency slightly lower than the earlier one
    # (2) upper_param : the value of the parameter that gives a resonant frequency slightly higher than the earlier one
    # (3) a_mirror_new_lower : the new a_mirror that maximizes gamma for positive delta_freq and new hy/hx 
    # (4) a_mirror_new_upper : the new a_mirror that maximizes gamma for negative delta_freq and new hy/x
    
    to_perturb = "hx"            # one of hx, hy and a
    perturb_range = 0.04         # edges of the wavelength (in um) window will be (target_lambda +- perturb_range) 
    tol_Thz = 1                 # tolerance in Thz to select the perturbed segment parameters
    
    target_wvl = 1.54            # vaccum wavelength ( in um ) of the unperturbed cavity design
    target_f = 1/target_wvl
    target_f_Thz =  convert_freq_to_Thz(target_f)
    
    f_perturb_lower = 1 / (target_wvl + perturb_range )           # target_f - perturbation
    f_perturb_upper = 1 / (target_wvl - perturb_range )           # target_f + perturbation
    
    f_perturb_lower_Thz =  convert_freq_to_Thz(f_perturb_lower)
    f_perturb_upper_Thz =  convert_freq_to_Thz(f_perturb_upper)
    
    lower_param, upper_param = get_perturb_param(to_perturb = to_perturb , 
                                                 w = w,  a = a_cen,   hy = hy,  hx = hx , h =h, 
                                                 target_f_Thz= target_f_Thz, substrate = substrate,
                                                 f_perturb_lower_Thz= f_perturb_lower_Thz, 
                                                 f_perturb_upper_Thz= f_perturb_upper_Thz, tol_Thz = tol_Thz,
                                                 mode = mode)


    step_size = 0.004            # size of each of the n_steps
    n_step = 7                   # number of steps to search for the optimal gamma for the mirror segment
    
    a_mirror_new_lower, a_mirror_new_upper = get_mirror_param(to_perturb = to_perturb,
                                                             w = w,  a_mirror = a_mirror,   
                                                             hy = hy,  hx = hx , h = h,
                                                             target_f_Thz = target_f_Thz, 
                                                             f_perturb_lower_Thz = f_perturb_lower_Thz, 
                                                             f_perturb_upper_Thz = f_perturb_upper_Thz, 
                                                             mode = mode, substrate = substrate,
                                                             step_size = step_size, n_step = n_step,
                                                             lower_param = lower_param, upper_param = upper_param)

    
    # Here upper_param and lower_param correspond to the perturbed parameters that result in resonant 
    # frequencies of f_perturb_upper_Thz and f_perturb_lower_Thz respectively 
    
    # a_mirror_new_lower,a_mirror_new_upper refer to the new values of a_mirror that maximise gamma_mirror for
    # the the two ends of the perturbation window
    
    
    
    #----------------------------------------------------------------------------------------------------#
    
    _cavity.polynomial_elliptical_hole_taper(_n_taper, hx, hy, w, a_cen, a_mirror )
    _cavity.apply_poly_spacing()
    
    print("--------------------------------------------------------------------------------------------------------")
    print(" Poly Tapering : hx = {}, hy = {}, w = {}, h= {}, a_cen  = {},  a_mirror = {}, n_taper = {}, Lx = {}".format(hx, hy,w, h, a_cen,a_mirror,_n_taper,Lx))
    print("--------------------------------------------------------------------------------------------------------")

    # cavity holes
    for x, y, z, hx, hy in _cavity.coordinates:
        # holes are completely filled with tuning material:
        geom.append(mp.Ellipsoid(material=material_holes,
                                         center=mp.Vector3(x, y, z),
                                         size=mp.Vector3(hx, hy, mp.inf)))

        geom.append(mp.Ellipsoid(material=material_holes,
                                         center=mp.Vector3(-x, y, z),
                                         size=mp.Vector3(hx, hy, mp.inf)))

    length = 2 * max(_cavity.coordinates[:, 0])

    return geom, length
예제 #14
0
import meep as mp
import numpy as np
import math

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

geometry = [  #mp.Block(center=mp.Vector3(0,0,0), size=cell_size, material=mp.air),
    mp.Ellipsoid(material=mp.metal,
                 size=mp.Vector3(2, 0.5, 0.5),
                 e1=mp.Vector3(1, 1, 1),
                 e2=mp.Vector3(-1, 1, -1),
                 e3=mp.Vector3(-2, 1, 1))
]

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

sim.init_sim()

eps_data = sim.get_epsilon()
#eps_data = sim.get_array()

#sim.plot3D(eps_data)

#from mayavi import mlab
#s = mlab.contour3d()
#mlab.show()
#mlab.savefig(filename='test2.png')

from mayavi import mlab
s = mlab.contour3d(eps_data, colormap="hsv")
#mlab.show()
예제 #15
0
### Parameters
rx = 100 * nm
ry = 125 * nm
rz = 75 * nm

material = meep_ext.material.Au()
material = meep.Medium(index=3.5)

geometry = []
# axis = meep.Vector3(np.sin(theta[i])*np.cos(phi[i]), np.sin(theta[i])*np.sin(phi[i]), np.cos(theta[i]))
q = miepy.quaternion.from_spherical_coords(np.pi / 4, np.pi / 3)
R = miepy.quaternion.as_rotation_matrix(q)
geometry.append(
    meep.Ellipsoid(center=meep.Vector3(0, 0, 0),
                   size=2 * meep.Vector3(rx, ry, rz),
                   e1=meep.Vector3(*R[:, 0]),
                   e2=meep.Vector3(*R[:, 1]),
                   e3=meep.Vector3(*R[:, 2]),
                   material=material))

box = [2 * ry, 2 * ry, 2 * ry]
resolution = 1 / (8 * 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
hy = hy_actual/a_actual
h = w/2/np.tan(theta*np.pi/180)


####################################################################

#sets size of lattice to be 3D; 1by1by1
geometry_lattice = mp.Lattice(size=mp.Vector3(a, w*3, h*3))

#https://meep.readthedocs.io/en/latest/Python_User_Interface/#prism
beam = mp.Prism([mp.Vector3(0,-w/2, h/2), mp.Vector3(0,w/2, h/2), mp.Vector3(0,0, -h/2)], a, axis=mp.Vector3(1,0,0), 
    center=None, material=mp.Medium(epsilon=n**2))
#Diamond: n = 2.4063; n^2 = ep_r


hole = mp.Ellipsoid(size=[hx, hy, mp.inf], material=mp.Medium(epsilon=1))

geometry = [beam, hole]

#Symmetry points
k_points = [
    mp.Vector3(0,0,0),               # Gamma
    mp.Vector3(0.5,0,0),          # X (normalized to a?)
]
#how many points to solve for between each specified point above
k_points = mp.interpolate(kpt_resolution, k_points) 

#geometry_center
#ModeSolver documentation: https://mpb.readthedocs.io/en/latest/Python_User_Interface/
ms = mpb.ModeSolver(
    geometry=geometry,
예제 #17
0
def get_freqs(hx,
              hy,
              a,
              w,
              h=0.22,
              substrate=False,
              output_epsilon=False,
              mode="zEyO",
              num_bands=2):

    # h = 0.23    # for manually setting waveguide height
    res = 20
    #mode = "zEyO"
    resolution = res  # pixels/a, taken from simpetus example

    print(" h = " + str(h) + ", SUBSTRATE = " + str(substrate) + ", mode = " +
          str(mode))

    a = round(a, 3)  # units of um
    h = round(h, 3)  # units of um
    w = round(w, 3)  # units of um
    hx = round(hx, 3)
    hy = round(hy, 3)

    h = h / a  # units of "a"
    w = w / a  # units of "a"
    hx = hx / a  # units of "a"
    hy = hy / a  # units of "a"

    cell_x = 1
    cell_y = 4
    cell_z = 4

    nSi = 3.45
    Si = mp.Medium(index=nSi)

    geometry_lattice = mp.Lattice(size=mp.Vector3(
        cell_x, cell_y,
        cell_z))  # dimensions of lattice taken from simpetus example

    geometry = [
        mp.Block(center=mp.Vector3(),
                 size=mp.Vector3(mp.inf, w, h),
                 material=Si),
        mp.Ellipsoid(material=mp.air,
                     center=mp.Vector3(),
                     size=mp.Vector3(hx, hy, mp.inf))
    ]

    if substrate:
        geometry = add_substrate(geom=geometry,
                                 waveguide_height=h,
                                 substrate_height=cell_z / 2 -
                                 h / 2)  # substrate height normalized with a

    k_points = [mp.Vector3(0.5, 0, 0)]

    num_bands = num_bands

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

    if mode == "te":

        ms.run_te()  # running for all modes and extracting parities

    if mode == "zEyO":

        ms.run_yodd_zeven()

    if mode == "yO":

        ms.run_yodd()

    if mode == "yE":

        ms.run_yeven()

#     if output_epsilon:
#         visualise_geometry(ms = ms, x = None , y = None, z = (4 * res)/ 2, value = None)
    if output_epsilon:
        return ms.get_epsilon()


#         with h5py.File('epsilon.hdf5', 'w') as f:
#             arr = ms.get_epsilon
#             dset = f.create_dataset("epsilon", data = arr)

    return ms.freqs
예제 #18
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
def main(series, folder, resolution, from_um_factor, d, h, paper, wlen_range,
         nfreq):

    #%% PARAMETERS

    ### MEAN PARAMETERS

    # Units: 10 nm as length unit
    from_um_factor = 10e-3  # Conversion of 1 μm to my length unit (=10nm/1μm)

    # Au sphere
    medium = import_medium("Au", from_um_factor,
                           paper=paper)  # Medium of sphere: gold (Au)
    d = d / (from_um_factor * 1e3)  # Diameter is now in Meep units
    h = h / (from_um_factor * 1e3)  # Height is now in Meep units

    # Frequency and wavelength
    wlen_range = wlen_range / (from_um_factor * 1e3
                               )  # Wavelength range now in Meep units
    nfreq = 100  # Number of frequencies to discretize range
    cutoff = 3.2

    # Computation time
    enlapsed = []
    time_factor_cell = 1.2
    until_after_sources = False
    second_time_factor = 10

    # Saving directories
    home = vs.get_home()

    ### OTHER PARAMETERS

    # Units
    # uman = MeepUnitsManager(from_um_factor=from_um_factor)

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

    # Space configuration
    pml_width = 0.38 * max(wlen_range)
    air_width = max(d / 2, h / 2) / 2  # 0.5 * max(wlen_range)

    #%% GENERAL GEOMETRY SETUP

    air_width = air_width - air_width % (1 / resolution)

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

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

    cell_width_z = 2 * (pml_width + air_width + h / 2
                        )  # Parallel to polarization.
    cell_width_z = cell_width_z - cell_width_z % (1 / resolution)

    cell_width_r = 2 * (pml_width + air_width + d / 2
                        )  # Parallel to incidence.
    cell_width_r = cell_width_r - cell_width_r % (1 / resolution)

    cell_size = mp.Vector3(cell_width_r, cell_width_r, cell_width_z)

    source_center = -0.5 * cell_width_r + pml_width
    # print("Resto Source Center: {}".format(source_center%(1/resolution)))
    sources = [
        mp.Source(mp.GaussianSource(freq_center,
                                    fwidth=freq_width,
                                    is_integrated=True,
                                    cutoff=cutoff),
                  center=mp.Vector3(source_center),
                  size=mp.Vector3(0, cell_width_r, cell_width_z),
                  component=mp.Ez)
    ]
    # Ez-polarized planewave pulse
    # (its size parameter fills the entire cell in 2d)
    # >> The planewave source extends into the PML
    # ==> is_integrated=True must be specified

    if time_factor_cell is not False:
        until_after_sources = time_factor_cell * cell_width_r
    else:
        if until_after_sources is False:
            raise ValueError(
                "Either time_factor_cell or until_after_sources must be specified"
            )
        time_factor_cell = until_after_sources / cell_width_r
    # Enough time for the pulse to pass through all the cell
    # Originally: Aprox 3 periods of lowest frequency, using T=λ/c=λ in Meep units
    # Now: Aprox 3 periods of highest frequency, using T=λ/c=λ in Meep units

    geometry = [
        mp.Ellipsoid(size=mp.Vector3(d, d, h),
                     material=medium,
                     center=mp.Vector3())
    ]
    # Au ellipsoid with frequency-dependant characteristics imported from Meep.

    path = os.path.join(home, folder, f"{series}")
    if not os.path.isdir(path) and mp.am_master():
        vs.new_dir(path)
    file = lambda f: os.path.join(path, f)

    #%% FIRST RUN: SET UP

    sim = mp.Simulation(resolution=resolution,
                        cell_size=cell_size,
                        boundary_layers=pml_layers,
                        sources=sources,
                        k_point=mp.Vector3())  #,
    # symmetries=symmetries)
    # >> k_point zero specifies boundary conditions needed
    # for the source to be infinitely extended

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

    #%% FIRST RUN: INITIALIZE

    temp = time()
    sim.init_sim()
    enlapsed.append(time() - temp)
    """
    112x112x112 with resolution 4
    (48 cells inside diameter)
    ==> 30 s to build
    
    112x112x112 with resolution 2
    (24 cells inside diameter)
    ==> 4.26 s to build
    
    116x116x116 with resolution 2
    (24 cells inside diameter)
    ==> 5.63 s
    
    98 x 98 x 98 with resolution 3
    (36 cells inside diameter)
    ==> 9.57 s
    
    172x172x172 with resolution 2
    (24 cells inside diameter)
    ==> 17.47 s
    
    67 x 67 x 67 with resolution 4
    (48 cells inside diameter)
    ==> 7.06 s
    
    67,375 x 67,375 x 67,375 with resolution 8
    (100 cells inside diameter)
    ==> 56.14 s
    """

    #%% FIRST RUN: SIMULATION NEEDED TO NORMALIZE

    temp = time()
    sim.run(until_after_sources=until_after_sources)
    #     mp.stop_when_fields_decayed(
    # np.mean(wlen_range), # dT = mean period of source
    # mp.Ez, # Component of field to check
    # mp.Vector3(0.5*cell_width - pml_width, 0, 0), # Where to check
    # 1e-3)) # Factor to decay
    enlapsed.append(time() - temp)
    """
    112x112x112 with resolution 2
    (24 cells inside diameter)
    ==> 135.95 s to complete 1st run
    
    116x116x116 with resolution 2
    (24 cells inside diameter)
    ==> 208 s to complete 1st run
    
    67 x 67 x 67 with resolution 4
    (48 cells inside diameter)
    ==> 2000 s = 33 min to complete 1st run
    """

    freqs = np.asarray(mp.get_flux_freqs(box_x1))
    box_x1_data = sim.get_flux_data(box_x1)
    box_x2_data = sim.get_flux_data(box_x2)
    box_y1_data = sim.get_flux_data(box_y1)
    box_y2_data = sim.get_flux_data(box_y2)
    box_z1_data = sim.get_flux_data(box_z1)
    box_z2_data = sim.get_flux_data(box_z2)

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

    # field = sim.get_array(center=mp.Vector3(),
    #                       size=(cell_width, cell_width, cell_width),
    #                       component=mp.Ez)

    sim.reset_meep()

    #%% SAVE MID DATA

    params = dict(
        from_um_factor=from_um_factor,
        resolution=resolution,
        d=d,
        h=h,
        paper=paper,
        wlen_range=wlen_range,
        nfreq=nfreq,
        cutoff=cutoff,
        pml_width=pml_width,
        air_width=air_width,
        source_center=source_center,
        enlapsed=enlapsed,
        series=series,
        folder=folder,
        pc=pc,
        until_after_sources=until_after_sources,
        time_factor_cell=time_factor_cell,
        second_time_factor=second_time_factor,
    )

    # f = h5.File(file("MidField.h5"), "w")
    # f.create_dataset("Ez", data=field)
    # for a in params: f["Ez"].attrs[a] = params[a]
    # f.close()
    # del f

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

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

    if mp.am_master():
        vs.savetxt(file("MidFlux.txt"),
                   data_mid,
                   header=header_mid,
                   footer=params)

    #%% PLOT FLUX FOURIER MID DATA

    if mp.my_rank() == 1:
        ylims = (np.min(data_mid[:, 1:]), np.max(data_mid[:, 1:]))
        ylims = (ylims[0] - .1 * (ylims[1] - ylims[0]),
                 ylims[1] + .1 * (ylims[1] - ylims[0]))

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

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

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

    #%% PLOT FLUX WALLS FIELD

    # if mp.am_master():
    # index_to_space = lambda i : i/resolution - cell_width/2
    # space_to_index = lambda x : round(resolution * (x + cell_width/2))

    # field_walls = [field[space_to_index(-r),:,:],
    #                 field[space_to_index(r),:,:],
    #                 field[:,space_to_index(-r),:],
    #                 field[:,space_to_index(r),:],
    #                 field[:,:,space_to_index(-r)],
    #                 field[:,:,space_to_index(r)]]

    # zlims = (np.min([np.min(f) for f in field_walls]),
    #           np.max([np.max(f) for f in field_walls]))

    # fig, ax = plt.subplots(3, 2)
    # fig.subplots_adjust(hspace=0.25)
    # for a, hm in zip(np.reshape(ax, 6), header_mid[1:]):
    #     a.set_title(hm.split(" ")[1].split("0")[0])

    # for f, a in zip(field_walls, np.reshape(ax, 6)):
    #     a.imshow(f.T, interpolation='spline36', cmap='RdBu',
    #               vmin=zlims[0], vmax=zlims[1])
    #     a.axis("off")

    # plt.savefig(file("MidField.png"))

    #%% SECOND RUN: SETUP

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

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

    #%% SECOND RUN: INITIALIZE

    temp = time()
    sim.init_sim()
    enlapsed.append(time() - temp)
    """
    112x112x112 with resolution 2
    (24 cells in diameter)
    ==> 5.16 s to build with sphere
    
    116x116x116 with resolution 2
    (24 cells inside diameter)
    ==> 9.71 s to build with sphere
    
    67 x 67 x 67 with resolution 4
    (48 cells inside diameter)
    ==> 14.47 s to build with sphere
    """

    temp = time()
    sim.load_minus_flux_data(box_x1, box_x1_data)
    sim.load_minus_flux_data(box_x2, box_x2_data)
    sim.load_minus_flux_data(box_y1, box_y1_data)
    sim.load_minus_flux_data(box_y2, box_y2_data)
    sim.load_minus_flux_data(box_z1, box_z1_data)
    sim.load_minus_flux_data(box_z2, box_z2_data)
    enlapsed.append(time() - temp)
    del box_x1_data, box_x2_data, box_y1_data, box_y2_data
    del box_z1_data, box_z2_data
    """
    112x112x112 with resolution 2
    (24 cells in diameter)
    ==> 0.016 s to add flux
    
    116x116x116 with resolution 2
    (24 cells inside diameter)
    ==> 0.021 s to add flux
    
    67 x 67 x 67 with resolution 4
    (48 cells inside diameter)
    ==> 0.043 s to add flux
    """

    #%% SECOND RUN: SIMULATION :D

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

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

    #%% ANALYSIS

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

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

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

    scatt_eff_meep = -1 * scatt_cross_section / (np.pi * d**2)
    # Scattering efficiency =
    # = scattering cross section / cross sectional area of the sphere
    # WATCH IT! Is this the correct cross section?

    freqs = np.array(freqs)

    #%% SAVE FINAL DATA

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

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

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

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

    if mp.am_master():
        vs.savetxt(file("Results.txt"), data, header=header, footer=params)
        vs.savetxt(file("BaseResults.txt"),
                   data_base,
                   header=header_base,
                   footer=params)

    #%% PLOT SCATTERING

    if mp.my_rank() == 1:
        plt.figure()
        plt.plot(1e3 * from_um_factor / freqs,
                 scatt_eff_meep,
                 'bo-',
                 label='Meep')
        plt.xlabel('Wavelength [nm]')
        plt.ylabel('Scattering efficiency [σ/πr$^{2}$]')
        plt.legend()
        plt.title(f'Scattering of Au Ellipsoid ({ 1e3*from_um_factor*d }x' +
                  f'{ 1e3*from_um_factor*d }x{ 1e3*from_um_factor*h } nm)')
        plt.tight_layout()
        plt.savefig(file("ScattSpectra.png"))

    #%% PLOT ABSORPTION

    if mp.am_master():
        plt.figure()
        plt.plot(1e3 * from_um_factor / freqs,
                 1 - scatt_eff_meep,
                 'bo-',
                 label='Meep')
        plt.xlabel('Wavelength [nm]')
        plt.ylabel('Absorption efficiency [σ/πr$^{2}$]')
        plt.legend()
        plt.title(f'Absorption of Au Ellipsoid ({ 1e3*from_um_factor*d }x' +
                  f'{ 1e3*from_um_factor*d }x{ 1e3*from_um_factor*h } nm)')
        plt.tight_layout()
        plt.savefig(file("AbsSpectra.png"))
예제 #20
0
rightwall = mp.Block(mp.Vector3(wallWidth, waveguideHeight + 2 * wallWidth,
                                mp.inf),
                     center=mp.Vector3(waveguideLength / 2 + wallWidth / 2, 0,
                                       0),
                     material=mp.metal)

obstacle = mp.Cylinder(radius=2,
                       height=1,
                       axis=mp.Vector3(0, 0, 1),
                       center=mp.Vector3(0, 0, 0),
                       material=mp.metal)

obstacle1 = mp.Ellipsoid(center=mp.Vector3(-5, 4, 0),
                         size=mp.Vector3(8, 2, 2),
                         e1=mp.Vector3(1, 1, 0),
                         e2=mp.Vector3(0, 1, 0),
                         e3=mp.Vector3(0, 0, 1),
                         material=mp.metal)

obstacle2 = mp.Ellipsoid(center=mp.Vector3(6, -6, 0),
                         size=mp.Vector3(8, 2, 2),
                         e1=mp.Vector3(1, .5, 0),
                         e2=mp.Vector3(0, 1, 0),
                         e3=mp.Vector3(0, 0, 1),
                         material=mp.metal)

port1 = mp.Block(portSize,
                 center=p1Loc,
                 material=mp.Medium(epsilon=dielectricConstant))

port2 = mp.Block(portSize,
예제 #21
0
# (its size parameter fills the entire cell in 2d)
# >> The planewave source extends into the PML
# ==> is_integrated=True must be specified

if time_factor_cell is not False:
    until_after_sources = time_factor_cell * cell_width_r
else:
    if until_after_sources is False:
        raise ValueError(
            "Either time_factor_cell or until_after_sources must be specified")
    time_factor_cell = until_after_sources / cell_width_r
# Enough time for the pulse to pass through all the cell
# Originally: Aprox 3 periods of lowest frequency, using T=λ/c=λ in Meep units
# Now: Aprox 3 periods of highest frequency, using T=λ/c=λ in Meep units

geometry = [mp.Ellipsoid(size=mp.Vector3(d, d, h), material=medium)]
# Au ellipsoid with frequency-dependant characteristics imported from Meep.

path = os.path.join(home, folder, f"{series}")
if not os.path.isdir(path): vs.new_dir(path)
file = lambda f: os.path.join(path, f)

#%% FIRST RUN: SET UP

sim = mp.Simulation(resolution=resolution,
                    cell_size=cell_size,
                    boundary_layers=pml_layers,
                    sources=sources,
                    k_point=mp.Vector3())  #,
# symmetries=symmetries)
# >> k_point zero specifies boundary conditions needed