Exemple #1
0
def main(args):

    n = 3.4  # index of waveguide
    w = 1  # width of waveguide
    r = 1  # inner radius of ring
    pad = 4  # padding between waveguide and edge of PML
    dpml = 32  # thickness of PML

    sr = r + w + pad + dpml  # radial size (cell is from 0 to sr)
    dimensions = mp.CYLINDRICAL
    cell = mp.Vector3(sr, 0, 0)

    # in cylindrical coordinates, the phi (angular) dependence of the fields
    # is given by exp(i m phi), where m is given by:
    m = args.m

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

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

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

    fcen = args.fcen  # pulse center frequency
    df = args.df  # pulse frequency width
    sources = [
        mp.Source(src=mp.GaussianSource(fcen, fwidth=df),
                  component=mp.Ez,
                  center=mp.Vector3(r + 0.1))
    ]

    # note that the r -> -r mirror symmetry is exploited automatically

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

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

    # Output fields for one period at the end.  (If we output
    # at a single time, we might accidentally catch the Ez field when it is
    # almost zero and get a distorted view.)  We'll append the fields
    # to a file to get an r-by-t picture.  We'll also output from -sr to -sr
    # instead of from 0 to sr.
    sim.run(mp.in_volume(
        mp.Volume(center=mp.Vector3(), size=mp.Vector3(2 * sr)),
        mp.at_beginning(mp.output_epsilon),
        mp.to_appended("ez", mp.at_every(1 / fcen / 20, mp.output_efield_z))),
            until=1 / fcen)
Exemple #2
0
 def get_step_funcs(self):
     sf = {self._get_meep_output_comp(f) for f in self.static_fields}
     sf = (mp.at_beginning(f) for f in sf)
     df = {self._get_meep_output_comp(f) for f in self.dynamic_fields}
     df = (mp.at_every(self.dt, f) for f in df)
     volume = mp.in_volume(mp.Volume(center=self.size / 2, size=self.size))
     fields = mp.with_prefix(f'{results_dir}/', *sf, *df)
     return volume, fields
Exemple #3
0
 def test_in_volume(self):
     sim = self.init_simple_simulation()
     sim.use_output_directory(self.temp_dir)
     sim.filename_prefix = 'test_in_volume'
     vol = mp.Volume(mp.Vector3(), size=mp.Vector3(x=2))
     sim.run(mp.at_end(mp.in_volume(vol, mp.output_efield_z)), until=200)
     fn = os.path.join(self.temp_dir, 'test_in_volume-ez-000200.00.h5')
     self.assertTrue(os.path.exists(fn))
    def test_animation_output(self):
        # ------------------------- #
        # Check over 2D domain
        # ------------------------- #

        sim = setup_sim() # generate 2D simulation
        
        Animate = mp.Animate2D(sim,fields=mp.Ez, realtime=False, normalize=False) # Check without normalization
        Animate_norm = mp.Animate2D(sim,mp.Ez,realtime=False,normalize=True) # Check with normalization

        # test both animation objects during same run
        sim.run(
            mp.at_every(1,Animate),
            mp.at_every(1,Animate_norm),
            until=5)
        
        # Test outputs
        Animate.to_mp4(5,'test_2D.mp4') # Check mp4 output
        Animate.to_gif(150,'test_2D.gif') # Check gif output
        Animate.to_jshtml(10) # Check jshtml output
        Animate_norm.to_mp4(5,'test_2D_norm.mp4') # Check mp4 output
        Animate_norm.to_gif(150,'test_2D_norm.gif') # Check gif output
        Animate_norm.to_jshtml(10) # Check jshtml output

        # ------------------------- #
        # Check over 3D domain
        # ------------------------- #
        sim = setup_sim(5) # generate 2D simulation
        
        Animate_xy = mp.Animate2D(sim,fields=mp.Ey, realtime=False, normalize=True) # Check without normalization
        Animate_xz = mp.Animate2D(sim,mp.Ey,realtime=False,normalize=True) # Check with normalization

        # test both animation objects during same run
        sim.run(
            mp.at_every(1,mp.in_volume(mp.Volume(center=mp.Vector3(),size=mp.Vector3(sim.cell_size.x,sim.cell_size.y)),Animate_xy)),
            mp.at_every(1,mp.in_volume(mp.Volume(center=mp.Vector3(),size=mp.Vector3(sim.cell_size.x,0,sim.cell_size.z)),Animate_xz)),
            until=5)
        
        # Test outputs
        Animate_xy.to_mp4(5,'test_3D_xy.mp4') # Check mp4 output
        Animate_xy.to_gif(150,'test_3D_xy.gif') # Check gif output
        Animate_xy.to_jshtml(10) # Check jshtml output
        Animate_xz.to_mp4(5,'test_3D_xz.mp4') # Check mp4 output
        Animate_xz.to_gif(150,'test_3D_xz.gif') # Check gif output
        Animate_xz.to_jshtml(10) # Check jshtml output
Exemple #5
0
def main(args):

    n = 3.4     # index of waveguide
    w = 1       # width of waveguide
    r = 1       # inner radius of ring
    pad = 4     # padding between waveguide and edge of PML
    dpml = 32    # thickness of PML

    sr = r + w + pad + dpml  # radial size (cell is from 0 to sr)
    dimensions = mp.CYLINDRICAL
    cell = mp.Vector3(sr, 0, 0)

    # in cylindrical coordinates, the phi (angular) dependence of the fields
    # is given by exp(i m phi), where m is given by:
    m = args.m

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

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

    # If we don't want to excite a specific mode symmetry, we can just
    # put a single point source at some arbitrary place, pointing in some
    # arbitrary direction.  We will only look for Ez-polarized modes.

    fcen = args.fcen  # pulse center frequency
    df = args.df      # pulse frequency width
    sources = [mp.Source(src=mp.GaussianSource(fcen, fwidth=df),
                         component=mp.Ez,
                         center=mp.Vector3(r + 0.1))]

    # note that the r -> -r mirror symmetry is exploited automatically

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

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

    # Output fields for one period at the end.  (If we output
    # at a single time, we might accidentally catch the Ez field when it is
    # almost zero and get a distorted view.)  We'll append the fields
    # to a file to get an r-by-t picture.  We'll also output from -sr to -sr
    # instead of from 0 to sr.
    sim.run(mp.in_volume(mp.Volume(center=mp.Vector3(), size=mp.Vector3(2 * sr)),
                         mp.at_beginning(mp.output_epsilon),
                         mp.to_appended("ez", mp.at_every(1 / fcen / 20, mp.output_efield_z))),
            until=1 / fcen)
    def run(self, duration):
        boundary_layers = self._create_boundary_layers()
        self.sim = mp.Simulation(cell_size=self.cell_size,
                                 geometry_center=self.center,
                                 default_material=self.dev.default_material,
                                 geometry=self.dev.geometry,
                                 resolution=self.resolution,
                                 sources=self.sources,
                                 boundary_layers=boundary_layers,
                                 force_complex_fields=True)

        # adding flux regions
        for k, v in self.profilers.items():
            v.flux = self.sim.add_flux(1 / 1.55, 1, 256, v.get_flux_region())

        self.sim.run(mp.in_volume(self.dev.volume), until=duration)
        mp.all_wait()
Exemple #7
0
def main(args):
    resolution = 20 # 20 pixels per unit 1 um
    eps = 80 # epsilon of cylinder medium
    Mat1 = mp.Medium(epsilon=eps) # definition of the material
    dimensions = mp.CYLINDRICAL

    r = args.r # the value of cylinder radius
    rl = args.rl # the r/l ration is given, to obtain the l value l=r/rl
    x = args.x
    dpml = args.dpml
    dair = args.dair
    m=args.m

    w=1*x  
    h = r/rl # the height of the cylinder
    sr = r + dair + dpml
    sz = h + 2*dair + 2*dpml
    w_max=1.8
    w_min=0.2
    dw=w_max-w_min

    boundary_layers = [mp.PML(dpml)]
    Cyl = mp.Cylinder(material=Mat1, radius=r, height=h, center=mp.Vector3(0,0,0)) # make a cylinder with given parameters
    geometry = [Cyl]
    cell_size = mp.Vector3(sr,0,sz)

    #sources = [ mp.Source(mp.ContinuousSource(frequency = w), component=mp.Hz, center=mp.Vector3(r+dair,0,0)) ]
    sources = [mp.Source(mp.GaussianSource(w, fwidth=dw), component=mp.Hz, center=mp.Vector3(r+dair,0,0))]
    sim = mp.Simulation(resolution=resolution,
                        cell_size=cell_size,
                        boundary_layers=boundary_layers,
                        geometry=geometry,
                        sources=sources,
                        dimensions=dimensions,
                        m=m)
    sim.run(mp.in_volume(mp.Volume(center=mp.Vector3(), size=mp.Vector3(sr,0,sz)),
            mp.at_end(mp.output_epsilon, mp.output_efield_z)),
            mp.after_sources(mp.Harminv(mp.Hz, mp.Vector3(), w, dw)),
            until_after_sources=100)
