예제 #1
0
#The waveguide is specified by a Block (parallelepiped) of size ∞×1×∞, with ε=12
#centered at (0,0) which is the center of the cell. By default, any place where
#there are no objects there is air (ε=1)

sources = [
    mp.Source(mp.ContinuousSource(frequency=0.15),
              component=mp.Ez,
              center=mp.Vector3(-7, 0))
]
#We gave the source a frequency of 0.15, and specified a ContinuousSource which is
#just a fixed-frequency sinusoid exp(−iωt) that by default is turned on at t=0
# frequency is specified in units of 2πc, which is equivalent to the inverse of the
#vacuum wavelength. Thus, 0.15 corresponds to a vacuum wavelength of about 1/0.15=6.67 μm,
#or a wavelength of about 2 μm in the ε=12 material

pml_layers = [mp.PML(1.0)]
#boundry conditions that absorb around the cell
#absorbing boundries handled by perfectly matched layers (PML)
#this adds absorbing layer thickness of 1 um around all sides of cell

resolution = 10
#this gives resolution of 10 pixels per um

sim = mp.Simulation(cell_size=cell,
                    boundary_layers=pml_layers,
                    geometry=geometry,
                    sources=sources,
                    resolution=resolution)
#this is the simulation based on all previously defined objects

sim.run(until=200)
예제 #2
0
w2 = 2.0  # width of waveguide 2
Lw = 10.0  # length of waveguides 1 and 2

# lengths of waveguide taper
Lts = [2**m for m in range(5)]

dair = 3.0  # length of air region
dpml_x = 6.0  # length of PML in x direction
dpml_y = 2.0  # length of PML in y direction

sy = dpml_y + dair + w2 + dair + dpml_y

Si = mp.Medium(epsilon=12.0)

boundary_layers = [
    mp.PML(dpml_x, direction=mp.X),
    mp.PML(dpml_y, direction=mp.Y)
]

lcen = 6.67  # mode wavelength
fcen = 1 / lcen  # mode frequency

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

R_coeffs = []
R_flux = []

for Lt in Lts:
    sx = dpml_x + Lw + Lt + Lw + dpml_x
    cell_size = mp.Vector3(sx, sy, 0)
    def __init__(self, dir_name, wavelength, thy_absorb, cyt_absorb):
        self.base_directory = base_directory + str(dir_name)

        self.wavelength = wavelength
        self.thy_absorb = thy_absorb
        self.cyt_absorb = cyt_absorb
        self.frequency = 1 / wavelength
        # Calculate wavelengths dependent on RI
        self.wavelength_in_media = wavelength / ri_media
        self.wavelength_in_cytoplasm = wavelength / ri_cytoplasm
        self.wavelength_in_thylakoid = wavelength / ri_thylakoid
        max_freq = self.frequency - 0.01
        min_freq = self.frequency + 0.01
        self.pulse_width = abs(max_freq - min_freq)

        cell = mp.Vector3(sxx, sxy, 0)
        pml_layers = [mp.PML(dpml)]

        thylakoid_material = mp.Medium(index=ri_thylakoid,
                                       D_conductivity=2 * math.pi *
                                       self.frequency * (thy_absorb /
                                                         (ri_thylakoid**2)))
        cytoplasm_material = mp.Medium(index=ri_cytoplasm,
                                       D_conductivity=2 * math.pi *
                                       self.frequency * (cyt_absorb /
                                                         (ri_cytoplasm**2)))

        thylakoid_region = mp.Sphere(radius=cell_radius,
                                     center=mp.Vector3(0, 0),
                                     material=thylakoid_material)
        cytoplasm_region = mp.Sphere(radius=cell_radius - thylakoid_thickness,
                                     center=mp.Vector3(0, 0),
                                     material=cytoplasm_material)
        geometry = [thylakoid_region, cytoplasm_region]

        # Sources
        kdir = mp.Vector3(1, 0, 0)  # direction of k (length is irrelevant)
        n = ri_media  # refractive index of material containing the source
        k = kdir.unit().scale(2 * math.pi * self.frequency *
                              n)  # k with correct length

        def pw_amp(k, x0):
            def _pw_amp(x):
                return cmath.exp(1j * k.dot(x + x0))

            return _pw_amp

        source = [
            mp.Source(
                mp.ContinuousSource(frequency=self.frequency,
                                    fwidth=self.pulse_width),  # along x axis
                component=mp.Ez,
                center=mp.Vector3(-0.5 * simulation_size, 0),  # x, ,y ,z
                size=mp.Vector3(0, sxy, 0),
                amp_func=pw_amp(k, mp.Vector3(x=-0.5 * simulation_size)))
        ]

        sim = mp.Simulation(
            cell_size=cell,
            sources=source,
            boundary_layers=pml_layers,
            resolution=resolution,
            geometry=geometry,
            default_material=mp.Medium(index=ri_media),
            force_complex_fields=complex_f,
            eps_averaging=eps_av,
        )

        sim.use_output_directory(self.base_directory)
        sim.run(mp.at_every(
            0.6,
            mp.output_png(mp.Ez,
                          "-Zc/data/home/bt16268/simInput/customColour.txt")),
                until=t)
예제 #4
0
pos_z = height + 0.005

pt = mp.Vector3(pos_x, pos_y, pos_z)

resolution = 150
numx = int(width_cal * resolution)
numy = int(height_cal * resolution)
x_list = np.linspace(-width_cal / 2, width_cal / 2, numx)
y_list = np.linspace(-height_cal / 2, height_cal / 2, numy)
x_grid, y_grid = np.meshgrid(x_list, y_list)
# %%
cell_size = mp.Vector3(length_cal, width_cal, height_cal)

pml_layers = [
    mp.Absorber(thickness=t_pml, direction=mp.Y),
    mp.PML(thickness=t_pml, direction=mp.Z),
    mp.PML(thickness=t_pml, direction=mp.X)
]

# Y dipole
source = [
    mp.Source(mp.ContinuousSource(frequency=omega), component=mp.Ey, center=pt)
]

