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)
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)
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)
''' 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 #----------------------------------------------------------------------
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)
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
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
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
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'] }