Exemple #8
0
def main():
    # Prefix all output files with the command line argument
    file_prefix = sys.argv[1]
    # Number of pixels per micron
    resolution = 150
    # Simulation volume (um)
    cell_x = 2
    cell_y = 2
    cell_z = 2.5
    # Refractive indicies
    index_si = 3.6  # previously 3.4467
    index_sio2 = 1.444
    # Durations in units of micron/c
    duration = round(1.5 * cell_x + 2)
    num_timesteps = duration * resolution
    # Absorbing layer on boundary
    pml = 0.5
    # Geometry
    src_buffer = pml / 16
    nbn_buffer = src_buffer
    nbn_length = cell_x - 2 * pml - src_buffer - nbn_buffer
    nbn_center_x = (src_buffer + nbn_buffer) / 2
    wavelength = 1.55
    waveguide_width = 0.750  # 750 nm
    waveguide_height = 0.110  # 110 nm
    plane_shift_y = 0

    # nbn is 10/8 times thicker than in reality to have enough simulation pixels
    # so we reduce its absorption by a factor of 5/4 to compensate
    nbn_thickness_comp = 250 / resolution

    nbn_thickness = 0.008 * nbn_thickness_comp  # Actually 8 nm, but simulating this for 2 grid points
    nbn_width = 0.100  # 100 nm
    nbn_spacing = 0.120  # 120 nm

    # Also compensate the difference in index by the same amount
    nbn_base_index = 5.23  # Taken from Hu thesis p86
    nbn_index = (5.23 - index_si) / nbn_thickness_comp + index_si
    nbn_base_k = 5.82  # Taken from Hu thesis p86
    nbn_k = nbn_base_k / nbn_thickness_comp
    conductivity = 2 * math.pi * wavelength * nbn_k / nbn_index

    flux_length = cell_x - 2 * pml - 4 * src_buffer

    # Generate simulation obejcts
    cell = mp.Vector3(cell_x, cell_y, cell_z)
    freq = 1 / wavelength
    src_pt = mp.Vector3(-cell_x / 2 + pml + src_buffer, 0, 0)
    output_slice = mp.Volume(center=mp.Vector3(y=(3 * waveguide_height / 4) +
                                               plane_shift_y),
                             size=(cell_x, 0, cell_z))

    # Log important quantities
    print('ABSORBING RUN')
    print('File prefix: {}'.format(file_prefix))
    print('Duration: {}'.format(duration))
    print('Resolution: {}'.format(resolution))
    print('Dimensions: {} um, {} um, {} um'.format(cell_x, cell_y, cell_z))
    print('Wavelength: {} um'.format(wavelength))
    print('Si thickness: {} um'.format(waveguide_height))
    print('NbN thickness: {} um'.format(nbn_thickness))
    print('Si index: {}; SiO2 index: {}'.format(index_si, index_sio2))
    print('Absorber dimensions: {} um, {} um, {} um'.format(
        nbn_length, nbn_thickness, nbn_width))
    print('Absorber n (base value): {} ({}), k: {} ({})'.format(
        nbn_index, nbn_base_index, nbn_k, nbn_base_k))
    print('Absorber compensation for thickness: {}'.format(nbn_thickness_comp))
    print('Flux length: {} um'.format(flux_length))
    print('\n\n**********\n\n')

    default_material = mp.Medium(epsilon=1)

    # Physical geometry of the simulation
    geometry = [
        mp.Block(mp.Vector3(mp.inf, cell_y, mp.inf),
                 center=mp.Vector3(0, -cell_y / 2 + plane_shift_y, 0),
                 material=mp.Medium(epsilon=index_sio2)),
        mp.Block(mp.Vector3(mp.inf, waveguide_height, waveguide_width),
                 center=mp.Vector3(0, waveguide_height / 2 + plane_shift_y, 0),
                 material=mp.Medium(epsilon=index_si))
    ]

    # Absorber will only be appended to geometry for the second simulation
    absorber = [
        mp.Block(mp.Vector3(nbn_length, nbn_thickness, nbn_width),
                 center=mp.Vector3(
                     nbn_center_x, waveguide_height +
                     nbn_thickness / nbn_thickness_comp / 2 + plane_shift_y,
                     nbn_spacing / 2),
                 material=mp.Medium(epsilon=nbn_index,
                                    D_conductivity=conductivity)),
        mp.Block(mp.Vector3(nbn_length, nbn_thickness, nbn_width),
                 center=mp.Vector3(
                     nbn_center_x, waveguide_height +
                     nbn_thickness / nbn_thickness_comp / 2 + plane_shift_y,
                     -nbn_spacing / 2),
                 material=mp.Medium(epsilon=nbn_index,
                                    D_conductivity=conductivity)),
    ]

    # geometry += absorber

    # Calculate eigenmode source
    src_max_y = cell_y - 2 * pml
    src_max_z = cell_z - 2 * pml
    src_y = src_max_y
    src_z = src_max_z  # min(3 * waveguide_width, src_max_z)

    src_center_y = 0  # plane_shift_y

    sources = [
        mp.EigenModeSource(src=mp.ContinuousSource(frequency=freq),
                           center=mp.Vector3(-cell_x / 2 + pml + src_buffer,
                                             src_center_y, 0),
                           size=mp.Vector3(0, src_y, src_z),
                           eig_match_freq=True,
                           eig_parity=mp.ODD_Z,
                           eig_band=1)
    ]

    pml_layers = [mp.PML(pml)]

    # Pass all simulation parameters to meep
    sim = mp.Simulation(
        cell_size=cell,
        boundary_layers=pml_layers,
        geometry=geometry,
        sources=sources,
        resolution=resolution,
        # eps_averaging=False,
        default_material=default_material,
        symmetries=[mp.Mirror(mp.Z, phase=-1)])

    # Create flux monitors to calculate transmission and absorption
    fr_y = cell_y - 2 * pml
    fr_z = cell_z - 2 * pml

    # Reflected flux
    refl_fr = mp.FluxRegion(center=mp.Vector3(
        -0.5 * cell_x + pml + 2 * src_buffer, 0, 0),
                            size=mp.Vector3(0, fr_y, fr_z))
    refl = sim.add_flux(freq, 0, 1, refl_fr)

    # Transmitted flux
    tran_fr = mp.FluxRegion(center=mp.Vector3(
        0.5 * cell_x - pml - 2 * src_buffer, 0, 0),
                            size=mp.Vector3(0, fr_y, fr_z))
    tran = sim.add_flux(freq, 0, 1, tran_fr)

    # Run simulation, outputting the epsilon distribution and the fields in the
    # x-y plane every 0.25 microns/c
    sim.run(mp.at_beginning(mp.output_epsilon),
            mp.to_appended(
                "ez_z0",
                mp.in_volume(output_slice,
                             mp.at_every(2 / resolution, mp.output_efield_z))),
            until=duration)

    print('\n\n**********\n\n')

    sim.fields.synchronize_magnetic_fields()

    # For normalization run, save flux fields data for reflection plane
    no_absorber_refl_data = sim.get_flux_data(refl)
    # Save incident power for transmission plane
    no_absorber_tran_flux = mp.get_fluxes(tran)

    print("Flux: {}".format(no_absorber_tran_flux[0]))

    eps_data = sim.get_array(center=mp.Vector3(z=(nbn_spacing + nbn_width) /
                                               2),
                             size=mp.Vector3(cell_x, cell_y, 0),
                             component=mp.Dielectric)
    eps_cross_data = sim.get_array(center=mp.Vector3(x=cell_x / 4),
                                   size=mp.Vector3(0, cell_y, cell_z),
                                   component=mp.Dielectric)

    max_field = 1.5

    # Plot epsilon distribution
    if mp.am_master():
        plt.figure()
        plt.imshow(eps_data.transpose(),
                   interpolation='spline36',
                   cmap='binary')
        plt.axis('off')
        plt.savefig(file_prefix + '_Eps_A.png', dpi=300)
        print('Saved ' + file_prefix + '_Eps_A.png')

    # Plot field on x-y plane
    ez_data = sim.get_array(center=mp.Vector3(),
                            size=mp.Vector3(cell_x, cell_y, 0),
                            component=mp.Ez)
    if mp.am_master():
        plt.figure()
        plt.imshow(eps_data.transpose(),
                   interpolation='spline36',
                   cmap='binary')
        plt.imshow(ez_data.transpose(),
                   interpolation='spline36',
                   cmap='RdBu',
                   alpha=0.9)
        plt.axis('off')
        plt.savefig(file_prefix + '_Ez_A.png', dpi=300)
        print('Saved ' + file_prefix + '_Ez_A.png')

    energy_side_data = sim.get_array(center=mp.Vector3(),
                                     size=mp.Vector3(cell_x, cell_y, 0),
                                     component=mp.EnergyDensity)
    if mp.am_master():
        plt.figure()
        plt.imshow(eps_data.transpose(),
                   interpolation='spline36',
                   cmap='binary')
        plt.imshow(energy_side_data.transpose(),
                   interpolation='spline36',
                   cmap='hot',
                   alpha=0.9)
        plt.axis('off')
        plt.savefig(file_prefix + '_Pwr0_A.png', dpi=300)
        print('Saved ' + file_prefix + '_Pwr0_A.png')

    # Plot energy density on y-z plane
    energy_data = sim.get_array(center=mp.Vector3(),
                                size=mp.Vector3(0, cell_y, cell_z),
                                component=mp.EnergyDensity)
    if mp.am_master():
        plt.figure()
        plt.imshow(eps_cross_data, interpolation='spline36', cmap='binary')
        plt.imshow(energy_data,
                   interpolation='spline36',
                   cmap='hot',
                   alpha=0.9)
        plt.axis('off')
        plt.savefig(file_prefix + '_Pwr1_A.png', dpi=300)
        print('Saved ' + file_prefix + '_Pwr1_A.png')

    energy_data = sim.get_array(center=mp.Vector3(x=cell_x / 4),
                                size=mp.Vector3(0, cell_y, cell_z),
                                component=mp.EnergyDensity)
    if mp.am_master():
        plt.figure()
        plt.imshow(eps_cross_data, interpolation='spline36', cmap='binary')
        plt.imshow(energy_data,
                   interpolation='spline36',
                   cmap='hot',
                   alpha=0.9)
        plt.axis('off')
        plt.savefig(file_prefix + '_Pwr2_A.png', dpi=300)
        print('Saved ' + file_prefix + '_Pwr2_A.png')

    # Plot cross-sectional fields at several locations to ensure seeing nonzero fields
    num_x = 4
    num_y = 3
    fig, ax = plt.subplots(num_x, num_y)
    fig.suptitle('Cross Sectional Ez Fields')

    for i in range(num_x * num_y):
        monitor_x = i * (cell_x / 4) / (num_x * num_y)
        ez_cross_data = sim.get_array(center=mp.Vector3(x=monitor_x),
                                      size=mp.Vector3(0, cell_y, cell_z),
                                      component=mp.Ez)
        ax_num = i // num_y, i % num_y
        if mp.am_master():
            ax[ax_num].imshow(eps_cross_data,
                              interpolation='spline36',
                              cmap='binary')
            ax[ax_num].imshow(ez_cross_data,
                              interpolation='spline36',
                              cmap='RdBu',
                              alpha=0.9,
                              norm=ZeroNormalize(vmax=np.max(max_field)))
            ax[ax_num].axis('off')
            ax[ax_num].set_title('x = {}'.format(
                round(cell_x / 4 + i / resolution, 3)))
    if mp.am_master():
        plt.savefig(file_prefix + '_Ez_CS_A.png', dpi=300)
        print('Saved ' + file_prefix + '_Ez_CS_A.png')

    fig_e, ax_e = plt.subplots(num_x, num_y)
    fig_e.suptitle('Cross Sectional Energy Density')

    for i in range(num_x * num_y):
        monitor_x = i * (cell_x / 4) / (num_x * num_y)
        energy_cross_data = sim.get_array(center=mp.Vector3(x=monitor_x),
                                          size=mp.Vector3(0, cell_y, cell_z),
                                          component=mp.EnergyDensity)
        ax_num = i // num_y, i % num_y
        if mp.am_master():
            ax_e[ax_num].imshow(eps_cross_data,
                                interpolation='spline36',
                                cmap='binary')
            ax_e[ax_num].imshow(energy_cross_data,
                                interpolation='spline36',
                                cmap='hot',
                                alpha=0.9)
            ax_e[ax_num].axis('off')
            ax_e[ax_num].set_title('x = {}'.format(
                round(cell_x / 4 + i / resolution, 3)))
    if mp.am_master():
        plt.savefig(file_prefix + '_Pwr_CS_A.png', dpi=300)
        print('Saved ' + file_prefix + '_Pwr_CS_A.png')

    print('\n\n**********\n\n')

    # Reset simulation for absorption run
    """
    sim.reset_meep()

    geometry += absorber

    sim = mp.Simulation(cell_size=cell,
                        boundary_layers=pml_layers,
                        geometry=geometry,
                        sources=sources,
                        resolution=resolution,
                        eps_averaging=False,
                        default_material=default_material,
                        symmetries=[mp.Mirror(mp.Z, phase=-1)])

    refl = sim.add_flux(freq, 0, 1, refl_fr)
    tran = sim.add_flux(freq, 0, 1, tran_fr)

    sim.load_minus_flux_data(refl, no_absorber_refl_data)

    # Run simulation with absorber
    sim.run(mp.at_beginning(mp.output_epsilon),
            mp.to_appended("ez_z0",
                           mp.in_volume(output_slice,
                                        mp.at_every(0.25, mp.output_efield_z))),
            until=duration)

    print('\n\n**********\n\n')

    # Calculate transmission and absorption
    absorber_refl_flux = mp.get_fluxes(refl)
    absorber_tran_flux = mp.get_fluxes(tran)

    transmittance = absorber_tran_flux[0] / no_absorber_tran_flux[0]
    reflectance = absorber_refl_flux[0] / no_absorber_tran_flux[0]
    absorption = 1 - transmittance
    penetration_depth = - nbn_length / math.log(transmittance)

    print('Flux: {}'.format(absorber_tran_flux[0]))
    print("Transmittance: %f" % transmittance)
    print("Reflectance: %f" % reflectance)
    print("Absorption: {} over {} um".format(absorption, nbn_length))
    print("lambda = {} mm".format(penetration_depth / 1000))

    eps_data = sim.get_array(center=mp.Vector3(z=(nbn_spacing + nbn_width) / 2), size=mp.Vector3(cell_x, cell_y, 0), component=mp.Dielectric)

    max_field = 1

    # Plot epsilon distribution with absorber
    if mp.am_master():
        plt.figure()
        plt.imshow(eps_data.transpose(), interpolation='spline36', cmap='binary')
        plt.axis('off')
        plt.savefig(file_prefix + '_Eps_B.png', dpi=300)
        print('Saved ' + file_prefix + '_Eps_B.png')

    # Plot fields in x-y plane with absorber
    ez_data = sim.get_array(center=mp.Vector3(), size=mp.Vector3(cell_x, cell_y, 0), component=mp.Ez)
    if mp.am_master():
        plt.figure()
        plt.imshow(eps_data.transpose(), interpolation='spline36', cmap='binary')
        plt.imshow(ez_data.transpose(), interpolation='spline36', cmap='RdBu', alpha=0.9)
        plt.axis('off')
        plt.savefig(file_prefix + '_Ez_B.png', dpi=300)
        print('Saved ' + file_prefix + '_Ez_B.png')

    # Plot field cross sections with absorber
    eps_cross_data = sim.get_array(center=mp.Vector3(x=cell_x/4), size=mp.Vector3(0, cell_y, cell_z), component=mp.Dielectric)
    num_x = 4
    num_y = 3
    fig, ax = plt.subplots(num_x, num_y)
    fig.suptitle('Cross Sectional Ez Fields')
    for i in range(num_x * num_y):
        monitor_x = cell_x/4 + i / resolution
        ez_cross_data = sim.get_array(center=mp.Vector3(x=monitor_x), size=mp.Vector3(0, cell_y, cell_z), component=mp.Ez)
        ax_num = i // num_y, i % num_y
        if mp.am_master():
            ax[ax_num].imshow(eps_cross_data, interpolation='spline36', cmap='binary')
            ax[ax_num].imshow(ez_cross_data, interpolation='spline36', cmap='RdBu', alpha=0.9, norm=ZeroNormalize(vmax=np.max(max_field)))
            ax[ax_num].axis('off')
            ax[ax_num].set_title('x = {}'.format(round(cell_x/4 + i / resolution, 3)))
    if mp.am_master():
        plt.savefig(file_prefix + '_Ez_CS_B.png', dpi=300)
        print('Saved ' + file_prefix + '_Ez_CS_B.png')

    print('\n\n**********\n\n')
    """

    print('Program finished.')
