示例#1
0
    def initialise_engine(self, landscape):
        '''Initializes the Meep simulation engine. Parameter is a reference to the simulation landscape (object of type runtime.basic.SimulationLandscape) .'''
        self.node_nr = int(Meep.my_rank())
        LOG.debug("Meep node %i -Defining the landscape in Meep..." %
                  (self.node_nr))
        if not isinstance(landscape, SimulationLandscape):
            raise InvalidArgumentException(
                "Invalid argument for function setLandscape:: not of type runtime.basic.SimulationLandscape."
            )
        self.landscape = landscape
        Meep.use_averaging(self.use_averaging)
        Meep.quiet(False)

        LOG.debug("Meep node %i -Defining material..." % (self.node_nr))
        [self.meepVol, self.dim
         ] = self.__createMeepComputationalVolume(landscape.simulation_volume)
        if self.dim == 2:
            try:
                self.material = MeepMaterial2DPolygons(
                    landscape.simulation_volume, self.meepVol)
            except Exception, err:
                LOG.error(
                    "MeepMaterial2DPolygons gives errors -> using MeepMaterial2DMatrix instead..."
                )
                self.material = MeepMaterial2DMatrix(
                    landscape.simulation_volume, self.meepVol)
示例#2
0
def get_flux_on_metalens(metalens):
    # Setup the MEEP objects
    cell = mp.Vector3(metalens['sim_cell_width'], metalens['sim_cell_height'])
    # All around the simulation cell
    pml_layers = [mp.PML(metalens['pml_width'])]
    # Set up the sources
    #    sources = [mp.Source(src=mp.ContinuousSource(
    #                         wavelength=metalens['wavelength'],
    #                         width=metalens['source_width']
    #                        ),
    #              component=mp.Ez,
    #              center=mp.Vector3(0, metalens['source_coord']),
    #              size=mp.Vector3(2 * metalens['ws'], 0),
    #              amp_func=far_ez_source_amp_func(metalens))]
    sources = [
        mp.Source(src=mp.ContinuousSource(wavelength=metalens['wavelength'],
                                          width=metalens['source_width']),
                  component=mp.Ex,
                  amp_func=in_plane_dip_amp_func_Ex(metalens),
                  center=mp.Vector3(0, metalens['source_coord']),
                  size=mp.Vector3(metalens['sim_cell_width'], 0)),
        mp.Source(src=mp.ContinuousSource(wavelength=metalens['wavelength'],
                                          width=metalens['source_width']),
                  component=mp.Hz,
                  amp_func=in_plane_dip_amp_func_Hz(metalens),
                  center=mp.Vector3(0, metalens['source_coord']),
                  size=mp.Vector3(metalens['sim_cell_width'], 0))
    ]
    # Set up the symmetries
    syms = []
    if metalens['x_mirror_symmetry']:
        syms.append(mp.Mirror(mp.X))
    sim = mp.Simulation(cell_size=cell,
                        boundary_layers=pml_layers,
                        geometry=metalens['flux_geometry'],
                        force_complex_fields=metalens['complex_fields'],
                        symmetries=syms,
                        sources=sources,
                        resolution=metalens['resolution'])
    mp.quiet(metalens['quiet'])
    sim.init_sim()
    sim.run(until=metalens['simulation_time'])

    fields = {
        'Ex': sim.get_array(component=mp.Ex).transpose(),
        'Ey': sim.get_array(component=mp.Ey).transpose(),
        'Hz': sim.get_array(component=mp.Hz).transpose()
    }
    transverse_axis = (np.linspace(-metalens['sim_cell_width'] / 2,
                                   metalens['sim_cell_width'] / 2,
                                   fields['Hz'].shape[1]))
    optical_axis = np.linspace(-metalens['sim_cell_height'] / 2,
                               metalens['sim_cell_height'] / 2,
                               fields['Hz'].shape[0])
    interface_index = np.argmin(
        np.abs(optical_axis - metalens['interface_coord']))
    Sy = (np.real(-np.conjugate(fields['Ex']) * fields['Hz'])[interface_index]
          )[np.abs(transverse_axis) <= metalens['R']]
    return np.sum(Sy)
示例#3
0
import meep as mp
try:
    import meep.adjoint as mpa
except:
    import adjoint as mpa
import numpy as np
from autograd import numpy as npa
from autograd import tensor_jacobian_product
import unittest
from enum import Enum
mp.quiet(True)

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)
示例#4
0
'''
simple_broadband.py
'''
import meep as mp
import meep_adjoint as mpa
import numpy as np
import jax.numpy as npa
from matplotlib import pyplot as plt
from os import path