# We first calculate the normalized power
sim0 = mp.Simulation(resolution=resolution,
                     cell_size=cell_size,
                     boundary_layers=pml_layers,
                     default_material=mp.Medium(index=index_SiN),
                     sources=source,
                     eps_averaging=False,
예제 #5
0
from autograd import numpy as npa
from autograd import tensor_jacobian_product
import unittest
from enum import Enum

MonitorObject = Enum('MonitorObject', 'EIGENMODE DFT')

resolution = 25

silicon = mp.Medium(epsilon=12)

sxy = 5.0
cell_size = mp.Vector3(sxy,sxy,0)

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

eig_parity = mp.EVEN_Y + mp.ODD_Z

design_shape = mp.Vector3(1.5,1.5)
design_region_resolution = int(2*resolution)
Nx = int(design_region_resolution*design_shape.x)
Ny = int(design_region_resolution*design_shape.y)

## ensure reproducible results
np.random.seed(9861548)

## random design region
p = np.random.rand(Nx*Ny)

## random epsilon perturbation for design region
def main():
    n = 3.4  # index of waveguide
    r = 1
    a = r  # inner radius of ring
    w = 1  # width of waveguide
    b = a + w  # outer radius of ring
    pad = 4  # padding between waveguide and edge of PML

    dpml = 2  # thickness of PML
    pml_layers = [mp.PML(dpml)]

    resolution = 100

    sr = b + pad + dpml  # radial size (cell is from 0 to sr)
    dimensions = mp.CYLINDRICAL  # coordinate system is (r,phi,z) instead of (x,y,z)
    cell = mp.Vector3(sr, 0, 0)

    m = 4

    geometry = [
        mp.Block(center=mp.Vector3(a + (w / 2)),
                 size=mp.Vector3(w, 1e20, 1e20),
                 material=mp.Medium(index=n))
    ]

    # Finding a resonance mode with a high Q-value (calculated with Harminv)

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

    sources = [
        mp.Source(mp.GaussianSource(fcen, fwidth=df),
                  mp.Hz,
                  mp.Vector3(r + 0.1),
                  amplitude=1)
    ]

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

    h = mp.Harminv(mp.Hz, mp.Vector3(r + 0.1), fcen, df)
    sim.run(mp.after_sources(h), until_after_sources=200)

    Harminv_freq_at_R = h.modes[0].freq

    sim.reset_meep()

    # now running the simulation that will be used with perturbation theory to calculate dw/dR

    fcen = Harminv_freq_at_R
    df = 0.01

    sources = [
        mp.Source(mp.GaussianSource(fcen, fwidth=df),
                  mp.Hz,
                  mp.Vector3(r + 0.1),
                  amplitude=1)
    ]

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

    sim.run(until_after_sources=200)

    # now need to calculate the surface integrals that go into dw/dR. Fields parallel and perpendicular to the interface
    # AND at the inner and outer surfaces are treated differently, so each will be calculated separately.

    # section for fields at inner surface
    npts_inner = 10
    angles_inner = 2 * np.pi / npts_inner * np.arange(npts_inner)
    deps_inner = 1 - n**2
    deps_inv_inner = 1 - 1 / (n**2)

    # section for fields parallel to interface (Ez and Ep)
    parallel_fields_inner = []
    for angle in angles_inner:
        point = mp.Vector3(a, angle)
        e_z_field = abs(sim.get_field_point(mp.Ez, point))**2
        e_p_field = abs(sim.get_field_point(mp.Ep, point))**2
        e_parallel_field = e_z_field + e_p_field
        # fields have to be multiplied by Δε
        e_parallel_field = deps_inner * e_parallel_field
        parallel_fields_inner.append(e_parallel_field)

    # section for fields perpendicular to interface (Er)
    perpendicular_fields_inner = []
    for angle in angles_inner:
        point = mp.Vector3(a, angle)
        e_r_field = abs(sim.get_field_point(mp.Er, point))**2
        e_perpendicular_field = e_r_field
        # fields have to be multiplied by Δ(1/ε) and ε**2
        e_perpendicular_field = deps_inv_inner * (abs(
            sim.get_epsilon_point(point, Harminv_freq_at_R))**
                                                  2) * e_perpendicular_field
        perpendicular_fields_inner.append(e_perpendicular_field)

    # section for fields at outer surface
    npts_outer = npts_inner
    angles_outer = 2 * np.pi / npts_outer * np.arange(npts_outer)
    deps_outer = n**2 - 1
    deps_inv_outer = -1 + 1 / (n**2)

    # section for fields parallel to interface (Ez and Ep)    parallel_fields_outer = []
    parallel_fields_outer = []
    for angle in angles_outer:
        point = mp.Vector3(b, angle)
        e_z_field = abs(sim.get_field_point(mp.Ez, point))**2
        e_p_field = abs(sim.get_field_point(mp.Ep, point))**2
        e_parallel_field = e_z_field + e_p_field
        # fields have to be multiplied by Δε
        e_parallel_field = deps_outer * e_parallel_field
        parallel_fields_outer.append(e_parallel_field)

    # section for fields perpendicular to interface (Er)
    perpendicular_fields_outer = []
    for angle in angles_inner:
        point = mp.Vector3(b, angle)
        e_r_field = abs(sim.get_field_point(mp.Er, point))
        e_perpendicular_field = e_r_field**2
        # fields have to be multiplied by Δ(1/ε) and ε**2
        e_perpendicular_field = deps_inv_outer * (abs(
            sim.get_epsilon_point(point, Harminv_freq_at_R))**
                                                  2) * e_perpendicular_field
        perpendicular_fields_outer.append(e_perpendicular_field)

    numerator_surface_integral = 2 * np.pi * b * (
        mean([mean(parallel_fields_inner),
              mean(parallel_fields_outer)]) - mean([
                  mean(perpendicular_fields_inner),
                  mean(perpendicular_fields_outer)
              ]))
    denominator_surface_integral = sim.electric_energy_in_box(
        center=mp.Vector3((b + pad / 2) / 2), size=mp.Vector3(b + pad / 2))
    perturb_theory_dw_dR = -Harminv_freq_at_R * numerator_surface_integral / (
        4 * denominator_surface_integral)

    center_diff_dw_dR = []
    Harminv_freqs_at_R_plus_dR = []

    drs = np.logspace(start=-3, stop=-1, num=10)

    for dr in drs:
        sim.reset_meep()
        w = 1 + dr  # width of waveguide
        b = a + w
        print(f'The current dr is dr={dr}')
        if len(Harminv_freqs_at_R_plus_dR) == 0:
            fcen = Harminv_freq_at_R
        else:
            fcen = Harminv_freqs_at_R_plus_dR[-1]
        df = 0.01

        sources = [
            mp.Source(mp.GaussianSource(fcen, fwidth=df), mp.Hz,
                      mp.Vector3(r + 0.1))
        ]

        geometry = [
            mp.Block(center=mp.Vector3(a + (w / 2)),
                     size=mp.Vector3(w, 1e20, 1e20),
                     material=mp.Medium(index=n))
        ]

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

        h = mp.Harminv(mp.Hz, mp.Vector3(r + 0.1), fcen, df)
        sim.run(mp.after_sources(h), until_after_sources=200)

        Harminv_freq_at_R_plus_dR = h.modes[0].freq
        Harminv_freqs_at_R_plus_dR.append(Harminv_freq_at_R_plus_dR)

        dw_dR = (Harminv_freq_at_R_plus_dR - Harminv_freq_at_R) / dr
        center_diff_dw_dR.append(dw_dR)

    relative_errors_dw_dR = [
        abs((dw_dR - perturb_theory_dw_dR) / dw_dR)
        for dw_dR in center_diff_dw_dR
    ]

    perturb_predicted_freqs_at_R_plus_dR = [
        dr * perturb_theory_dw_dR + Harminv_freq_at_R for dr in drs
    ]
    relative_errors_freqs_at_R_plus_dR = [
        abs((perturb_predicted_freqs_at_R_plus_dR[i] -
             Harminv_freqs_at_R_plus_dR[i]) / Harminv_freqs_at_R_plus_dR[i])
        for i in range(len(Harminv_freqs_at_R_plus_dR))
    ]

    if mp.am_master():
        plt.figure(dpi=150)
        plt.loglog(drs, relative_errors_dw_dR, 'bo-', label='relative error')
        plt.grid(True, which='both', ls='-')
        plt.xlabel('perturbation amount $dr$')
        plt.ylabel('relative error between $dω/dR$')
        plt.legend(loc='upper right')
        plt.title(
            'Comparison of Perturbation Theory and \nCenter-Difference Calculations in Finding $dω/dR$'
        )
        plt.tight_layout()
        # plt.show()
        plt.savefig('ring_Hz_perturbation_theory.dw_dR_error.png')
        plt.clf()

        plt.figure(dpi=150)
        plt.loglog(drs,
                   relative_errors_freqs_at_R_plus_dR,
                   'bo-',
                   label='relative error')
        plt.grid(True, which='both', ls='-')
        plt.xlabel('perturbation amount $dr$')
        plt.ylabel('relative error between $ω(R+dR)$')
        plt.legend(loc='upper left')
        plt.title(
            'Comparison of resonance frequencies at $R+dR$ predicted by\nperturbation theory and found with Harminv'
        )
        plt.tight_layout()
        # plt.show()
        plt.savefig('ring_Hz_perturbation_theory.freqs_error.png')
        plt.clf()
예제 #7
0
def setup_sim(zDim=0):
    cell = mp.Vector3(16, 8, zDim)

    # A simple waveguide
    geometry = [
        mp.Block(mp.Vector3(mp.inf, 1, 1),
                 center=mp.Vector3(),
                 material=mp.Medium(epsilon=12))
    ]

    # Add point sources
    sources = [
        mp.Source(mp.ContinuousSource(frequency=0.15),
                  component=mp.Ez,
                  center=mp.Vector3(-5, 0),
                  size=mp.Vector3(0, 0, 2)),
        mp.Source(mp.ContinuousSource(frequency=0.15),
                  component=mp.Ez,
                  center=mp.Vector3(0, 2),
                  size=mp.Vector3(0, 0, 2)),
        mp.Source(mp.ContinuousSource(frequency=0.15),
                  component=mp.Ez,
                  center=mp.Vector3(-1, 1),
                  size=mp.Vector3(0, 0, 2)),
        mp.Source(mp.ContinuousSource(frequency=0.15),
                  component=mp.Ez,
                  center=mp.Vector3(-2, -2, 1),
                  size=mp.Vector3(0, 0, 0)),
    ]

    # Add line sources
    sources += [
        mp.Source(mp.ContinuousSource(frequency=0.15),
                  component=mp.Ez,
                  size=mp.Vector3(0, 2, 2),
                  center=mp.Vector3(-6, 0)),
        mp.Source(mp.ContinuousSource(frequency=0.15),
                  component=mp.Ez,
                  size=mp.Vector3(0, 2, 2),
                  center=mp.Vector3(0, 1))
    ]

    # Add plane sources
    sources += [
        mp.Source(mp.ContinuousSource(frequency=0.15),
                  component=mp.Ez,
                  size=mp.Vector3(2, 2, 2),
                  center=mp.Vector3(-3, 0)),
        mp.Source(mp.ContinuousSource(frequency=0.15),
                  component=mp.Ez,
                  size=mp.Vector3(2, 2, 2),
                  center=mp.Vector3(0, -2))
    ]

    # Different pml layers
    pml_layers = [
        mp.PML(2.0, mp.X),
        mp.PML(1.0, mp.Y, mp.Low),
        mp.PML(1.5, mp.Y, mp.High),
        mp.PML(1.5, mp.Z)
    ]

    resolution = 10

    sim = mp.Simulation(cell_size=cell,
                        boundary_layers=pml_layers,
                        geometry=geometry,
                        sources=sources,
                        resolution=resolution)
    # Line monitor
    sim.add_flux(
        1, 0, 1,
        mp.FluxRegion(center=mp.Vector3(5, 0, 0),
                      size=mp.Vector3(0, 4, 4),
                      direction=mp.X))

    # Plane monitor
    sim.add_flux(
        1, 0, 1,
        mp.FluxRegion(center=mp.Vector3(2, 0, 0),
                      size=mp.Vector3(4, 4, 4),
                      direction=mp.X))

    return sim
예제 #8
0
def main(args):

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

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

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

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

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

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

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

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

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

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

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

    sim.reset_meep()

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

    sim.change_sources(new_sources)

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

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

    runtime = 5000
    sim.run(until_after_sources=runtime)
    sim.display_fluxes(wvg_pwr)
    sim.display_forces(wvg_force)
예제 #9
0
def diff(ht,wvl_cen):
	import meep as mp
	import numpy as np
	import math
	import random
	
	#450	 1.674	
	#550     1.642
	#650     1.629
	
	if (wvl_cen == 0.45):
		photoresist = mp.Medium(index=1.674)   #波长为450nm时光刻胶的折射率 
	elif (wvl_cen == 0.55):
		photoresist = mp.Medium(index=1.642)   #波长为550nm时光刻胶的折射率 
	else:
		photoresist = mp.Medium(index=1.629)   #波长为650nm时光刻胶的折射率 
	
	
	## at least 8 pixels per smallest wavelength, i.e. np.floor(8/wvl_min)
	resolution = 25.0          

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

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

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

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

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

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

	ff_r = sim.get_farfields(n2f_obj, ff_res, center=mp.Vector3(0.5*(sr-dpml),0,-0.5*sz+dpml+dsub+h+focal_length),size=mp.Vector3(sr-dpml))
	E2_r = np.absolute(ff_r['Ex'])**2+np.absolute(ff_r['Ey'])**2+np.absolute(ff_r['Ez'])**2
	
	E_sum = sum(E2_r)
	n = round((1.5*(wvl_cen/(2*NA)))/(r/(len(E2_r)-1)))
	#print ('n = %d' % n)
	E = 0.0
	for i in range (n):
		E += E2_r[i]
	
	return E/E_sum  
예제 #10
0
    def test_dft_energy(self):
        resolution = 20
        cell = mp.Vector3(10, 5)
        geom = [
            mp.Block(size=mp.Vector3(mp.inf, 1, mp.inf),
                     material=mp.Medium(epsilon=12))
        ]
        pml = [mp.PML(1)]
        fsrc = 0.15
        sources = [
            mp.EigenModeSource(src=mp.GaussianSource(frequency=fsrc,
                                                     fwidth=0.2 * fsrc),
                               center=mp.Vector3(-3),
                               size=mp.Vector3(y=5),
                               eig_band=1,
                               eig_parity=mp.ODD_Z + mp.EVEN_Y,
                               eig_match_freq=True)
        ]

        sim = mp.Simulation(resolution=resolution,
                            cell_size=cell,
                            geometry=geom,
                            boundary_layers=pml,
                            sources=sources,
                            symmetries=[mp.Mirror(direction=mp.Y)])

        flux = sim.add_flux(fsrc,
                            0,
                            1,
                            mp.FluxRegion(center=mp.Vector3(3),
                                          size=mp.Vector3(y=5)),
                            decimation_factor=1)
        energy = sim.add_energy(fsrc,
                                0,
                                1,
                                mp.EnergyRegion(center=mp.Vector3(3),
                                                size=mp.Vector3(y=5)),
                                decimation_factor=1)
        energy_decimated = sim.add_energy(fsrc,
                                          0,
                                          1,
                                          mp.EnergyRegion(
                                              center=mp.Vector3(3),
                                              size=mp.Vector3(y=5)),
                                          decimation_factor=10)
        sim.run(until_after_sources=100)

        res = sim.get_eigenmode_coefficients(flux, [1],
                                             eig_parity=mp.ODD_Z + mp.EVEN_Y)
        mode_vg = res.vgrp[0]
        poynting_flux = mp.get_fluxes(flux)[0]
        e_energy = mp.get_electric_energy(energy)[0]
        ratio_vg = (0.5 * poynting_flux) / e_energy
        m_energy = mp.get_magnetic_energy(energy)[0]
        t_energy = mp.get_total_energy(energy)[0]

        self.assertAlmostEqual(m_energy + e_energy, t_energy)
        self.assertAlmostEqual(ratio_vg, mode_vg, places=3)

        e_energy_decimated = mp.get_electric_energy(energy_decimated)[0]
        m_energy_decimated = mp.get_magnetic_energy(energy_decimated)[0]
        self.assertAlmostEqual(e_energy, e_energy_decimated, places=1)
        self.assertAlmostEqual(m_energy, m_energy_decimated, places=1)
예제 #11
0
 def _create_boundary_layers(self):
     return [mp.PML(self.pml)]
예제 #12
0
def get_simulation(
    component: Component,
    extend_ports_length: Optional[float] = 4.0,
    layer_stack: LayerStack = LAYER_STACK,
    res: int = 20,
    t_clad_top: float = 1.0,
    t_clad_bot: float = 1.0,
    tpml: float = 1.0,
    clad_material: str = "SiO2",
    is_3d: bool = False,
    wl_min: float = 1.5,
    wl_max: float = 1.6,
    wl_steps: int = 50,
    dfcen: float = 0.2,
    port_source_name: str = 1,
    port_field_monitor_name: str = 2,
    port_margin: float = 0.5,
    distance_source_to_monitors: float = 0.2,
) -> Dict[str, Any]:
    """Returns Simulation dict from gdsfactory.component

    based on meep directional coupler example
    https://meep.readthedocs.io/en/latest/Python_Tutorials/GDSII_Import/

    https://support.lumerical.com/hc/en-us/articles/360042095873-Metamaterial-S-parameter-extraction

    Args:
        component: gf.Component
        extend_ports_function: function to extend the ports for a component to ensure it goes beyond the PML
        layer_to_thickness: Dict of layer number (int, int) to thickness (um)
        res: resolution (pixels/um) For example: (10: 100nm step size)
        t_clad_top: thickness for cladding above core
        t_clad_bot: thickness for cladding below core
        tpml: PML thickness (um)
        clad_material: material for cladding
        is_3d: if True runs in 3D
        wavelengths: iterable of wavelengths to simulate
        dfcen: delta frequency
        sidewall_angle: in degrees
        port_source_name: input port name
        port_field_monitor_name:
        port_margin: margin on each side of the port
        distance_source_to_monitors: in (um) source goes before

    Returns:
        sim: simulation object

    Make sure you visualize the simulation region with gf.before you simulate a component

    .. code::

        import gdsfactory as gf
        import gmeep as gm

        c = gf.components.bend_circular()
        margin = 2
        cm = gm.add_monitors(c)
        gf.show(cm)

    """
    layer_to_thickness = layer_stack.get_layer_to_thickness()
    layer_to_material = layer_stack.get_layer_to_material()
    layer_to_zmin = layer_stack.get_layer_to_zmin()
    layer_to_sidewall_angle = layer_stack.get_layer_to_sidewall_angle()

    wavelengths = np.linspace(wl_min, wl_max, wl_steps)
    if port_source_name not in component.ports:
        warnings.warn(
            f"port_source_name={port_source_name} not in {component.ports.keys()}"
        )
        port_source = component.get_ports_list()[0]
        port_source_name = port_source.name
        warnings.warn(f"Selecting port_source_name={port_source_name} instead.")

    if port_field_monitor_name not in component.ports:
        warnings.warn(
            f"port_field_monitor_name={port_field_monitor_name} not in {component.ports.keys()}"
        )
        port_field_monitor = (
            component.get_ports_list()[0]
            if len(component.ports) < 2
            else component.get_ports_list()[1]
        )
        port_field_monitor_name = port_field_monitor.name
        warnings.warn(
            f"Selecting port_field_monitor_name={port_field_monitor_name} instead."
        )

    assert isinstance(
        component, Component
    ), f"component needs to be a gf.Component, got Type {type(component)}"

    component_extended = (
        gf.components.extension.extend_ports(
            component=component, length=extend_ports_length, centered=True
        )
        if extend_ports_length
        else component
    )

    component = component.ref()
    component.x = 0
    component.y = 0

    gf.show(component_extended)

    component_extended.flatten()
    component_extended = component_extended.ref()

    # geometry_center = [component_extended.x, component_extended.y]
    # geometry_center = [0, 0]
    # print(geometry_center)

    layers_thickness = [
        layer_to_thickness[layer]
        for layer in component.get_layers()
        if layer in layer_to_thickness
    ]

    t_core = max(layers_thickness)
    cell_thickness = tpml + t_clad_bot + t_core + t_clad_top + tpml if is_3d else 0

    cell_size = mp.Vector3(
        component.xsize + 2 * tpml,
        component.ysize + 2 * tpml,
        cell_thickness,
    )

    geometry = []
    layer_to_polygons = component_extended.get_polygons(by_spec=True)
    for layer, polygons in layer_to_polygons.items():
        if layer in layer_to_thickness and layer in layer_to_material:
            height = layer_to_thickness[layer] if is_3d else mp.inf
            zmin_um = layer_to_zmin[layer] if is_3d else 0
            # center = mp.Vector3(0, 0, (zmin_um + height) / 2)

            for polygon in polygons:
                vertices = [mp.Vector3(p[0], p[1], zmin_um) for p in polygon]
                material_name = layer_to_material[layer]
                material = get_material(name=material_name)
                geometry.append(
                    mp.Prism(
                        vertices=vertices,
                        height=height,
                        sidewall_angle=layer_to_sidewall_angle[layer],
                        material=material,
                        # center=center
                    )
                )

    freqs = 1 / wavelengths
    fcen = np.mean(freqs)
    frequency_width = dfcen * fcen

    # Add source
    port = component.ports[port_source_name]
    angle = port.orientation
    width = port.width + 2 * port_margin
    size_x = width * abs(np.sin(angle * np.pi / 180))
    size_y = width * abs(np.cos(angle * np.pi / 180))
    size_x = 0 if size_x < 0.001 else size_x
    size_y = 0 if size_y < 0.001 else size_y
    size_z = cell_thickness - 2 * tpml if is_3d else 20
    size = [size_x, size_y, size_z]
    center = port.center.tolist() + [0]  # (x, y, z=0)

    field_monitor_port = component.ports[port_field_monitor_name]
    field_monitor_point = field_monitor_port.center.tolist() + [0]  # (x, y, z=0)

    sources = [
        mp.EigenModeSource(
            src=mp.GaussianSource(fcen, fwidth=frequency_width),
            size=size,
            center=center,
            eig_band=1,
            eig_parity=mp.NO_PARITY if is_3d else mp.EVEN_Y + mp.ODD_Z,
            eig_match_freq=True,
        )
    ]

    sim = mp.Simulation(
        resolution=res,
        cell_size=cell_size,
        boundary_layers=[mp.PML(tpml)],
        sources=sources,
        geometry=geometry,
        default_material=get_material(name=clad_material),
        # geometry_center=geometry_center,
    )

    # Add port monitors dict
    monitors = {}
    for port_name in component.ports.keys():
        port = component.ports[port_name]
        angle = port.orientation
        width = port.width + 2 * port_margin
        size_x = width * abs(np.sin(angle * np.pi / 180))
        size_y = width * abs(np.cos(angle * np.pi / 180))
        size_x = 0 if size_x < 0.001 else size_x
        size_y = 0 if size_y < 0.001 else size_y
        size = mp.Vector3(size_x, size_y, size_z)
        size = [size_x, size_y, size_z]

        # if monitor has a source move monitor inwards
        length = -distance_source_to_monitors if port_name == port_source_name else 0
        xy_shifted = move_polar_rad_copy(
            np.array(port.center), angle=angle * np.pi / 180, length=length
        )
        center = xy_shifted.tolist() + [0]  # (x, y, z=0)
        m = sim.add_mode_monitor(freqs, mp.ModeRegion(center=center, size=size))
        m.z = 0
        monitors[port_name] = m
    return dict(
        sim=sim,
        cell_size=cell_size,
        freqs=freqs,
        monitors=monitors,
        sources=sources,
        field_monitor_point=field_monitor_point,
        port_source_name=port_source_name,
    )
예제 #13
0
from __future__ import division, print_function

import meep as mp
import math

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

pml_layers = mp.PML(dpml)

fcen = 1.0
df = 0.4
src_cmpt = mp.Ez

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

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

sim = mp.Simulation(cell_size=cell,
                    resolution=resolution,
                    sources=[sources],
                    symmetries=symmetries,
sources = [
    mp.Source(
        mp.GaussianSource(frequency=frequency, fwidth=frequencyWidth),
        component=mp.Ex,
        center=mp.Vector3(0, 0, -materialThickness / 2),
    )
]

geometry = [
    mp.Block(mp.Vector3(mp.inf, mp.inf, materialThickness + pmlThickness),
             center=mp.Vector3(0, 0, materialThickness / 2 + pmlThickness / 2),
             material=mp.Medium(index=2))
]

pmlLayers = [mp.PML(1.0)]

simulation = mp.Simulation(cell_size=cellSize,
                           sources=sources,
                           resolution=resolution,
                           boundary_layers=pmlLayers,
                           k_point=kVector)

incidentRegion = mp.FluxRegion(center=mp.Vector3(0, 0, -materialThickness / 4))
incidentFluxMonitor = simulation.add_flux(frequency, frequencyWidth,
                                          numberFrequencies, incidentRegion)

simulation.run(until_after_sources=mp.stop_when_fields_decayed(
    20, mp.Ex, transmissionMonitorLocation, powerDecayTarget))
fieldEx = np.real(
    simulation.get_array(center=mp.Vector3(0, 0, 0),
예제 #15
0
import meep as mp
import numpy as np
import matplotlib.pyplot as plt

resolution = 50  # pixels/μm

cell_size = mp.Vector3(14, 14)

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

# rotation angle (in degrees) of waveguide, counter clockwise (CCW) around z-axis
rot_angle = np.radians(20)

w = 1.0  # width of waveguide

geometry = [
    mp.Block(center=mp.Vector3(),
             size=mp.Vector3(mp.inf, w, mp.inf),
             e1=mp.Vector3(1).rotate(mp.Vector3(z=1), rot_angle),
             e2=mp.Vector3(y=1).rotate(mp.Vector3(z=1), rot_angle),
             material=mp.Medium(epsilon=12))
]

fsrc = 0.15  # frequency of eigenmode or constant-amplitude source
kx = 0.4  # initial guess for wavevector in x-direction of eigenmode
bnum = 1  # band number of eigenmode

kpoint = mp.Vector3(kx).rotate(mp.Vector3(z=1), rot_angle)

compute_flux = True  # compute flux (True) or plot the field profile (False)
from __future__ import division
import meep as mp
import numpy as np
import matplotlib.pyplot as plt
import math
from meep.materials import Au

pml_layers = [mp.PML(0.4)]

#Au = mp.Medium(index=math.pow(6.9,(1/2)))
dpml = 0.4
minwavelength = 0.4
maxwavelength = 0.8
minf = 1 / maxwavelength
maxf = 1 / minwavelength
fcen = (maxf + minf) / 2
df = maxf - minf
nfreq = 100
resolution = 100

upperside_without_flux = []
otherside_without_flux = []
upperside_with_flux = []
lightside_with_flux = []
otherside_with_flux = []
indecentflux = []

for i in (np.arange(1, 5)):
    r = i * 0.005
    sx = 12 * r + 2 * dpml
    cell = mp.Vector3(sx, sx)
예제 #17
0
import meep as mp
import numpy as np
import matplotlib.pyplot as plt
import PyMieScatt as ps

r = 1.0  # radius of sphere

frq_cen = 1.0

resolution = 20  # pixels/um

dpml = 0.5
dair = 1.5  # at least 0.5/frq_cen padding between source and near-field monitor

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

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

# circularly-polarized source with propagation axis along x
# is_integrated=True necessary for any planewave source extending into PML
sources = [
    mp.Source(mp.GaussianSource(frq_cen,
                                fwidth=0.2 * frq_cen,
                                is_integrated=True),
              center=mp.Vector3(-0.5 * s + dpml),
              size=mp.Vector3(0, s, s),
              component=mp.Ez),
    mp.Source(mp.GaussianSource(frq_cen,
                                fwidth=0.2 * frq_cen,
                                is_integrated=True),
from meep.simulation import at_every
import numpy as np
results = []
for j in range(1, 10):
    simruntime = 60

    CdSe = mp.Medium(index=2.52)
    Glass = mp.Medium(index=1.5)
    ZnO = mp.Medium(index=2.21)

    celly = 4
    fingersize = 0.05 * j

    cell = mp.Vector3(7.5, celly)
    polarization = mp.Ez
    pml_layers = [mp.Absorber(1, mp.X, mp.Low), mp.PML(1, mp.X, mp.High)]

    resolution = 80

    sources = [
        mp.Source(mp.ContinuousSource(wavelength=0.550, end_time=20),
                  component=polarization,
                  center=mp.Vector3(-1.5, 0))
    ]

    # sources.append(mp.Source(mp.ContinuousSource(wavelength=0.550, end_time=20),
    #                          component=polarization,
    #                          center=mp.Vector3(-1.6, 3)))

    # sources.append(mp.Source(mp.ContinuousSource(wavelength=0.550, end_time=20),
    #                          component=polarization,
예제 #19
0
    period_line=period_line,
    period_plane=period_plane,
    plane_center=plane_center,
    line_center=line_center,
    plane_size=plane_size,
    line_size=line_size,
    time_is_after_source=time_is_after_source,
    run_time=run_time,
    series=series,
    home=home)

#%% LAYOUT CONFIGURATION

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

boundary_layers = [mp.PML(thickness=pml_width)]

source_center = -0.5*cell_width + pml_width
sources = [mp.Source(mp.ContinuousSource(wavelength=wlen, 
                                         is_integrated=is_integrated),
                     center=mp.Vector3(source_center),
                     size=mp.Vector3(0, cell_width, cell_width),
                     component=mp.Ez)]

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

enlapsed = []

path = os.path.join(home, folder, "{}Results".format(series))
if not os.path.isdir(path): vs.new_dir(path)
file = lambda f : os.path.join(path, f)
예제 #20
0
def _simulate(
        wlens: List[float],
        sim_region: goos.Box3d,
        pml_thickness: List[float],
        geometry: List[mp.GeometricObject],
        resolution: float,
        sources: List[SimSourceImpl],
        outputs: List[SimOutputImpl],
        sim_timing: SimulationTiming,
        adjoint_grad_val: goos.ArrayFlow.Grad = None,
        adjoint_sources: List[SimOutput] = None,
        adjoint: bool = False,
) -> Tuple[List[goos.Flow], List[SimOutput]]:
    """Runs Meep EM simulation.

    This function factors out the core Meep simulation functionality so that
    we can run the simulation in another process. The idea is to pickle (dill)
    the arguments to this function, which is sent to another process(es) to
    run the simulation.
    """
    # Note that we have to compute PML here because apparently `mp.PML` is
    # a SWIG object, which cannot be pickled.
    pml_layers = []
    for thickness, direction, side in zip(
            pml_thickness, [mp.X, mp.X, mp.Y, mp.Y, mp.Z, mp.Z],
        [mp.Low, mp.High, mp.Low, mp.High, mp.Low, mp.High]):
        pml_layers.append(mp.PML(thickness, direction=direction, side=side))

    sim = mp.Simulation(
        cell_size=sim_region.extents,
        geometry_center=sim_region.center,
        boundary_layers=pml_layers,
        geometry=geometry,
        sources=[],
        resolution=resolution,
        force_complex_fields=adjoint,
    )

    # Add the sources. Because the sources may depend on the permittivity
    # distribution, we call `init_sim` to setup permittivity and then call
    # `change_sources` to add the new source list.
    sim.init_sim()

    for src in sources:
        src.before_sim(sim)

    if adjoint:
        for out, g in zip(adjoint_sources, adjoint_grad_val):
            out.before_adjoint_sim(sim, g)

    for out in outputs:
        out.before_sim(sim)

    stop_conds = [sim_timing.max_timesteps] + [
        cond.build()
        for cond in _generate_stopping_conds(sim_timing.stopping_conditions)
    ]
    if sim_timing.until_after_sources:
        sim.run(until_after_sources=stop_conds)
    else:
        sim.run(until=stop_conds)

    results = [out.eval(sim) for out in outputs]

    for out in outputs:
        out.after_sim()

    return results, outputs
예제 #21
0
    def test_get_point(self):
        sxy = 6                 # cell size
        dpml = 1                # thickness of PML

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

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

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

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

        sim.run(until_after_sources=100)

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

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

        x = np.linspace(-0.865692,2.692867,29)
        for j in range(x.size):
            self.assertAlmostEqual(np.real(sim.get_field_point(mp.Ez, mp.Vector3(x[j],-0.394862))),ez_ref[j],places=10)
            self.assertAlmostEqual(sim.get_epsilon_point(mp.Vector3(x[j],2.967158)),eps_ref[j],places=10)
예제 #22
0
def binary_grating_diffraction(gp, gh, gdc, theta):

    resolution = 50  # pixels/μm

    dpml = 1.0  # PML thickness
    dsub = 3.0  # substrate thickness
    dpad = 3.0  # length of padding between grating and PML

    sx = dpml + dsub + gh + dpad + dpml
    sy = gp

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

    wvl = 0.5  # center wavelength
    fcen = 1 / wvl  # center frequency
    df = 0.05 * fcen  # frequency width

    ng = 1.5
    glass = mp.Medium(index=ng)

    # rotation angle of incident planewave; counter clockwise (CCW) about Z axis, 0 degrees along +X axis
    theta_in = math.radians(theta)

    eig_parity = mp.EVEN_Z

    # k (in source medium) with correct length (plane of incidence: XY)
    k = mp.Vector3(fcen * ng).rotate(mp.Vector3(z=1), theta_in)

    if theta_in == 0:
        k = mp.Vector3()
        eig_parity += mp.ODD_Y

    def pw_amp(k, x0):
        def _pw_amp(x):
            return cmath.exp(1j * 2 * math.pi * k.dot(x + x0))

        return _pw_amp

    src_pt = mp.Vector3(-0.5 * sx + dpml, 0, 0)
    sources = [
        mp.Source(mp.GaussianSource(fcen, fwidth=df),
                  component=mp.Hz,
                  center=src_pt,
                  size=mp.Vector3(0, sy, 0),
                  amp_func=pw_amp(k, src_pt))
    ]

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

    tran_pt = mp.Vector3(0.5 * sx - dpml, 0, 0)
    tran_mon = sim.add_flux(
        fcen, 0, 1, mp.FluxRegion(center=tran_pt, size=mp.Vector3(0, sy, 0)))

    sim.run(until_after_sources=50)

    input_flux = mp.get_fluxes(tran_mon)

    sim.reset_meep()

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

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

    tran_mon = sim.add_mode_monitor(
        fcen, 0, 1, mp.FluxRegion(center=tran_pt, size=mp.Vector3(0, sy, 0)))

    sim.run(until_after_sources=100)

    # number of (non-evanescent) transmitted orders
    nm_t = np.floor((fcen - k.y) * gp) - np.ceil((-fcen - k.y) * gp)
    if theta_in == 0:
        nm_t = nm_t / 2
    nm_t = int(nm_t) + 1

    bands = range(1, nm_t + 1)

    if theta_in == 0:
        orders = range(0, nm_t)
    else:
        orders = range(int(np.ceil((-fcen - k.y) * gp)),
                       int(np.floor((fcen - k.y) * gp)) + 1)

    eig_sum = 0
    dp_sum = 0

    for band, order in zip(bands, orders):
        res = sim.get_eigenmode_coefficients(tran_mon, [band],
                                             eig_parity=eig_parity)
        if res is not None:
            tran_eig = abs(res.alpha[0, 0, 0])**2 / input_flux[0]
            if theta_in == 0:
                tran_eig = 0.5 * tran_eig
        else:
            tran_eig = 0
        eig_sum += tran_eig

        res = sim.get_eigenmode_coefficients(
            tran_mon,
            mp.DiffractedPlanewave((0, order, 0), mp.Vector3(0, 1, 0), 0, 1))
        if res is not None:
            tran_dp = abs(res.alpha[0, 0, 0])**2 / input_flux[0]
            if (theta_in == 0) and (order == 0):
                tran_dp = 0.5 * tran_dp
        else:
            tran_dp = 0
        dp_sum += tran_dp

        if theta_in == 0:
            err = abs(tran_eig - tran_dp) / tran_eig
            print("tran:, {:2d}, {:.8f}, {:2d}, {:.8f}, {:.8f}".format(
                band, tran_eig, order, tran_dp, err))
        else:
            print("tran:, {:2d}, {:.8f}, {:2d}, {:.8f}".format(
                band, tran_eig, order, tran_dp))

    flux = mp.get_fluxes(tran_mon)
    t_flux = flux[0] / input_flux[0]
    if (theta_in == 0):
        t_flux = 0.5 * t_flux

    err = abs(dp_sum - t_flux) / t_flux
    print("flux:, {:.8f}, {:.8f}, {:.8f}, {:.8f}".format(
        eig_sum, dp_sum, t_flux, err))
예제 #23
0
import math

resolution = 60  # pixels/μm

dpml = 1.0  # PML thickness
dsub = 3.0  # substrate thickness
dpad = 3.0  # padding between grating and PML
gp = 10.0  # grating period
gh = 0.5  # grating height
gdc = 0.5  # grating duty cycle

sx = dpml + dsub + gh + dpad + dpml
sy = gp

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

wvl_min = 0.4  # min wavelength
wvl_max = 0.6  # max wavelength
fmin = 1 / wvl_max  # min frequency
fmax = 1 / wvl_min  # max frequency
fcen = 0.5 * (fmin + fmax)  # center frequency
df = fmax - fmin  # frequency width

src_pt = mp.Vector3(-0.5 * sx + dpml + 0.5 * dsub, 0, 0)
sources = [
    mp.Source(mp.GaussianSource(fcen, fwidth=df),
              component=mp.Ez,
              center=src_pt,
              size=mp.Vector3(0, sy, 0))
]
예제 #24
0
def main(args):
    cell_zmax = 0.5 * cell_thickness if args.three_d else 0
    cell_zmin = -0.5 * cell_thickness if args.three_d else 0
    si_zmax = 0.5 * t_Si if args.three_d else 10
    si_zmin = -0.5 * t_Si if args.three_d else -10

    # read cell size, volumes for source region and flux monitors,
    # and coupler geometry from GDSII file
    upper_branch = mp.get_GDSII_prisms(silicon, gdsII_file, UPPER_BRANCH_LAYER,
                                       si_zmin, si_zmax)
    lower_branch = mp.get_GDSII_prisms(silicon, gdsII_file, LOWER_BRANCH_LAYER,
                                       si_zmin, si_zmax)

    cell = mp.GDSII_vol(gdsII_file, CELL_LAYER, cell_zmin, cell_zmax)
    p1 = mp.GDSII_vol(gdsII_file, PORT1_LAYER, si_zmin, si_zmax)
    p2 = mp.GDSII_vol(gdsII_file, PORT2_LAYER, si_zmin, si_zmax)
    p3 = mp.GDSII_vol(gdsII_file, PORT3_LAYER, si_zmin, si_zmax)
    p4 = mp.GDSII_vol(gdsII_file, PORT4_LAYER, si_zmin, si_zmax)
    src_vol = mp.GDSII_vol(gdsII_file, SOURCE_LAYER, si_zmin, si_zmax)

    # displace upper and lower branches of coupler (as well as source and flux regions)
    if args.d != default_d:
        delta_y = 0.5 * (args.d - default_d)
        delta = mp.Vector3(y=delta_y)
        p1.center += delta
        p2.center -= delta
        p3.center += delta
        p4.center -= delta
        src_vol.center += delta
        cell.size += 2 * delta
        for np in range(len(lower_branch)):
            lower_branch[np].center -= delta
            for nv in range(len(lower_branch[np].vertices)):
                lower_branch[np].vertices[nv] -= delta
        for np in range(len(upper_branch)):
            upper_branch[np].center += delta
            for nv in range(len(upper_branch[np].vertices)):
                upper_branch[np].vertices[nv] += delta

    geometry = upper_branch + lower_branch

    if args.three_d:
        oxide_center = mp.Vector3(z=-0.5 * t_oxide)
        oxide_size = mp.Vector3(cell.size.x, cell.size.y, t_oxide)
        oxide_layer = [
            mp.Block(material=oxide, center=oxide_center, size=oxide_size)
        ]
        geometry = geometry + oxide_layer

    sources = [
        mp.EigenModeSource(
            src=mp.GaussianSource(fcen, fwidth=df),
            volume=src_vol,
            eig_parity=mp.NO_PARITY if args.three_d else mp.EVEN_Y + mp.ODD_Z)
    ]

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

    mode1 = sim.add_mode_monitor(fcen, 0, 1, mp.ModeRegion(volume=p1))
    mode2 = sim.add_mode_monitor(fcen, 0, 1, mp.ModeRegion(volume=p2))
    mode3 = sim.add_mode_monitor(fcen, 0, 1, mp.ModeRegion(volume=p3))
    mode4 = sim.add_mode_monitor(fcen, 0, 1, mp.ModeRegion(volume=p4))

    sim.run(until_after_sources=100)

    # S parameters
    p1_coeff = sim.get_eigenmode_coefficients(
        mode1, [1],
        eig_parity=mp.NO_PARITY if args.three_d else mp.EVEN_Y +
        mp.ODD_Z).alpha[0, 0, 0]
    p2_coeff = sim.get_eigenmode_coefficients(
        mode2, [1],
        eig_parity=mp.NO_PARITY if args.three_d else mp.EVEN_Y +
        mp.ODD_Z).alpha[0, 0, 1]
    p3_coeff = sim.get_eigenmode_coefficients(
        mode3, [1],
        eig_parity=mp.NO_PARITY if args.three_d else mp.EVEN_Y +
        mp.ODD_Z).alpha[0, 0, 0]
    p4_coeff = sim.get_eigenmode_coefficients(
        mode4, [1],
        eig_parity=mp.NO_PARITY if args.three_d else mp.EVEN_Y +
        mp.ODD_Z).alpha[0, 0, 0]

    # transmittance
    p2_trans = abs(p2_coeff)**2 / abs(p1_coeff)**2
    p3_trans = abs(p3_coeff)**2 / abs(p1_coeff)**2
    p4_trans = abs(p4_coeff)**2 / abs(p1_coeff)**2

    print("trans:, {:.2f}, {:.6f}, {:.6f}, {:.6f}".format(
        args.d, p2_trans, p3_trans, p4_trans))
예제 #25
0
def main(args):
    resolution = 20      # pixels/um
    eps = 13             # epsilon of waveguide
    w = 1.2              # width of the  waveguide
    dpml = 1             # PML thickness
    largC = 16           # largura da celula
    altC = 16            # altura da celula

    sx = largC + dpml
    sy = altC + dpml

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


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


    def epsP(p):
       valorIm = -0.5 + math.pow(math.cos((p.y)*(2*math.pi/(altC/4))),2)
       return mp.Medium(epsilon=3, D_conductivity=2*math.pi*fcen*(valorIm)/3)
    epsP.do_averaging = True



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



#    AQUI ESTÁ A LINHA DE TESTE: USAMOS A FUNCAO PARA DEFINIR O EPSILON
#    geometry.append(mp.Block(size=mp.Vector3(mp.inf,w,mp.inf)))
    geometry.append(mp.Block(center=mp.Vector3(),size=mp.Vector3(mp.inf,altC,mp.inf),material=epsP))




    pml_layers = [mp.PML(1.0)]


    src = [mp.Source(mp.GaussianSource(fcen, fwidth=df),
                     component=mp.Ey,
                     center=mp.Vector3(-0.5*sx+dpml), # fonte na esquerda; para colocar na direita usar 0.5*sx - dpml
                     size=mp.Vector3(0,w))]


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


    sim.run(mp.at_beginning(mp.output_epsilon),
            mp.to_appended("hz",mp.at_every(0.4,mp.output_hfield_z)),
            until=300)



    epsilon0 = sim.get_array(center=mp.Vector3(), size=cell, component=mp.Dielectric)
    plt.figure()
    plt.imshow(epsilon0.transpose(), interpolation='spline36', cmap='RdBu')
    plt.axis('off')
    plt.savefig('epsilon.png',format='png')
    plt.show()
예제 #26
0
    decay = meep.Ex
else:
    source = lambda sim: meep_ext.y_polarized_plane_wave(sim, src_time)
    decay = meep.Ey

### monitor info
particle_monitor_gap = 50 * nm
pml_monitor_gap = 50 * nm
norm_file_ext = 'norm_box'
monitor_size = [
    box[0] + 2 * particle_monitor_gap, box[1] + 2 * particle_monitor_gap,
    box[2] + 2 * particle_monitor_gap
]

### grid
pml = meep.PML(15 / resolution)
lx = box[0] + 2 * particle_monitor_gap + 2 * pml_monitor_gap + 2 * pml.thickness
ly = box[1] + 2 * particle_monitor_gap + 2 * pml_monitor_gap + 2 * pml.thickness
lz = box[2] + 2 * particle_monitor_gap + 2 * pml_monitor_gap + 2 * pml.thickness
cell = meep.Vector3(lx, ly, lz)
Nx, Ny, Nz = map(round, cell * resolution)


@job.cache
def norm_sim():
    """perform normalization simulation"""
    norm = meep.Simulation(cell_size=cell,
                           boundary_layers=[pml],
                           geometry=[],
                           default_material=medium,
                           resolution=resolution)
예제 #27
0
cell = mp.Vector3(sx, sy, 0)

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

geometry = [blk]

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

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

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

# add sources
sim.sources = [
    mp.Source(mp.GaussianSource(fcen, fwidth=df), mp.Hz, mp.Vector3())
]

# run until sources are finished (and no later)
sim._run_sources_until(0, [])

# get 1D and 2D array slices
xMin = -0.25 * sx
xMax = +0.25 * sx
yMin = -0.15 * sy
yMax = +0.15 * sy
예제 #28
0
from utils import ApproxComparisonTestCase

MonitorObject = Enum('MonitorObject', 'EIGENMODE DFT')

resolution = 30

silicon = mp.Medium(epsilon=12)
sapphire = mp.Medium(epsilon_diag=(10.225, 10.225, 9.95),
                     epsilon_offdiag=(-0.825, -0.55 * np.sqrt(3 / 2),
                                      0.55 * np.sqrt(3 / 2)))

sxy = 5.0
cell_size = mp.Vector3(sxy, sxy, 0)

dpml = 1.0
pml_xy = [mp.PML(thickness=dpml)]
pml_x = [mp.PML(thickness=dpml, direction=mp.X)]

eig_parity = mp.EVEN_Y + mp.ODD_Z

design_region_size = mp.Vector3(1.5, 1.5)
design_region_resolution = int(2 * resolution)
Nx, Ny = int(design_region_size.x * design_region_resolution), int(
    design_region_size.y * design_region_resolution)

## ensure reproducible results
rng = np.random.RandomState(9861548)

## random design region
p = 0.5 * rng.rand(Nx * Ny)
예제 #29
0
import matplotlib.pyplot as plt


# In[5]:


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)]
예제 #30
0
    def _load_dump_structure(self, chunk_file=False, chunk_sim=False):
        from meep.materials import Al
        resolution = 50
        cell = mp.Vector3(5, 5)
        sources = mp.Source(src=mp.GaussianSource(1, fwidth=0.2),
                            center=mp.Vector3(),
                            component=mp.Ez)
        one_by_one = mp.Vector3(1, 1, mp.inf)
        geometry = [
            mp.Block(material=Al, center=mp.Vector3(), size=one_by_one),
            mp.Block(material=mp.Medium(epsilon=13),
                     center=mp.Vector3(1),
                     size=one_by_one)
        ]
        pml_layers = [mp.PML(0.5)]

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

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

        sample_point = mp.Vector3(0.12, -0.29)
        ref_field_points = []

        def get_ref_field_point(sim):
            p = sim.get_field_point(mp.Ez, sample_point)
            ref_field_points.append(p.real)

        sim1.run(mp.at_every(5, get_ref_field_point), until=50)
        dump_fn = 'test_load_dump_structure.h5'
        dump_chunk_fname = None
        chunk_layout = None
        sim1.dump_structure(dump_fn)
        if chunk_file:
            dump_chunk_fname = 'test_load_dump_structure_chunks.h5'
            sim1.dump_chunk_layout(dump_chunk_fname)
            chunk_layout = dump_chunk_fname
        if chunk_sim:
            chunk_layout = sim1

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

        field_points = []

        def get_field_point(sim):
            p = sim.get_field_point(mp.Ez, sample_point)
            field_points.append(p.real)

        sim.run(mp.at_every(5, get_field_point), until=50)

        for ref_pt, pt in zip(ref_field_points, field_points):
            self.assertAlmostEqual(ref_pt, pt)

        mp.all_wait()
        if mp.am_master():
            os.remove(dump_fn)
            if dump_chunk_fname:
                os.remove(dump_chunk_fname)