Exemple #9
0
def simulation(plotMe,
               plotDir='simulationData/',
               jobSpecifier='direct-',
               mat=None):
    if os.getenv("X_USE_MPI") != "1":
        jobName = jobSpecifier + randomString()
    else:
        jobName = jobSpecifier
    start = time.time()

    if str(plotMe) == '1':
        os.makedirs(plotDir)
        import matplotlib
        #matplotlib.use('Agg')
        from matplotlib import pyplot as plt
        print('will plot')
    else:
        mp.quiet(True)
    __author__ = 'Marco Butz'

    pixelSize = mat['pixelSize']

    spectralWidth = 300 / mat['wavelength']
    modeFrequencyResolution = 1
    normOffset = pixelSize / 1000 * 10
    if mat['dims'][2] == 1:
        cell = mp.Vector3(mat['dims'][0]*pixelSize/1000, \
        mat['dims'][1]*pixelSize/1000, 0)
    else:
        cell = mp.Vector3(mat['dims'][0]*pixelSize/1000, \
        mat['dims'][1]*pixelSize/1000, mat['dims'][2]*pixelSize/1000)

    #generate hdf5 epsilon file
    if mp.am_master():
        h5f = h5py.File(jobName + '_eps.h5', 'a')
        h5f.create_dataset('epsilon', data=mat['epsilon'])
        h5f.close()

    sourceCenter = [
        (mat['modeSourcePos'][0][0] + mat['modeSourcePos'][1][0]) / 2,
        (mat['modeSourcePos'][0][1] + mat['modeSourcePos'][1][1]) / 2,
        (mat['modeSourcePos'][0][2] + mat['modeSourcePos'][1][2]) / 2
    ]
    sourceSize = [(mat['modeSourcePos'][1][0] - mat['modeSourcePos'][0][0]),
                  (mat['modeSourcePos'][1][1] - mat['modeSourcePos'][0][1]),
                  (mat['modeSourcePos'][1][2] - mat['modeSourcePos'][0][2])]

    modeNumModesToMeasure = []
    posModesToMeasure = []
    if not isinstance(mat['modeNumModesToMeasure'], Iterable):
        #this wraps stuff into an array if it has been squeezed before
        posModesToMeasure = [mat['posModesToMeasure']]
        modeNumModesToMeasure = [mat['modeNumModesToMeasure']]
        print('transformed')
    else:
        posModesToMeasure = mat['posModesToMeasure']
        modeNumModesToMeasure = mat['modeNumModesToMeasure']

    outputsModeNum = []
    outputsCenter = []
    outputsSize = []
    for i in range(0, mat['numModesToMeasure']):
        outputsCenter.append([
            (posModesToMeasure[i][0][0] + posModesToMeasure[i][1][0]) / 2,
            (posModesToMeasure[i][0][1] + posModesToMeasure[i][1][1]) / 2,
            (posModesToMeasure[i][0][2] + posModesToMeasure[i][1][2]) / 2
        ])
        outputsSize.append([
            (posModesToMeasure[i][1][0] - posModesToMeasure[i][0][0]),
            (posModesToMeasure[i][1][1] - posModesToMeasure[i][0][1]),
            (posModesToMeasure[i][1][2] - posModesToMeasure[i][0][2])
        ])
        outputsModeNum.append(modeNumModesToMeasure[i])

    for i in range(0, len(sourceCenter)):
        sourceCenter[i] = sourceCenter[i] * pixelSize / 1000 - cell[i] / 2
        sourceSize[i] = sourceSize[i] * pixelSize / 1000
    for i in range(0, len(outputsCenter)):
        for j in range(0, len(outputsCenter[i])):
            outputsCenter[i][
                j] = outputsCenter[i][j] * pixelSize / 1000 - cell[j] / 2
            outputsSize[i][j] = outputsSize[i][j] * pixelSize / 1000

    sources = [
        mp.EigenModeSource(
            src=mp.GaussianSource(wavelength=mat['wavelength'] / 1000,
                                  fwidth=spectralWidth),
            eig_band=mat['modeSourceNum'] + 1,
            center=mp.Vector3(sourceCenter[0], sourceCenter[1],
                              sourceCenter[2]),
            size=mp.Vector3(sourceSize[0], sourceSize[1], sourceSize[2]))
    ]
    """
    sources = [mp.EigenModeSource(src=mp.ContinuousSource(wavelength=mat['wavelength']/1000),
                                    eig_band=mat['modeSourceNum']+1,
                                    center=mp.Vector3(sourceCenter[0],sourceCenter[1],sourceCenter[2]),
                                    size=mp.Vector3(sourceSize[0],sourceSize[1],sourceSize[2]))]
    """

    resolution = 1000 / pixelSize  #pixels per micrometer

    pmlLayers = [mp.PML(pixelSize * 10 / 1000)]

    sim = mp.Simulation(cell_size=cell,
                        boundary_layers=pmlLayers,
                        geometry=[],
                        epsilon_input_file=jobName + '_eps.h5',
                        sources=sources,
                        resolution=resolution)
    #force_complex_fields=True) #needed for fdfd solver

    transmissionFluxes = []
    transmissionModes = []
    normFluxRegion = mp.FluxRegion(
        center=mp.Vector3(sourceCenter[0] + normOffset, sourceCenter[1],
                          sourceCenter[2]),
        size=mp.Vector3(sourceSize[0], sourceSize[1], sourceSize[2]),
        direction=mp.X)
    normMode = sim.add_mode_monitor(1000 / mat['wavelength'], spectralWidth,
                                    modeFrequencyResolution, normFluxRegion)
    normFlux = sim.add_flux(1000 / mat['wavelength'], spectralWidth,
                            modeFrequencyResolution, normFluxRegion)

    for i in range(0, len(outputsCenter)):
        transmissionFluxRegion = mp.FluxRegion(
            center=mp.Vector3(outputsCenter[i][0], outputsCenter[i][1],
                              outputsCenter[i][2]),
            size=mp.Vector3(outputsSize[i][0], outputsSize[i][1],
                            outputsSize[i][2]),
            direction=mp.X)
        transmissionFluxes.append(
            sim.add_flux(1000 / mat['wavelength'], spectralWidth,
                         modeFrequencyResolution, transmissionFluxRegion))
        transmissionModes.append(
            sim.add_mode_monitor(1000 / mat['wavelength'], spectralWidth,
                                 modeFrequencyResolution,
                                 transmissionFluxRegion))
    if str(plotMe) == '1':
        animation = mp.Animate2D(sim,
                                 fields=mp.Ey,
                                 realtime=False,
                                 normalize=True,
                                 field_parameters={
                                     'alpha': 0.8,
                                     'cmap': 'RdBu',
                                     'interpolation': 'none'
                                 },
                                 boundary_parameters={
                                     'hatch': 'o',
                                     'linewidth': 1.5,
                                     'facecolor': 'y',
                                     'edgecolor': 'b',
                                     'alpha': 0.3
                                 })
        sim.run(mp.at_every(0.5,mp.in_volume(mp.Volume(center=mp.Vector3(),size=mp.Vector3(sim.cell_size.x,sim.cell_size.y)),animation)), \
            until_after_sources=mp.stop_when_fields_decayed(20,mp.Ey,mp.Vector3(outputsCenter[0][0],outputsCenter[0][1],outputsCenter[0][2]),1e-5))
        #sim.init_sim()
        #sim.solve_cw(tol=10**-5,L=20)
        print('saving animation to ' +
              str(os.path.join(plotDir + 'animation.gif')))
        animation.to_gif(
            10,
            os.path.join(plotDir + 'inputMode_' + str(mat['modeSourceNum']) +
                         '_' + 'animation.gif'))
    else:
        sim.run(until_after_sources=mp.stop_when_fields_decayed(
            20, mp.Ey,
            mp.Vector3(outputsCenter[0][0], outputsCenter[0][1],
                       outputsCenter[0][2]), 1e-5))

    normModeCoefficients = sim.get_eigenmode_coefficients(
        normMode, [mat['modeSourceNum'] + 1], direction=mp.X)
    #print('input norm coefficients TE00: ', numpy.abs(sim.get_eigenmode_coefficients(normMode, [1], direction=mp.X).alpha[0][0][0])**2)
    #print('input norm coefficients TE10: ', numpy.abs(sim.get_eigenmode_coefficients(normMode, [3], direction=mp.X).alpha[0][0][0])**2)
    #print('input norm coefficients TE20: ', numpy.abs(sim.get_eigenmode_coefficients(normMode, [5], direction=mp.X).alpha[0][0][0])**2)
    #normFluxes = sim.get
    resultingModes = []
    resultingOverlaps = []
    for i in range(0, len(outputsCenter)):
        resultingModes.append(
            sim.get_eigenmode_coefficients(transmissionModes[i],
                                           [outputsModeNum[i] + 1],
                                           direction=mp.X))
        resultingOverlaps.append([
            numpy.abs(resultingModes[i].alpha[0][j][0])**2 /
            numpy.abs(normModeCoefficients.alpha[0][j][0])**2
            for j in range(modeFrequencyResolution)
        ])
        #resultingFluxes.append(sim.get_flux_data(transmissionFluxes[i]) / inputFlux)

    if str(plotMe) == '1':
        eps_data = sim.get_array(center=mp.Vector3(),
                                 size=cell,
                                 component=mp.Dielectric)

        plt.figure()
        for i in range(0, len(resultingModes)):
            frequencys = numpy.linspace(
                1000 / mat['wavelength'] - spectralWidth / 2,
                1000 / mat['wavelength'] + spectralWidth / 2,
                modeFrequencyResolution)
            plt.plot(1000 / frequencys,
                     resultingOverlaps[i],
                     label='Transmission TE' +
                     str(int(outputsModeNum[i] / 2)) + '0')
            print('mode coefficients: ' + str(resultingOverlaps[i]) +
                  ' for mode number ' + str(outputsModeNum[i]))
            print('mode coefficients: ' + str(resultingModes[i].alpha[0]) +
                  ' for mode number ' + str(outputsModeNum[i]))
        plt.legend()
        plt.xlabel('Wavelength [nm]')
        plt.savefig(
            os.path.join(plotDir + 'inputMode_' + str(mat['modeSourceNum']) +
                         '_' + 'mode_coefficients.png'))
        plt.close()

        if mat['dims'][2] == 1:
            plt.figure()
            plt.imshow(eps_data.transpose(),
                       interpolation='spline36',
                       cmap='binary')
            plt.axis('off')
            plt.savefig(
                os.path.join(plotDir + 'inputMode_' +
                             str(mat['modeSourceNum']) + '_' +
                             'debug_structure.png'))
            plt.close()

            inputFourier = [
                sources[0].src.fourier_transform(1000 / f)
                for f in range(1, 1000)
            ]
            plt.figure()
            plt.plot(inputFourier)
            plt.savefig(
                os.path.join(plotDir + 'inputMode_' +
                             str(mat['modeSourceNum']) + '_' +
                             'debug_input_fourier.png'))
            plt.close()

            ez_data = numpy.real(
                sim.get_array(center=mp.Vector3(), size=cell, component=mp.Ez))
            plt.figure()
            plt.imshow(eps_data.transpose(),
                       interpolation='spline36',
                       cmap='binary')
            plt.imshow(ez_data.transpose(),
                       interpolation='spline36',
                       cmap='RdBu',
                       alpha=0.9)
            plt.axis('off')
            plt.savefig(
                os.path.join(plotDir + 'inputMode_' +
                             str(mat['modeSourceNum']) + '_' +
                             'debug_overlay.png'))
            plt.close()

    #it might be possible to just reset the structure. will result in speedup
    mp.all_wait()
    sim.reset_meep()
    end = time.time()
    if mp.am_master():
        os.remove(jobName + '_eps.h5')
        print('simulation took ' + str(end - start))

    if __name__ == "__main__":
        jobNameWithoutPath = jobName.split('/')[len(jobName.split('/')) - 1]
        sio.savemat(
            "results_" + jobNameWithoutPath, {
                'pos': posModesToMeasure,
                'modeNum': modeNumModesToMeasure,
                'overlap': resultingOverlaps,
                'inputModeNum': mat['modeSourceNum'],
                'inputModePos': mat['modeSourcePos']
            })
    else:
        return {
            'pos': posModesToMeasure,
            'modeNum': modeNumModesToMeasure,
            'overlap': resultingOverlaps,
            'inputModeNum': mat['modeSourceNum'],
            'inputModePos': mat['modeSourcePos']
        }