mp.quiet(quietval=True)
load_from_file = True

#----------------------------------------------------------------------
# Initial setup
#----------------------------------------------------------------------

seed = 24
np.random.seed(seed)
nf = 120
resolution = 10

Sx = 6
Sy = 5
cell_size = mp.Vector3(Sx,Sy)

pml_layers = [mp.PML(1.0)]

time = 500

#----------------------------------------------------------------------
示例#5
0
Run simulation:

    $ python wdm2.py run myrun

View results:

    $ python wdm2.py view myrun
"""
import os
import pickle

import matplotlib.pyplot as plt
import meep as mp
# Silence Meep logging output.
mp.quiet()
import numpy as np

from spins import goos
from spins.goos import compat
from spins.goos_sim import maxwell
from spins.goos_sim import meep
from spins.invdes.problem_graph import optplan


def main(save_folder: str,
         min_feature: float = 100,
         sim_3d: bool = False,
         visualize: bool = False) -> None:
    goos.util.setup_logging(save_folder)
def simulation(f_cen, df, fmin, fmax, sy, dpml, air, sx, resolution, nfreq,
               geometry, init_refl_data, init_tran_flux, n, THICKNESS):
    #----------------------Simulation------------------------------
    cell = mp.Vector3(sx, sy)
    thick = np.sum(THICKNESS)
    #define Gaussian plane wave
    sources = [
        mp.Source(mp.GaussianSource(f_cen, fwidth=df),
                  component=mp.Ez,
                  center=mp.Vector3(0, 0.5 * sy - dpml - 0.02 * air, 0),
                  size=mp.Vector3(x=sx))
    ]
    #define pml layers
    pml_layers = [
        mp.PML(thickness=dpml, direction=mp.Y, side=mp.High),
        mp.Absorber(thickness=dpml, direction=mp.Y, side=mp.Low)
    ]
    tran_fr = mp.FluxRegion(center=mp.Vector3(0, -0.5 * sy + dpml + 0.05),
                            size=mp.Vector3(x=sx))
    refl_fr = mp.FluxRegion(center=mp.Vector3(0, 0.5 * sy - dpml - 0.1 * air),
                            size=mp.Vector3(x=sx))
    mp.quiet(quietval=True)
    if n == 0:
        #if os.path.exists('dft_Z_empty.h5'):
        #os.remove('dft_Z_empty.h5')
        sim = mp.Simulation(cell_size=cell,
                            boundary_layers=pml_layers,
                            sources=sources,
                            symmetries=[mp.Mirror(mp.X)],
                            dimensions=2,
                            resolution=resolution,
                            k_point=mp.Vector3())

        #----------------------Monitors------------------------------
        refl = sim.add_flux(f_cen, df, nfreq, refl_fr)
        tran = sim.add_flux(f_cen, df, nfreq, tran_fr)
        dfts_Z = sim.add_dft_fields([mp.Ez],
                                    fmin,
                                    fmax,
                                    nfreq,
                                    where=mp.Volume(center=mp.Vector3(
                                        0, -sy * 0.5 + dpml + THICKNESS * 0.5,
                                        0),
                                                    size=mp.Vector3(
                                                        sx, THICKNESS)))
        #----------------------Run------------------------------
        sim.run(until_after_sources=mp.stop_when_fields_decayed(
            5, mp.Ez, mp.Vector3(), 1e-3))

        #----------------------Genetic------------------------------
        sim.output_dft(dfts_Z, "dft_Z_empty")
        init_refl_data = sim.get_flux_data(refl)
        init_tran_flux = mp.get_fluxes(tran)
        sim.reset_meep()
        get = init_refl_data, init_tran_flux

    elif n == 1:
        #if os.path.exists('dft_Z_fields.h5'):
        #os.remove('dft_Z_fields.h5')
        sim = mp.Simulation(cell_size=cell,
                            boundary_layers=pml_layers,
                            sources=sources,
                            geometry=geometry,
                            symmetries=[mp.Mirror(mp.X)],
                            dimensions=2,
                            resolution=resolution,
                            k_point=mp.Vector3())

        refl = sim.add_flux(f_cen, df, nfreq, refl_fr)
        tran = sim.add_flux(f_cen, df, nfreq, tran_fr)
        sim.load_minus_flux_data(refl, init_refl_data)
        dfts_Z = sim.add_dft_fields([mp.Ez],
                                    fmin,
                                    fmax,
                                    nfreq,
                                    where=mp.Volume(center=mp.Vector3(
                                        0, -sy * 0.5 + dpml + thick * 0.5, 0),
                                                    size=mp.Vector3(sx,
                                                                    thick)))
        sim.run(until_after_sources=mp.stop_when_fields_decayed(
            5, mp.Ez, mp.Vector3(),
            1e-3))  #mp.at_beginning(mp.output_epsilon),
        sim.output_dft(dfts_Z, "dft_Z_fields")
        flux_freqs = mp.get_flux_freqs(refl)
        final_refl_flux = mp.get_fluxes(refl)
        wl = []
        Rs = []
        for i in range(nfreq):
            wl = np.append(wl, 1 / flux_freqs[i])
            Rs = np.append(Rs, -final_refl_flux[i] / init_tran_flux[i])
        sim.reset_meep()
        #get = np.min(Rs)
        en = enhance(Rs, 0)
        get = en, Rs, wl
    elif n == 2:
        #if os.path.exists('dft_Z_fields.h5'):
        #os.remove('dft_Z_fields.h5')
        sim = mp.Simulation(cell_size=cell,
                            boundary_layers=pml_layers,
                            sources=sources,
                            geometry=geometry,
                            symmetries=[mp.Mirror(mp.X)],
                            dimensions=2,
                            resolution=resolution,
                            k_point=mp.Vector3())

        refl = sim.add_flux(f_cen, df, nfreq, refl_fr)
        tran = sim.add_flux(f_cen, df, nfreq, tran_fr)
        sim.load_minus_flux_data(refl, init_refl_data)
        dfts_Z = sim.add_dft_fields([mp.Ez],
                                    fmin,
                                    fmax,
                                    nfreq,
                                    where=mp.Volume(center=mp.Vector3(
                                        0, -sy * 0.5 + dpml + thick * 0.5, 0),
                                                    size=mp.Vector3(sx,
                                                                    thick)))
        sim.run(mp.at_beginning(mp.output_epsilon),
                until_after_sources=mp.stop_when_fields_decayed(
                    5, mp.Ez, mp.Vector3(),
                    1e-3))  #mp.at_beginning(mp.output_epsilon),
        sim.output_dft(dfts_Z, "dft_Z_fields")
        flux_freqs = mp.get_flux_freqs(refl)
        final_refl_flux = mp.get_fluxes(refl)
        final_tran_flux = mp.get_fluxes(tran)
        wl = []
        Rs = []
        Ts = []
        for i in range(nfreq):
            wl = np.append(wl, 1 / flux_freqs[i])
            Rs = np.append(Rs, -final_refl_flux[i] / init_tran_flux[i])
            Ts = np.append(Ts, final_tran_flux[i] / init_tran_flux[i])
        As = 1 - Rs - Ts
        plt.clf()
        plt.figure()
        plt.plot(wl, Rs, 'bo-', label='reflectance')
        plt.plot(wl, Ts, 'ro-', label='transmittance')
        plt.plot(wl, As, 'go-', label='absorption')
        plt.xlabel("wavelength (μm)")
        plt.legend(loc="upper right")
        plt.savefig('Extinction.png')
        #get = np.min(Rs)
        en = enhance(Rs, 1)
        get = en, Rs, wl

        #plt.figure()
        #plt.plot(wl,Rs,'bo-',label='reflectance')
        eps = h5py.File('_last-eps-000000000.h5', 'r')
        eps = eps.get('eps').value
        Enhance = np.rot90(eps)
        plt.clf()
        plt.figure()
        heat_map = sb.heatmap(Enhance,
                              cmap='plasma',
                              xticklabels=False,
                              yticklabels=False)
        plt.xlabel("x-axis")
        plt.ylabel("y-axis")
        plt.savefig('Epsilon.png')

    return (get)
示例#7
0
def test_simulate_wg_opt():
    with goos.OptimizationPlan() as plan:
        wg_in = goos.Cuboid(pos=goos.Constant([-2000, 0, 0]),
                            extents=goos.Constant([3000, 800, 40]),
                            material=goos.material.Material(index=3.45))
        wg_out = goos.Cuboid(pos=goos.Constant([2000, 0, 0]),
                             extents=goos.Constant([3000, 800, 40]),
                             material=goos.material.Material(index=3.45))

        def initializer(size):
            # Set the seed immediately before calling `random` to ensure
            # reproducibility.
            np.random.seed(247)
            return np.random.random(size) * 0.1 + np.ones(size) * 0.7

        var, design = goos.pixelated_cont_shape(
            initializer=initializer,
            pos=goos.Constant([0, 0, 0]),
            extents=[1000, 800, 40],
            pixel_size=[40, 40, 40],
            material=goos.material.Material(index=1),
            material2=goos.material.Material(index=3.45),
        )
        eps = goos.GroupShape([wg_in, wg_out, design])
        sim = meep.FdtdSimulation(
            eps=eps,
            sources=[
                meep.WaveguideModeSource(
                    center=[-1000, 0, 0],
                    extents=[0, 2500, 0],
                    normal=[1, 0, 0],
                    mode_num=2,
                    power=1,
                    wavelength=1550,
                    bandwidth=100,
                )
            ],
            sim_space=meep.SimulationSpace(
                dx=40,
                sim_region=goos.Box3d(
                    center=[0, 0, 0],
                    extents=[4000, 4000, 0],
                ),
                pml_thickness=[400, 400, 400, 400, 0, 0]),
            sim_timing=meep.SimulationTiming(stopping_conditions=[
                meep.StopWhenFieldsDecayed(
                    time_increment=50,
                    component=2,
                    pos=[0, 0, 0],
                    threshold=1e-6,
                )
            ], ),
            background=goos.material.Material(index=1.0),
            outputs=[
                meep.Epsilon(wavelength=1550),
                meep.ElectricField(wavelength=1550),
                meep.WaveguideModeOverlap(wavelength=1550,
                                          center=[1000, 0, 0],
                                          extents=[0, 2500, 0],
                                          normal=[1, 0, 0],
                                          mode_num=0,
                                          power=1),
            ])

        obj = -goos.abs(sim[2])

        import meep as mp
        mp.quiet()
        goos.opt.scipy_minimize(obj,
                                "L-BFGS-B",
                                monitor_list=[obj],
                                max_iters=5)
        plan.run()

        # Check that we can optimize. We choose something over 60% as
        # incorrect gradients will typically not reach this point.
        assert obj.get().array < -0.85

        # As a final check, compare simulation results against Maxwell.
        # Note that dx = 40 for Meep is actually too innaccurate. We therefore
        # resimulate the final structure for both Meep and Maxwell.
        from spins.goos_sim import maxwell
        sim_fdfd = maxwell.fdfd_simulation(
            wavelength=1550,
            eps=eps,
            sources=[
                maxwell.WaveguideModeSource(
                    center=[-1000, 0, 0],
                    extents=[0, 2500, 0],
                    normal=[1, 0, 0],
                    mode_num=2,
                    power=1,
                )
            ],
            simulation_space=maxwell.SimulationSpace(
                mesh=maxwell.UniformMesh(dx=20),
                sim_region=goos.Box3d(
                    center=[0, 0, 0],
                    extents=[4000, 4000, 0],
                ),
                pml_thickness=[400, 400, 400, 400, 0, 0]),
            background=goos.material.Material(index=1.0),
            outputs=[
                maxwell.Epsilon(),
                maxwell.ElectricField(),
                maxwell.WaveguideModeOverlap(center=[1000, 0, 0],
                                             extents=[0, 2500, 0],
                                             normal=[1, 0, 0],
                                             mode_num=0,
                                             power=1),
            ],
            solver="local_direct")

        sim_fdtd_hi = meep.FdtdSimulation(
            eps=eps,
            sources=[
                meep.WaveguideModeSource(
                    center=[-1000, 0, 0],
                    extents=[0, 2500, 0],
                    normal=[1, 0, 0],
                    mode_num=2,
                    power=1,
                    wavelength=1550,
                    bandwidth=100,
                )
            ],
            sim_space=meep.SimulationSpace(
                dx=20,
                sim_region=goos.Box3d(
                    center=[0, 0, 0],
                    extents=[4000, 4000, 0],
                ),
                pml_thickness=[400, 400, 400, 400, 0, 0]),
            sim_timing=meep.SimulationTiming(stopping_conditions=[
                meep.StopWhenFieldsDecayed(
                    time_increment=50,
                    component=2,
                    pos=[0, 0, 0],
                    threshold=1e-6,
                )
            ], ),
            background=goos.material.Material(index=1.0),
            outputs=[
                meep.Epsilon(wavelength=1550),
                meep.ElectricField(wavelength=1550),
                meep.WaveguideModeOverlap(wavelength=1550,
                                          center=[1000, 0, 0],
                                          extents=[0, 2500, 0],
                                          normal=[1, 0, 0],
                                          mode_num=0,
                                          power=1),
            ])
        fdtd_hi_power = goos.abs(sim_fdtd_hi[2])**2
        fdfd_power = goos.abs(sim_fdfd[2])**2

        # Check that power is correct within 0.5%.
        assert np.abs(fdfd_power.get().array - fdtd_hi_power.get().array) < 0.005
示例#8
0
def simulate_metalens(metalens):
    # Setup the MEEP objects
    cell = mp.Vector3(metalens['sim_cell_width'], metalens['sim_cell_height'])
    # All around the simulation cell
    pml_layers = [mp.PML(metalens['pml_width'])]
    # Set up the sources
    sources = [
        mp.Source(src=mp.ContinuousSource(wavelength=metalens['wavelength'],
                                          width=metalens['source_width']),
                  component=mp.Ez,
                  center=mp.Vector3(0, metalens['source_coordinate']),
                  size=mp.Vector3(2 * metalens['ws'], 0),
                  amp_func=out_of_plane_dip_amp_func_Ez(metalens)),
        mp.Source(src=mp.ContinuousSource(wavelength=metalens['wavelength'],
                                          width=metalens['source_width']),
                  component=mp.Hx,
                  center=mp.Vector3(0, metalens['source_coordinate']),
                  size=mp.Vector3(2 * metalens['ws'], 0),
                  amp_func=out_of_plane_dip_amp_func_Hx(metalens))
    ]
    # Set up the symmetries
    syms = []
    if metalens['x_mirror_symmetry']:
        syms.append(mp.Mirror(mp.X))
    sim = mp.Simulation(cell_size=cell,
                        boundary_layers=pml_layers,
                        geometry=metalens['geometry'],
                        force_complex_fields=metalens['complex_fields'],
                        symmetries=syms,
                        sources=sources,
                        resolution=metalens['resolution'])
    start_time = time.time()
    metalens['run_date'] = (
        datetime.datetime.now().strftime("%b %d %Y at %H:%M:%S"))
    mp.quiet(metalens['quiet'])
    sim.init_sim()

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

    # Compute the clock run time and grab the fields
    metalens['array_metadata'] = sim.get_array_metadata()
    metalens['run_time_in_s'] = time.time() - start_time
    metalens['fields'] = {
        'Ez': sim.get_array(component=mp.Ez).transpose(),
        'Hx': sim.get_array(component=mp.Hx).transpose(),
        'Hy': sim.get_array(component=mp.Hy).transpose()
    }
    metalens['eps'] = sim.get_epsilon().transpose()
    # Dump the result to disk
    if metalens['log_to_pkl'][0]:
        if metalens['log_to_pkl'][1] == '':
            pkl_fname = '%smetalens-%s.pkl' % (datadir, metalens['sim_id'])
        else:
            pkl_fname = metalens['log_to_pkl'][1]
        print(pkl_fname)
        pickle.dump(metalens, open(pkl_fname, 'wb'))
    return metalens
示例#9
0
def standard(metalens):
    metalens['run_date'] = int(time())
    matter = mp.Medium(epsilon=metalens['epsilon'])

    pillar_locs = list(
        product(
            [-metalens['pillar_separation'], metalens['pillar_separation']],
            [-metalens['pillar_separation'], metalens['pillar_separation']]))
    pillar_locs.append((0, 0))

    pillars = [
        mp.Cylinder(radius=metalens['pillar_radius'],
                    height=metalens['pillar_height'],
                    center=mp.Vector3(x, y, 0),
                    material=matter) for x, y in pillar_locs
    ]

    substrate = [
        mp.Block(size=mp.Vector3(metalens['sim_cell_width'],
                                 metalens['sim_cell_width'],
                                 metalens['sim_cell_width'] / 2),
                 center=mp.Vector3(0, 0, -metalens['sim_cell_width'] / 4),
                 material=matter)
    ]
    geometry = substrate + pillars
    cell = mp.Vector3(metalens['sim_cell_width'], metalens['sim_cell_width'],
                      metalens['sim_cell_width'])
    pml = [mp.PML(metalens['PML_width'])]
    source = [
        mp.Source(src=mp.ContinuousSource(wavelength=metalens['wavelength']),
                  component=mp.Ex,
                  center=mp.Vector3(0, 0, -metalens['sim_cell_width'] / 4),
                  size=mp.Vector3(0, 0, 0))
    ]
    symmetries = []
    for symmetry in metalens['symmetries']:
        if symmetry == 'x':
            symmetries.append(mp.Mirror(mp.X))
        if symmetry == 'y':
            symmetries.append(mp.Mirror(mp.Y))
    sim = mp.Simulation(cell_size=cell,
                        boundary_layers=pml,
                        geometry=geometry,
                        force_complex_fields=metalens['complex_fields'],
                        symmetries=symmetries,
                        sources=source,
                        resolution=metalens['resolution'])
    start_time = time()
    mp.quiet(metalens['quiet'])
    # mp.verbosity(3)
    sim.init_sim()
    metalens['time_for_init'] = (time() - start_time)
    start_time = time()
    #sim.run(mp.at_end(mp.output_efield(sim)),until=metalens['sim_time'])
    sim.run(until=metalens['sim_time'])
    metalens['time_for_running'] = time() - start_time
    start_time = time()
    sim.filename_prefix = 'standard_candle-%d' % metalens['run_date']
    print(sim.filename_prefix)
    mp.output_efield(sim)
    mp.output_hfield(sim)

    # print("collecting fields...")
    # h5_fname = 'candle-{run_date}.h5'.format(run_date = metalens['run_date'])
    # if metalens['save_fields_to_h5'] and rank ==0:#(not os.path.exists(h5_fname)):
    #     metalens['h5_fname'] = h5_fname
    #     h5_file = h5py.File(h5_fname,'w', driver='mpio', comm=MPI.COMM_WORLD)
    #     fields = h5_file.create_group('fields')
    #     Ex = np.transpose(sim.get_array(component=mp.Ex),(2,1,0))
    #     metalens['voxels'] = Ex.shape[0]**3
    #     metalens['voxels'] = Ex.shape[0]**3
    #     metalens['above_pillar_index'] = int(Ex.shape[0]/2. + 3*metalens['pillar_height']*metalens['resolution']/2)
    #     mp.output_efield('test')
    #     fields.create_dataset('Ex',
    #            data=Ex)
    #     del Ex
    #     fields.create_dataset('Ey',
    #            data=np.transpose(sim.get_array(component=mp.Ey),(2,1,0)))
    #     fields.create_dataset('Ez',
    #            data=np.transpose(sim.get_array(component=mp.Ez),(2,1,0)))
    #     fields.create_dataset('Hx',
    #            data=np.transpose(sim.get_array(component=mp.Hx),(2,1,0)))
    #     fields.create_dataset('Hy',
    #            data=np.transpose(sim.get_array(component=mp.Hy),(2,1,0)))
    #     fields.create_dataset('Hz',
    #            data=np.transpose(sim.get_array(component=mp.Hz),(2,1,0)))
    #     h5_file.close()
    # else:
    #     metalens['fields'] = {
    #       'Ex': np.transpose(sim.get_array(component=mp.Ex),(2,1,0)),
    #       'Ey': np.transpose(sim.get_array(component=mp.Ey),(2,1,0)),
    #       'Ez': np.transpose(sim.get_array(component=mp.Ez),(2,1,0)),
    #       'Hx': np.transpose(sim.get_array(component=mp.Hx),(2,1,0)),
    #       'Hy': np.transpose(sim.get_array(component=mp.Hy),(2,1,0)),
    #       'Hz': np.transpose(sim.get_array(component=mp.Hz),(2,1,0))
    #       }
    #     metalens['voxels'] = metalens['fields']['Ex'].shape[0]**3
    #     metalens['above_pillar_index'] = int(metalens['fields']['Ex'].shape[0]/2. + 3*metalens['pillar_height']*metalens['resolution']/2)
    metalens['voxels'] = int((8 * metalens['resolution'])**3)
    metalens['time_for_saving_fields'] = round(time() - start_time, 0)
    metalens['max_mem_usage_in_Gb'] = metalens[
        'num_cores'] * resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1E6
    metalens['max_mem_usage_in_Gb'] = round(metalens['max_mem_usage_in_Gb'], 2)
    metalens['summary'] = '''init time = {time_for_init:.1f} s
    running simulation = {time_for_running:.1f} s
    saving fields = {time_for_saving_fields:.1f} s
    num voxels = {voxels}
    max memory usage = {max_mem_usage_in_Gb:.2f} Gb'''.format(**metalens)
    metalens['pkl_fname'] = 'standard-candle-%d.pkl' % metalens['run_date']
    return metalens
示例#10
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']
        }