Exemple #10
0
sx = 40
sy = 6
cell_size = mp.Vector3(sx + 2 * dpml, sy)

v0 = 1.0  # pulse center frequency
a = 0.2   # Gaussian envelope half-width
b = -0.5  # linear chirp rate (positive: up-chirp, negative: down-chirp)
t0 = 15   # peak time


def chirp(t): return np.exp(1j * 2 * np.pi * v0 * (t - t0)) * \
    np.exp(-a * (t - t0)**2 + 1j * b * (t - t0)**2)


sources = [mp.Source(src=mp.CustomSource(src_func=chirp),
                     center=mp.Vector3(-0.5 * sx),
                     size=mp.Vector3(y=sy),
                     component=mp.Ez)]

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

sim.run(mp.in_volume(mp.Volume(center=mp.Vector3(), size=mp.Vector3(sx, sy)),
                     mp.at_every(2.7, mp.output_efield_z)),
        until=t0 + 50)
def main(args):
    # Some parameters to describe the geometry:
    eps = 13  # dielectric constant of waveguide
    w = 1.2  # width of waveguide
    r = 0.36  # radius of holes
    d = 1.4  # defect spacing (ordinary spacing = 1)
    N = args.N  # number of holes on either side of defect

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

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

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

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

    geometry = [blk]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        sim.display_fluxes(trans)  # print out the flux spectrum
def run_simulation(save_prefix,
                   tip_radius=0.007,
                   cone_height=0.364,
                   trunk_radius=0.275,
                   n_tip=3.694,
                   k_tip=0.0,
                   fcen=1.25,
                   waves=7.5,
                   theta_deg=10,
                   sample=20,
                   sx=0.8,
                   sy=1.5,
                   sz=1.0,
                   dpml=0.1,
                   res=1000,
                   res_factor=0.2,
                   X_1=-0.2,
                   X_2=0.2,
                   Y_1=-0.2,
                   Y_2=0.2,
                   Z_1=-0.2,
                   Z_2=0.2,
                   x_mon_rat=1.0,
                   y_mon_rat=1.0,
                   z_mon_rat=1.0):

    #Interpolate to next resolution step for high-res region
    dx = 1 / res
    X_1 = np.floor(X_1 / dx) * dx
    X_2 = np.ceil(X_2 / dx) * dx
    Y_1 = np.floor(Y_1 / dx) * dx
    Y_2 = np.ceil(Y_2 / dx) * dx
    Z_1 = np.floor(Z_1 / dx) * dx
    Z_2 = np.ceil(Z_2 / dx) * dx

    #Dump all the settings to a file:
    settings_file = h5py.File(
        Path(sys.argv[0]).stem + '-' + save_prefix + '_settings.h5', 'w')
    settings_file.create_dataset('tip_radius', data=tip_radius)
    settings_file.create_dataset('cone_height', data=cone_height)
    settings_file.create_dataset('trunk_radius', data=trunk_radius)
    settings_file.create_dataset('n_tip', data=n_tip)
    settings_file.create_dataset('k_tip', data=k_tip)
    settings_file.create_dataset('fcen', data=fcen)
    settings_file.create_dataset('waves', data=waves)
    settings_file.create_dataset('theta_deg', data=theta_deg)
    settings_file.create_dataset('sample', data=sample)
    settings_file.create_dataset('sx', data=sx)
    settings_file.create_dataset('sy', data=sy)
    settings_file.create_dataset('sz', data=sz)
    settings_file.create_dataset('dpml', data=dpml)
    settings_file.create_dataset('res', data=res)
    settings_file.create_dataset('res_factor', data=res_factor)
    settings_file.create_dataset('X_1', data=X_1)
    settings_file.create_dataset('X_2', data=X_2)
    settings_file.create_dataset('Y_1', data=Y_1)
    settings_file.create_dataset('Y_2', data=Y_2)
    settings_file.create_dataset('Z_1', data=Z_1)
    settings_file.create_dataset('Z_2', data=Z_2)
    settings_file.create_dataset('x_mon_rat', data=x_mon_rat)
    settings_file.create_dataset('y_mon_rat', data=y_mon_rat)
    settings_file.create_dataset('z_mon_rat', data=z_mon_rat)
    settings_file.close()

    #Convert theta to radians
    theta = theta_deg * np.pi / 180

    eps_tip = calc_eps_r(n_tip, k_tip)
    sig_d_tip = calc_sig_d(n_tip, k_tip, fcen)

    #Create the cell size
    sX = 2 * dpml + sx
    sY = 2 * dpml + sy
    sZ = 2 * dpml + sz

    #Monitor sizes
    x_mon = sx * x_mon_rat
    y_mon = sx * y_mon_rat
    z_mon = sx * z_mon_rat

    #Calculate values in prime-space:
    sx_prime = sx * res_factor + (X_2 - X_1) * (1 - res_factor)
    sy_prime = sy * res_factor + (Y_2 - Y_1) * (1 - res_factor)
    sz_prime = sz * res_factor + (Z_2 - Z_1) * (1 - res_factor)
    dpml_prime = dpml * res_factor

    sX_prime = 2 * dpml_prime + sx_prime
    sY_prime = 2 * dpml_prime + sy_prime
    sZ_prime = 2 * dpml_prime + sz_prime

    x_mon_prime = (x_mon/2.0 > X_2)*((x_mon/2.0 - X_2)*res_factor + X_2) +\
                  (x_mon/2.0)*(x_mon/2.0 <= X_2) -\
                  (-1*x_mon/2.0 < X_1)*((-1*x_mon/2.0 - X_1)*res_factor + X_1) -\
                  (-1*x_mon/2.0)*(-1*x_mon/2.0 >= X_1)

    y_mon_prime = (y_mon/2.0 > Y_2)*((y_mon/2.0 - Y_2)*res_factor + Y_2) +\
                  (y_mon/2.0)*(y_mon/2.0 <= Y_2) -\
                  (-1*y_mon/2.0 < Y_1)*((-1*y_mon/2.0 - Y_1)*res_factor + Y_1) -\
                  (-1*y_mon/2.0)*(-1*y_mon/2.0 >= Y_1)

    z_mon_prime = (z_mon/2.0 > Z_2)*((z_mon/2.0 - Z_2)*res_factor + Z_2) +\
                  (z_mon/2.0)*(z_mon/2.0 <= Z_2) -\
                  (-1*z_mon/2.0 < Z_1)*((-1*z_mon/2.0 - Z_1)*res_factor + Z_1) -\
                  (-1*z_mon/2.0)*(-1*z_mon/2.0 >= Z_1)

    cell = mp.Vector3(sX_prime, sY_prime, sZ_prime)

    tip = [
        mp.Cylinder(radius=trunk_radius,
                    center=mp.Vector3(
                        0.0, -1 * sY / 4.0 - cone_height / 2.0 - tip_radius,
                        0.0),
                    height=(sY / 2.0 - cone_height),
                    axis=mp.Vector3(0.0, 1.0, 0.0)),
        mp.Cone(center=mp.Vector3(0, -1 * cone_height / 2 - tip_radius, 0),
                height=cone_height,
                radius=trunk_radius,
                radius2=tip_radius,
                axis=mp.Vector3(0, 1, 0)),
        mp.Sphere(center=mp.Vector3(0, -1 * tip_radius, 0), radius=tip_radius)
    ]

    def mat_func(r_prime):

        r_x = r_prime.x
        r_y = r_prime.y
        r_z = r_prime.z

        x_fac = 1
        y_fac = 1
        z_fac = 1

        if (r_prime.x < X_1):
            x_fac = res_factor
            r_x = X_1 + (r_prime.x - X_1) / res_factor
        elif (r_prime.x > X_2):
            x_fac = res_factor
            r_x = X_2 + (r_prime.x - X_2) / res_factor

        if (r_prime.y < Y_1):
            y_fac = res_factor
            r_y = Y_1 + (r_prime.y - Y_1) / res_factor
        elif (r_prime.y > Y_2):
            y_fac = res_factor
            r_y = Y_2 + (r_prime.y - Y_2) / res_factor

        if (r_prime.z < Z_1):
            z_fac = res_factor
            r_z = Z_1 + (r_prime.z - Z_1) / res_factor
        elif (r_prime.z > Z_2):
            z_fac = res_factor
            r_z = Z_2 + (r_prime.z - Z_2) / res_factor

        r = mp.Vector3(r_x, r_y, r_z)

        J = np.matrix([[x_fac, 0, 0], [0, y_fac, 0], [0, 0, z_fac]])

        #Loop through all objects inside of tip and see if point is inside.
        #  if yes -- then set eps_point to tip eps
        #  if no -- then leave it as air
        eps_point = 1.0
        for kk in range(len(tip)):
            if (mp.is_point_in_object(r, tip[kk])):
                eps_point = eps_tip

        eps_transform = eps_point * J * J.transpose() / np.linalg.det(J)
        mu_transform = J * J.transpose() / np.linalg.det(J)

        eps_diag = eps_transform.diagonal()
        mu_diag = mu_transform.diagonal()

        mat = mp.Medium(epsilon_diag=mp.Vector3(eps_diag[0, 0], eps_diag[0, 1],
                                                eps_diag[0, 2]),
                        mu_diag=mp.Vector3(mu_diag[0, 0], mu_diag[0, 1],
                                           mu_diag[0, 2]),
                        D_conductivity=sig_d_tip)

        return mat

    #Create source amplitude function:
    ky = fcen * np.sin(theta)
    ky_prime = ky * sY / sY_prime

    def my_amp_func_y(r_prime):

        r_y = r_prime.y
        y_fac = 1 / res_factor

        if ((r_prime.x >= X_1) and (r_prime.x <= X_2)):
            x_fac = 1.0 / res_factor
        else:
            x_fac = 1.0

        if (r_prime.y < Y_1):
            y_fac = 1.0
            r_y = Y_1 + (r_prime.y - Y_1) / res_factor
        elif (r_prime.y > Y_2):
            y_fac = 1.0
            r_y = Y_2 + (r_prime.y - Y_2) / res_factor

        if ((r_prime.z >= Z_1) and (r_prime.z <= Z_2)):
            z_fac = 1.0 / res_factor
        else:
            z_fac = 1.0

        J = np.matrix([[x_fac, 0, 0], [0, y_fac, 0], [0, 0, z_fac]])

        transform = J / np.linalg.det(J)

        phase_factor = np.exp(-1 * 2 * 1j * np.pi * ky * r_y)
        amp_factor = transform.diagonal()[0, 1]

        return amp_factor * phase_factor

    def my_amp_func_z(r_prime):

        r_y = r_prime.y
        y_fac = 1.0 / res_factor

        if ((r_prime.x >= X_1) and (r_prime.x <= X_2)):
            x_fac = 1.0 / res_factor
        else:
            x_fac = 1.0

        if (r_prime.y < Y_1):
            y_fac = 1.0
            r_y = Y_1 + (r_prime.y - Y_1) / res_factor
        elif (r_prime.y > Y_2):
            y_fac = 1.0
            r_y = Y_2 + (r_prime.y - Y_2) / res_factor

        if ((r_prime.z >= Z_1) and (r_prime.z <= Z_2)):
            z_fac = 1.0 / res_factor
        else:
            z_fac = 1.0

        J = np.matrix([[x_fac, 0, 0], [0, y_fac, 0], [0, 0, z_fac]])

        transform = J / np.linalg.det(J)

        phase_factor = np.exp(-1 * 2 * 1j * np.pi * ky * r_y)
        amp_factor = transform.diagonal()[0, 2]

        return amp_factor * phase_factor

    #Create PMLs
    pml_layers = [
        mp.PML(thickness=dpml_prime, direction=mp.X),
        mp.PML(thickness=dpml_prime, direction=mp.Y),
        mp.PML(thickness=dpml_prime, direction=mp.Z)
    ]

    symmetry = [mp.Mirror(direction=mp.X)]

    #Sources
    Ey_source = mp.Source(mp.ContinuousSource(frequency=fcen),
                          component=mp.Ey,
                          center=mp.Vector3(0, 0, -1 * sz_prime * 0.5),
                          size=mp.Vector3(sX_prime, sY_prime, 0),
                          amp_func=my_amp_func_y,
                          amplitude=np.cos(theta))

    Ez_source = mp.Source(mp.ContinuousSource(frequency=fcen),
                          component=mp.Ez,
                          center=mp.Vector3(0, 0, -1 * sz_prime * 0.5),
                          size=mp.Vector3(sX_prime, sY_prime, 0),
                          amp_func=my_amp_func_z,
                          amplitude=np.sin(theta))

    sources = [Ey_source, Ez_source]

    monitor_xy = mp.Volume(center=mp.Vector3(0, 0, 0),
                           size=mp.Vector3(x_mon_prime, y_mon_prime, 0))
    monitor_yz = mp.Volume(center=mp.Vector3(0, 0, 0),
                           size=mp.Vector3(0, y_mon_prime, z_mon_prime))

    #Now make the simulation
    sim = mp.Simulation(
        cell_size=cell,
        boundary_layers=pml_layers,
        geometry=[],
        sources=sources,
        resolution=res,
        symmetries=symmetry,
        dimensions=3,
        k_point=mp.Vector3(0, -1 * ky_prime, 0),
        material_function=mat_func,
        extra_materials=[mp.Medium(epsilon=eps_tip, mu=4, D_conductivity=1)],
        verbose=True)

    sim.run(mp.in_volume(
        monitor_xy,
        mp.to_appended(save_prefix + "E_xy",
                       mp.at_every(1 / fcen / sample, mp.output_efield))),
            mp.in_volume(
                monitor_yz,
                mp.to_appended(
                    save_prefix + "E_yz",
                    mp.at_every(1 / fcen / sample, mp.output_efield))),
            until=waves / fcen)
Exemple #13
0
dpml = 2
pml_layers = [mp.PML(thickness=dpml,direction=mp.X)]

sx = 40
sy = 6
cell_size = mp.Vector3(sx+2*dpml,sy)

v0 = 1.0  # pulse center frequency
a = 0.2   # Gaussian envelope half-width
b = -0.5  # linear chirp rate (positive: up-chirp, negative: down-chirp)
t0 = 15   # peak time

chirp = lambda t: np.exp(1j*2*np.pi*v0*(t-t0)) * np.exp(-a*(t-t0)**2+1j*b*(t-t0)**2)

sources = [mp.Source(src=mp.CustomSource(src_func=chirp),
                     center=mp.Vector3(-0.5*sx),
                     size=mp.Vector3(y=sy),
                     component=mp.Ez)]

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

sim.run(mp.in_volume(mp.Volume(center=mp.Vector3(), size=mp.Vector3(sx,sy)),
                     mp.at_every(2.7, mp.output_efield_z)),
        until=t0+50)
    mp.Source(mp.GaussianSource(fcen, fwidth=df),
              size=mp.Vector3(0, 0, 0.8),
              component=mp.Ez,
              center=mp.Vector3(-14, 5.))
]  #-14,5.,0.8
#sources = [mp.Source(mp.ContinuousSource(frequency=fcen, width=20), component=mp.Ez, center=mp.Vector3(-14,5.))]
sim = mp.Simulation(
    cell_size=cell,
    boundary_layers=pml_layers,
    geometry=geometry,
    sources=sources,
    resolution=res)  #geometry=geometry, boundary_layers=pml_layers

sim.run(mp.at_beginning(mp.output_epsilon),
        mp.in_volume(
            mp.Volume(center=mp.Vector3(0, 0, 0), size=mp.Vector3(sx, sy, 0)),
            mp.to_appended("ez", mp.at_every(0.6, mp.output_efield_z))),
        mp.in_volume(
            mp.Volume(center=mp.Vector3(-14, 5., 0), size=mp.Vector3(0, 0, 0)),
            mp.to_appended("EzTr", mp.at_every(0.6, mp.output_efield_z))),
        mp.in_volume(
            mp.Volume(center=mp.Vector3(14., -5., 0), size=mp.Vector3(0, 0,
                                                                      0)),
            mp.to_appended("EzR2", mp.at_every(0.6, mp.output_efield_z))),
        mp.in_volume(
            mp.Volume(center=mp.Vector3(10., 5., 0), size=mp.Vector3(0, 0, 0)),
            mp.to_appended("EzR3", mp.at_every(0.6, mp.output_efield_z))),
        mp.in_volume(
            mp.Volume(center=mp.Vector3(10., -5., 0), size=mp.Vector3(0, 0,
                                                                      0)),
            mp.to_appended("EzR4", mp.at_every(0.6, mp.output_efield_z))),
Exemple #15
0
 def test_in_volume(self):
     sim = self.init_simple_simulation()
     sim.filename_prefix = 'test_in_volume'
     vol = mp.Volume(mp.Vector3(), size=mp.Vector3(x=2))
     sim.run(mp.at_end(mp.in_volume(vol, mp.output_efield_z)), until=200)
Exemple #16
0
def main(args):

    resolution = 20  # pixels/um

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

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

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

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

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

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

    pml_layers = [mp.PML(1.0)]

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

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

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

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

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

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

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

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

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

    sim.display_fluxes(trans)  # print out the flux spectrum
Exemple #17
0
def main(args):
    resolution = 20 # pixels/um
    
    eps = 13      # dielectric constant of waveguide
    w = 1.2       # width of waveguide
    r = 0.36      # radius of holes
    d = 1.4       # defect spacing (ordinary spacing = 1)
    N = args.N    # number of holes on either side of defect

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

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

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

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

    geometry = [blk]

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

    fcen = args.fcen  # pulse center frequency
    df = args.df      # pulse frequency width
    nfreq = 500       # number of frequencies at which to compute flux

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

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

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

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

        sim.run(mp.at_every(1/fcen/20, mp.output_hfield_z), until=1/fcen)
    else:
        sim.sources.append(mp.Source(mp.GaussianSource(fcen, fwidth=df),
                                     component=mp.Ey,
                                     center=mp.Vector3(-0.5*sx+dpml),
                                     size=mp.Vector3(0,w)))

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

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

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

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

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

        sim.display_fluxes(trans)  # print out the flux spectrum
        sim.symmetries.append(mp.Mirror(mp.Y, phase=-1))
        sim.symmetries.append(mp.Mirror(mp.X, phase=-1))

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

        sim.run(mp.at_every(1 / fcen / 20, mp.output_hfield_z), until=1 / fcen)
    else:
        sim.sources.append(mp.Source(mp.GaussianSource(fcen, fwidth=df),
                                     component=mp.Ey,
                                     center=mp.Vector3(-0.5 * sx + dpml),
                                     size=mp.Vector3(0, w)))

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

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

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

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

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

        sim.display_fluxes(trans)  # print out the flux spectrum
def generateData(i,
                 resolution=5,
                 total_time=10000,
                 dT=10,
                 length=500.,
                 pml_thickness=10.,
                 outer_radius=10.,
                 chi3=0.0,
                 half=False,
                 shift=200):
    ### Generate data using MEEP

    print('Run ' + str(i + 1) + ' of ' + str(data_size))

    while True:
        dr1 = np.random.normal(scale=0.05)
        dr2 = np.random.normal(scale=0.02)
        de1 = np.random.normal(scale=1)
        de2 = np.random.normal(scale=2)

        inner_core_radius = 0.5 + dr2
        core_radius = 1.0 + dr1

        if core_radius > inner_core_radius:
            break

    output_dir = f"out-{i:05d}"

    cell_size = mp.Vector3(outer_radius + pml_thickness, 0,
                           length + 2 * pml_thickness)
    pml_layers = [mp.PML(thickness=pml_thickness)]
    default_material = mp.Medium(index=1, chi3=chi3)
    geometry = [
        mp.Block(center=mp.Vector3(),
                 size=mp.Vector3(2 * core_radius, mp.inf, mp.inf),
                 material=mp.Medium(epsilon=8 + de1, chi3=chi3)),
        mp.Block(center=mp.Vector3(),
                 size=mp.Vector3(2 * inner_core_radius, mp.inf, mp.inf),
                 material=mp.Medium(epsilon=30 + de2, chi3=chi3))
    ]

    fsrc = 0.1
    if not half:
        u0, f = get_f(total_time, dT, fsrc=fsrc, batch_size=1)
    else:
        u0, f = get_f_half(total_time, dT, fsrc=fsrc, batch_size=1)
    sources = [
        mp.Source(src=mp.CustomSource(src_func=lambda t: f(t)[0]),
                  center=mp.Vector3(0, 0, -length / 2.),
                  size=mp.Vector3(2 * (3)),
                  component=mp.Er)
    ]

    sim = mp.Simulation(cell_size=cell_size,
                        resolution=resolution,
                        boundary_layers=pml_layers,
                        sources=sources,
                        geometry=geometry,
                        dimensions=mp.CYLINDRICAL,
                        m=1)
    flux_total = sim.add_flux(
        fsrc, 1. * fsrc,
        int(fsrc * total_time) + 1,
        mp.FluxRegion(center=mp.Vector3(0, 0, -length / 2. + pml_thickness),
                      size=mp.Vector3(2 * outer_radius)))

    sim.use_output_directory(output_dir)
    sim.run(mp.at_every(
        dT,
        mp.in_volume(
            mp.Volume(center=mp.Vector3(), size=mp.Vector3(0, 0, length)),
            mp.output_efield_r)),
            until=total_time)

    files = sorted(glob.glob(output_dir + "/*er-*.h5"))
    data = []
    for file in files:
        f = h5py.File(file, "r")
        data.append(np.array(f['er.r']) + 1j * np.array(f['er.i']))

    data = np.stack(data)

    # Normalize by flux
    freqs = np.array(mp.get_flux_freqs(flux_total))
    flux = np.array(mp.get_fluxes(flux_total))
    integrated_flux = np.sum(flux) * (freqs[1] - freqs[0])
    integrated_efield = np.sum(
        np.abs(data[:, int(resolution * pml_thickness) + 1])**2) * dT
    norm_factor = np.sqrt(integrated_flux / integrated_efield)
    data *= norm_factor

    mean_norm2 = np.mean(
        np.abs(data[:, int(resolution * pml_thickness) + 1])**2)

    # Remove carrier frequency/wavelength
    k = np.fft.fftfreq(data.shape[-1], d=1. / resolution)
    k0 = k[np.argmax(np.abs(np.mean(np.fft.fft(data), 0)))]
    psi = data * np.exp(
        1j * 2 * np.pi *
        (fsrc * dT * np.expand_dims(np.arange(data.shape[0]), 1) -
         k0 * np.arange(data.shape[1]) / resolution))

    psi = psi[shift:,
              int(resolution * pml_thickness) + 1:-1:int(
                  resolution)]  # drop region near PML and initial time 200*dT
    psi = psi.transpose()  # swap t and z axis

    shutil.rmtree(output_dir)

    return np.expand_dims(np.stack([np.real(psi), np.imag(psi)], axis=-3),
                          0).astype(np.float32), np.array(
                              [[dr1, dr2, de1, de2, k0,
                                mean_norm2]]).astype(np.float32)
Exemple #20
0
def main(args):
    """
    Args:
       * **fields** (boolean): If true, outputs the fields at the relevant waveguide cross-sections (top-down and side-view)
       * **output_directory** (string): Name of the output directory (for storing the fields)
       * **eps_input_file** (string): Name of the hdf5 file that defines the geometry through prisms
       * **input_pol** (string): Either "TE", or "TM", corresponding to the desired input mode.  Defaults to "TE"
       * **res** (int): Resolution of the MEEP simulation
       * **nfreq** (int): The number of wavelength points to record in the transmission/reflection spectra
       * **input_direction** (1 or -1): Direction of propagation for the input eigenmode.  If +1, goes in +x, else if -1, goes in -x.  Defaults to +1.
       * **dpml** (float): Length (in microns) of the perfectly-matched layer (PML) at simulation boundaries.  Defaults to 0.5 um.
       * **wl_center** (float): Center wavelength (in microns)
       * **wl_span** (float): Wavelength span (determines the pulse width)
       * **port_vcenter** (float): Vertical center of the waveguide
       * **port_height** (float): Height of the port cross-section (flux plane)
       * **port_width** (float): Width of the port cross-section (flux plane)
       * **source_offset** (float): Offset (in x-direction) between reflection monitor and source.  Defaults to 0.1 um.
       * **center_x** (float): x-coordinate of the center of the simulation region
       * **center_y** (float): y-coordinate of the center of the simulation region
       * **center_z** (float): z-coordinate of the center of the simulation region
       * **sx** (float): Size of the simulation region in x-direction
       * **sx** (float): Size of the simulation region in y-direction
       * **sz** (float): Size of the simulation region in z-direction
       * **port_coords** (list): List of the port coordinates (variable length), in the format [x1, y1, x2, y2, x3, y3, ...] (*must* be even)
    """
    #Boolean inputs
    fields = args.fields

    #String inputs
    output_directory = args.output_directory
    eps_input_file = args.eps_input_file
    input_pol = args.input_pol

    #Int inputs
    res = args.res
    nfreq = args.nfreq
    input_direction = args.input_direction

    #Float inputs
    dpml = args.dpml
    wl_center = args.wl_center
    wl_span = args.wl_span
    port_vcenter = args.port_vcenter
    port_height = args.port_height
    port_width = args.port_width
    source_offset = args.source_offset
    center_x, center_y, center_z = args.center_x, args.center_y, args.center_z
    sx, sy, sz = args.sx, args.sy, args.sz

    #List of floats
    port_coords = [float(x) for x in args.port_coords[0].split(" ")]
    ports = [(port_coords[2 * i], port_coords[2 * i + 1])
             for i in range(int(len(port_coords) / 2))]

    if input_pol == "TE":
        parity = mp.ODD_Z
    elif input_pol == "TM":
        parity = mp.EVEN_Z
    else:
        raise ValueError(
            "Warning! Improper value of 'input_pol' was passed to mcts.py (input_pol given ="
            + str(input_pol) + ")")

    if len(port_coords) % 2 != 0:
        raise ValueError(
            "Warning! Improper port_coords was passed to `meep_compute_transmission_spectra`.  Must be even number of port_coords in [x1, y1, x2, y2, ..] format."
        )

    # Setup the simulation geometries

    prism_objects = get_prism_objects(eps_input_file)
    geometry = []
    for p in prism_objects:
        #        print('vertices='+str(p['vlist']))
        #        print('axis = '+str(mp.Vector3(0,1,0)))
        #        print('height = '+str(p['height']))
        print('material = ' + str(p['eps']))
        #        print('\n')
        geometry.append(
            mp.Prism(p['vlist'],
                     axis=mp.Vector3(0, 1, 0),
                     height=p['height'],
                     material=mp.Medium(epsilon=p['eps'])))

    # Setup the simulation sources
    fmax = 1.0 / (wl_center - 0.5 * wl_span)
    fmin = 1.0 / (wl_center + 0.5 * wl_span)
    fcen = (fmax + fmin) / 2.0
    df = fmax - fmin
    if abs(abs(input_direction) - 1) > 1E-6:
        print(input_direction)
        raise ValueError("Warning! input_direction is not +1 or -1.")

    # Use first port in 'ports' as the location of the eigenmode source
    sources = [
        mp.EigenModeSource(
            src=mp.GaussianSource(fcen, fwidth=df, cutoff=30),
            component=mp.ALL_COMPONENTS,
            size=mp.Vector3(0, 3 * float(port_height), 3 * float(port_width)),
            center=mp.Vector3(ports[0][0] + source_offset - center_x,
                              float(port_vcenter) - center_y,
                              ports[0][1] - center_z),
            eig_match_freq=True,
            eig_parity=parity,
            eig_kpoint=mp.Vector3(float(input_direction) * wl_center, 0, 0),
            eig_resolution=2 * res if res > 16 else 32,
        )
    ]

    # Setup the simulation
    sim = mp.Simulation(cell_size=mp.Vector3(sx, sy, sz),
                        boundary_layers=[mp.PML(dpml)],
                        geometry=geometry,
                        sources=sources,
                        dimensions=3,
                        resolution=res,
                        filename_prefix=False)
    """ Add power flux monitors """
    print("ADDING FLUX MONITORS")
    flux_plane_objects = []

    for port in ports:
        flux_region = mp.FluxRegion(size=mp.Vector3(0, float(port_height),
                                                    float(port_width)),
                                    center=mp.Vector3(
                                        float(port[0]) - center_x,
                                        float(port_vcenter) - center_y,
                                        float(port[1]) - center_z))
        fpo = sim.add_flux(fcen, df, nfreq, flux_region)
        flux_plane_objects.append(fpo)

    sim.use_output_directory(str(output_directory))
    """ Run the simulation """
    """ Monitor the amplitude in the center of the structure """
    decay_pt = mp.Vector3(0, port_vcenter, 0)

    sv = mp.Volume(size=mp.Vector3(sx, sy, 0), center=mp.Vector3(0, 0, 0))
    tv = mp.Volume(size=mp.Vector3(sx, 0, sz),
                   center=mp.Vector3(0, port_vcenter, 0))

    print("RUNNING SIMULATION")

    if fields:
        sim.run(mp.at_beginning(mp.output_epsilon),
                mp.at_beginning(
                    mp.with_prefix(str("sideview-"),
                                   mp.in_volume(sv, mp.output_epsilon))),
                mp.at_beginning(
                    mp.with_prefix(str("topview-"),
                                   mp.in_volume(tv, mp.output_epsilon))),
                mp.at_every(
                    1.0,
                    mp.to_appended(str("ez-sideview"),
                                   mp.in_volume(sv, mp.output_efield_z))),
                mp.at_every(
                    1.0,
                    mp.to_appended(str("ez-topview"),
                                   mp.in_volume(tv, mp.output_efield_z))),
                until_after_sources=mp.stop_when_fields_decayed(
                    20, mp.Ez, decay_pt, 1e-4))
    else:
        sim.run(until_after_sources=mp.stop_when_fields_decayed(
            20, mp.Ez, decay_pt, 1e-4))

    sim.display_fluxes(*flux_plane_objects)

    print("FINISHED SIMULATION")
Exemple #21
0
def main(args):

    resolution = 30  # pixels/um

    a_start = args.a_start  # starting periodicity
    a_end = args.a_end  # ending periodicity
    s_cav = args.s_cav  # cavity length
    r = args.r  # hole radius  (units of a)
    h = args.hh  # waveguide height
    w = args.w  # waveguide width

    dair = 1.00  # air padding
    dpml = 1.00  # PML thickness

    Ndef = args.Ndef  # number of defect periods
    a_taper = mp.interpolate(Ndef, [a_start, a_end])
    dgap = a_end - 2 * r * a_end

    Nwvg = args.Nwvg  # number of waveguide periods
    sx = 2 * (Nwvg * a_start + sum(a_taper)) - dgap + s_cav
    sy = dpml + dair + w + dair + dpml
    sz = dpml + dair + h + dair + dpml

    cell_size = mp.Vector3(sx, sy, sz)
    boundary_layers = [mp.PML(dpml)]

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

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

    for mm in range(Nwvg):
        geometry.append(
            mp.Cylinder(material=mp.air,
                        radius=r * a_start,
                        height=mp.inf,
                        center=mp.Vector3(
                            -0.5 * sx + 0.5 * a_start + mm * a_start, 0, 0)))
        geometry.append(
            mp.Cylinder(material=mp.air,
                        radius=r * a_start,
                        height=mp.inf,
                        center=mp.Vector3(
                            +0.5 * sx - 0.5 * a_start - mm * a_start, 0, 0)))

    for mm in range(Ndef + 2):
        geometry.append(
            mp.Cylinder(material=mp.air,
                        radius=r * a_taper[mm],
                        height=mp.inf,
                        center=mp.Vector3(
                            -0.5 * sx + Nwvg * a_start +
                            (sum(a_taper[:mm]) if mm > 0 else 0) +
                            0.5 * a_taper[mm], 0, 0)))
        geometry.append(
            mp.Cylinder(material=mp.air,
                        radius=r * a_taper[mm],
                        height=mp.inf,
                        center=mp.Vector3(
                            +0.5 * sx - Nwvg * a_start -
                            (sum(a_taper[:mm]) if mm > 0 else 0) -
                            0.5 * a_taper[mm], 0, 0)))

    lambda_min = 1.46  # minimum source wavelength
    lambda_max = 1.66  # maximum source wavelength
    fmin = 1 / lambda_max
    fmax = 1 / lambda_min
    fcen = 0.5 * (fmin + fmax)
    df = fmax - fmin

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

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

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

    sim.run(mp.in_volume(
        mp.Volume(center=mp.Vector3(), size=mp.Vector3(sx, sy, 0)),
        mp.at_end(mp.output_epsilon, mp.output_efield_y)),
            mp.after_sources(mp.Harminv(mp.Ey, mp.Vector3(), fcen, df)),
            until_after_sources=500)
Exemple #22
0
#
dft_objx = []
for i in range(len(flux_freqsX)):
    dft_objx = np.append(
        dft_objx,
        sim.add_dft_fields([polarisation],
                           flux_freqsX[i],
                           flux_freqsX[i],
                           1,
                           where=monitor))

dft_obj = sim.add_dft_fields([polarisation], fcen, fcen, 1, where=monitor)

sim.use_output_directory('flux-out_1')
sim.run(mp.in_volume(monitor, mp.at_beginning(mp.output_epsilon)),
        mp.in_volume(
            monitor,
            mp.to_appended("ez", mp.at_every(time_step, mp.output_efield_x))),
        until_after_sources=mp.stop_when_fields_decayed(
            add_time, polarisation, pt, decay))
'''
sim.run(until_after_sources=mp.stop_when_fields_decayed(add_time,polarisation,pt,decay))
'''

#save scattered reflected flux from the surfaces
scat_refl_data_t = mp.get_fluxes(refl_t)
scat_refl_data_b = mp.get_fluxes(refl_b)
scat_refl_data_l = mp.get_fluxes(refl_l)
scat_refl_data_r = mp.get_fluxes(refl_r)
Exemple #23
0
def generate_model(params, args):

    
    cell = mp.Vector3(params.cell_width, params.cell_height, 0)

    spheres = mplib.geo2D_spherical_pc(params.ps_n, params.si_n,
                                       params.ps_thickness, params.si_thickness, params.cell_height, params.num_layers,
                                       params.cell_width/2-200, params.sph_radius,
                                       params.sph_spacing, params.offset, params.xoffset)

    thin_film = mplib.geo2D_thin_film(params.ps_n, params.ps_thickness, params.cell_height,
                                      params.cell_width/2-100)

    pc_ideal = mplib.geo2D_photonic_crystal(params.ps_n, params.other_n,
                                            params.ps_thickness, params.cell_height,
                                            params.si_thickness, params.si_n,
                                            5, params.cell_width/2-200, 50)

    


    geometry = pc_ideal
    
    if args.background:
        geometry = []


    ## Gaussian source
    source_pos = -1*params.cell_width/2 + params.dpml+5
    sources = [mp.Source(mp.GaussianSource(frequency=params.freq, fwidth=params.df),
                         mp.Ez, center=mp.Vector3(source_pos,0,0),
                         size=mp.Vector3(0,params.cell_height,0))]
    
    
    pml_layers = [mp.PML(params.dpml, direction=mp.X)]


    sim = mp.Simulation(cell_size = cell,
                        boundary_layers = pml_layers,
                        geometry = geometry,
                        filename_prefix=args.filename,
                        sources = sources,
                        k_point = mp.Vector3(0,0,0),
                        resolution = params.resolution)

    freg_trans = mp.FluxRegion(center = mp.Vector3(0.5*params.cell_width - params.dpml - 1,0,0),
                         size = mp.Vector3(0, params.cell_height, 0))

    freg_ref    = mp.FluxRegion(center = mp.Vector3(source_pos + 10, 0, 0),
                                size = mp.Vector3(0, params.cell_height), weight=1.0)


    trans_flux = sim.add_flux(params.freq, params.df , 500, freg_trans)
    ref_flux    = sim.add_flux(params.freq, params.df, 500, freg_ref)
    vol = mp.Volume(mp.Vector3(0), size = mp.Vector3(params.cell_width,0,0))

    if not args.reflectflux:
        sim.load_minus_flux("pulse_bg_flux_{:d}".format(params.wavelength),ref_flux)

    if args.outdir:
        print("Output directory: {:s}".format(args.outdir))
        sim.use_output_directory(args.outdir)

    if args.geometry:
        sim.run(mp.at_beginning(mp.output_epsilon),
                until=1)
    else:   
        sim.run(mp.at_beginning(mp.output_epsilon),
                mp.to_appended("ez", mp.at_every(params.dt, mp.output_efield_z)),
                #mp.to_appended("ep", mp.at_every(params.dt, mp.output_dpwr)),
                mp.in_volume(vol, mp.to_appended("ez_slice", mp.at_every(params.dt, mp.output_efield_z))),
                until=params.time)

    if args.reflectflux:
        sim.save_flux("pulse_bg_flux_{:d}".format(params.wavelength),ref_flux)
    
    #sim.save_flux("bg_flux_other", trans_flux)
    sim.display_fluxes(trans_flux, ref_flux)
Exemple #24
0
 def test_in_volume(self):
     sim = self.init_simple_simulation()
     sim.filename_prefix = 'test_in_volume'
     vol = mp.Volume(mp.Vector3(), size=mp.Vector3(x=2))
     sim.run(mp.at_end(mp.in_volume(vol, mp.output_efield_z)), until=200)
Exemple #25
0
def main(args):
    resolution = 20  # pixels/um
    eps = 13  # epsilon of waveguide
    cols = 3  # metade da quantidade de colunas no cristal
    lines = 1  #7 é valor anterior            # metade da quantidade de linhas no cristal
    w = 1.2  # width of the  waveguide
    r = 0.2  # radius of holes
    N = args.N  # number of holes on either side of defect
    #pad = 1              # padding between last hole and PML
    dpml = 1  # PML thickness

    sy = 2 * (dpml + lines)  # tamanho da celula em Y (perpend ao guia)
    #sy = args.sy        # size of cell in Y (perpend to wvg)
    fcen = args.fcen  # pulse centger frequency
    df = args.df  # pulse frequency width

    #sx = 2*(pad + dpml ) + lines      #  size of cell in X
    sx = 2 * (dpml + cols)

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

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

    for i in range(lines):
        geometry.append(mp.Cylinder(r, center=mp.Vector3(0, i)))
        for j in range(cols):
            geometry.append(mp.Cylinder(r,
                                        center=mp.Vector3(i,
                                                          j)))  #      j,i)))
            geometry.append(mp.Cylinder(r,
                                        center=mp.Vector3(-i,
                                                          j)))  #      j,-i)))
            geometry.append(mp.Cylinder(r,
                                        center=mp.Vector3(i,
                                                          -j)))  #      -j,i)))
            geometry.append(mp.Cylinder(r, center=mp.Vector3(
                -i, -j)))  #      -j,-i)))

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

    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)

    freg = mp.FluxRegion(
        center=mp.Vector3(
            0.5 * sx - dpml - 0.5
        ),  # fluxo na direita; para colocar na esquerda usar -0.5*sx+dpml+0.5
        size=mp.Vector3(0, 2 * w))
    nfreq = 500  # number of frequencies computed fluxes

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

    vol = mp.Volume(mp.Vector3(0), size=mp.Vector3(sx))
    volTime = mp.Volume(mp.Vector3(((sx) / 2 - dpml), 0),
                        size=mp.Vector3(
                            0, 1,
                            0))  # dados para pulso no tempo no final do guia

    hvals = []

    def gethvals(sim):
        hvals.append(
            sim.get_array(center=mp.Vector3(), size=cell, component=mp.Hz))

    sim.run(mp.at_beginning(mp.output_epsilon),
            mp.in_volume(
                volTime,
                mp.to_appended("TimeVsE2", mp.at_every(0.4, mp.output_dpwr))),
            mp.in_volume(
                vol,
                mp.to_appended("hz-slice",
                               mp.at_every(0.4, gethvals,
                                           mp.output_hfield_z))),
            until=300)

    sim.display_fluxes(
        trans)  # print flux spectrum  - linha realocada, ver abaixo

    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()