def __init__(self, field=None, component=meep.Ex, timebounds=(0, np.inf), timestep=0, volume=None, normal=None, position=None, model=None, pad=0, outputdir="", name=None, outputPNGs=False, outputGIF=True, outputHDF=False, outputVTK=False): """ """ self.field = field self.outputdir = outputdir self.component = component self.timebounds = timebounds self.timestep = timestep self.outputPNGs = outputPNGs self.outputGIF = outputGIF self.outputHDF = outputHDF self.outputVTK = outputVTK if volume: self.volume = volume meep.master_printf("Will record slices at times %.3g, %.3g ... %.3g s \n" % (timebounds[0], timebounds[0]+timestep, timebounds[1])) else: #if not position: #raise RuntimeError("Specify the position of the cut plane (on the axis perpendicular to it)") if normal=="x": self.volume = meep.volume( meep.vec(position, -model.size_y/2+pad, -model.size_z/2+pad), meep.vec(position, model.size_y/2-pad, model.size_z/2-pad)) elif normal=="y": self.volume = meep.volume( meep.vec(-model.size_x/2+pad, position, -model.size_z/2+pad), meep.vec(model.size_x/2-pad, position, model.size_z/2-pad)) elif normal=="z": self.volume = meep.volume( meep.vec(-model.size_x/2+pad, -model.size_y/2+pad, position), meep.vec(model.size_x/2-pad, model.size_y/2-pad, position)) #else: #print normal #raise RuntimeError("Specify the normal parameter as 'x', 'y' or 'z'") meep.master_printf("Will record slices at %s=%.3g m, at times %g, %g ... %g s \n" \ % (normal, position, timebounds[0], timebounds[0]+timestep, timebounds[1])) self.outputdir = outputdir if not name: if not position or not normal: self.name = "SliceByVolume" else: self.name = "Slice_%s%.3e" % (normal, position) else: self.name = name self.images_number = 0 self.last_slice_time = 0. #slices=[] #slices.append({"name":"Ex_xz_slice", "component":meep.Ex, "geom": if not os.path.exists(outputdir): run_bash("mkdir -p %s" % outputdir, anyprocess=True) self.openfile = meep.prepareHDF5File("%s.h5" % (os.path.join(self.outputdir, self.name)))
def get_output_volume(self, meepVolume): sur_max_vec = meepVolume.surroundings().get_max_corner() if (self.normal_vector == 'x'): if (self.cut_value < 0.): self.cut_value = sur_max_vec.x() / 2.0 front_vec = meep.vec(self.cut_value, 0.0, 0.0) rear_vec = meep.vec(self.cut_value, sur_max_vec.y(), sur_max_vec.z()) elif (self.normal_vector == 'y'): if (self.cut_value < 0.): self.cut_value = sur_max_vec.y() / 2.0 front_vec = meep.vec(0.0, self.cut_value, 0.0) rear_vec = meep.vec(sur_max_vec.x(), self.cut_value, sur_max_vec.z()) else: if (self.cut_value < 0.): self.cut_value = sur_max_vec.z() / 2.0 front_vec = meep.vec(0.0, 0.0, self.cut_value) rear_vec = meep.vec(sur_max_vec.x(), sur_max_vec.y(), self.cut_value) perp_vol = meep.volume(front_vec, rear_vec) return perp_vol
vol = meep.vol3d(model.size_x, model.size_y, model.size_z, 1./model.resolution) vol.center_origin() s = meep_utils.init_structure(model=model, volume=vol, pml_axes=meep.Z) f = meep.fields(s) # Define the Bloch-periodic boundaries (any transversal component of k-vector is allowed) f.use_bloch(meep.X, getattr(model, 'Kx', 0) / (-2*np.pi)) f.use_bloch(meep.Y, getattr(model, 'Ky', 0) / (-2*np.pi)) # Add the field source (see meep_utils for an example of how an arbitrary source waveform is defined) if not getattr(model, 'frequency', None): ## (temporal source shape) #src_time_type = meep.band_src_time(model.src_freq/c, model.src_width/c, model.simtime*c/1.1) src_time_type = meep.gaussian_src_time(model.src_freq/c, model.src_width/c) else: src_time_type = meep.continuous_src_time(getattr(model, 'frequency', None)/c) srcvolume = meep.volume( ## (spatial source shape) meep.vec(-model.size_x/2, -model.size_y/2, -model.size_z/2+model.pml_thickness), meep.vec( model.size_x/2, model.size_y/2, -model.size_z/2+model.pml_thickness)) #f.add_volume_source(meep.Ex, src_time_type, srcvolume) ## Replace the f.add_volume_source(meep.Ex, srctype, srcvolume) line with following: ## Option for a custom source (e.g. exciting some waveguide mode) class SrcAmplitudeFactor(meep.Callback): ## The source amplitude is complex -> phase factor modifies its direction ## todo: implement in MEEP: we should define an AmplitudeVolume() object and reuse it for monitors later def __init__(self, Kx=0, Ky=0): meep.Callback.__init__(self) (self.Kx, self.Ky) = Kx, Ky def complex_vec(self, vec): ## Note: the 'vec' coordinates are _relative_ to the source center # (oblique) plane wave source: return np.exp(-1j*(self.Kx*vec.x() + self.Ky*vec.y())) # (oblique) Gaussian beam source:
f.use_bloch(meep.X, getattr(model, 'Kx', 0) / (-2 * np.pi)) f.use_bloch(meep.Y, getattr(model, 'Ky', 0) / (-2 * np.pi)) f.use_bloch(meep.Z, getattr(model, 'Kz', 0) / (-2 * np.pi)) # Add the field source (see meep_utils for an example of how an arbitrary source waveform is defined) if not getattr(model, 'frequency_domain', None): ## Select the source dependence on time src_time_type = meep_utils.band_src_time(model.src_freq / c, model.src_width / c, model.simtime * c / 10) #src_time_type = meep.gaussian_src_time(model.src_freq/c, model.src_width/c) else: src_time_type = meep.continuous_src_time( getattr(model, 'frequency', None) / c) srcvolume = meep.volume( ## Source must fill the whole simulation volume meep.vec(-model.size_x / 2, -model.size_y / 2, -model.size_z / 2), meep.vec(model.size_x / 2, model.size_y / 2, model.size_z / 2)) class AmplitudeFactor(meep.Callback): def __init__(self, Kx=0, Ky=0, Kz=0): meep.Callback.__init__(self) (self.Kx, self.Ky, self.Kz) = Kx, Ky, Kz def complex_vec( self, vec ): ## Note: the 'vec' coordinates are _relative_ to the source center ## Current-driven homogenisation source forces the K-vector in whole unit cell return np.exp( -1j * (self.Kx * vec.x() + self.Ky * vec.y() + self.Kz * vec.z()))
1. / model.resolution) vol.center_origin() s = meep_utils.init_structure(model=model, volume=vol, pml_axes=meep.Z) ## Create fields with Bloch-periodic boundaries f = meep.fields(s) # Define the Bloch-periodic boundaries (any transversal component of k-vector is allowed) f.use_bloch(meep.X, getattr(model, 'Kx', 0) / (-2 * np.pi)) f.use_bloch(meep.Y, getattr(model, 'Ky', 0) / (-2 * np.pi)) # Add the field source (see meep_utils for an example of how an arbitrary source waveform is defined) src_time_type = meep.gaussian_src_time(model.src_freq / c, model.src_width / c) #src_time_type = meep.continuous_src_time(model.src_freq/c) srcvolume = meep.volume( meep.vec(-model.size_x / 2, -model.size_y / 2, -model.size_z / 2 + model.pml_thickness), meep.vec(+model.size_x / 2, +model.size_y / 2, -model.size_z / 2 + model.pml_thickness)) #f.add_volume_source(meep.Ex, src_time_type, srcvolume) class SrcAmplitudeFactor(meep.Callback): ## The source amplitude is complex -> phase factor modifies its direction ## todo: implement in MEEP: we should define an AmplitudeVolume() object and reuse it for monitors later def __init__(self, Kx=0, Ky=0): meep.Callback.__init__(self) (self.Kx, self.Ky) = Kx, Ky def complex_vec( self, vec
sim_param, model_param = meep_utils.process_param(sys.argv[1:]) model = PlasmonFilm_model(**model_param) if sim_param['frequency_domain']: model.simulation_name += ("_frequency=%.4e" % sim_param['frequency']) ## Initialize volume, structure and the fields according to the model vol = meep.vol3d(model.size_x, model.size_y, model.size_z, 1./model.resolution) vol.center_origin() s = meep_utils.init_structure(model=model, volume=vol, sim_param=sim_param, pml_axes="All") ## Create fields with Bloch-periodic boundaries f = meep.fields(s) # Add the field source (see meep_utils for an example of how an arbitrary source waveform is defined) src_time_type = meep.continuous_src_time(model.src_freq/c) srcvolume = meep.volume( meep.vec(-model.size_x/2, -model.size_y/2, -model.size_z/2+model.pml_thickness), meep.vec(+model.size_x/2, +model.size_y/2, -model.size_z/2+model.pml_thickness)) f.add_volume_source(meep.Ex, src_time_type, srcvolume) ## Define visualisation output slices = [meep_utils.Slice(model=model, field=f, components=(meep.Dielectric), at_t=0, name='EPS')] slices += [meep_utils.Slice(model=model, field=f, components=meep.Ez, at_y=0, min_timestep=.3e-15, outputgif=True, name='ParallelCut')] slices += [meep_utils.Slice(model=model, field=f, components=meep.Ez, at_z=model.metalthick/2+model.resolution, min_timestep=.3e-15, outputgif=True, name='PerpendicularCut')] slices += [meep_utils.Slice(model=model, field=f, components=meep.Ex, at_t=100e-15)] if not sim_param['frequency_domain']: ## time-domain computation f.step(); timer = meep_utils.Timer(simtime=model.simtime); meep.quiet(True) # use custom progress messages while (f.time()/c < model.simtime): # timestepping cycle f.step() timer.print_progress(f.time()/c)
field = meep.fields(s) #field.use_bloch(meep.Z, 1) ## periodic along the cylinder XXX # (removing cylinder caps -> making an infinite waveguide with periodic boundary condition, change pml_axes=meep.XY) # Add the field source (see meep_utils for an example of how an arbitrary source waveform is defined) if not sim_param['frequency_domain']: ## Select the source dependence on time #src_time_type = meep.band_src_time(-model.src_freq/c, model.src_width/c, model.simtime*c/1.1) src_time_type = meep.gaussian_src_time( -model.src_freq / c, model.src_width / c) ## negative frequency supplied -> e^(+i omega t) convention else: src_time_type = meep.continuous_src_time( -sim_param['frequency'] / c ) ## TODO check in freq domain that negative frequency is OK, and is it needed? srcvolume = meep.volume( meep.vec(model.radius * .15, -model.radius * .25, -model.height * .15), meep.vec(model.radius * .15, -model.radius * .25, -model.height * .15)) field.add_volume_source( meep.Ez, src_time_type, srcvolume ) ## source of oblique polarization - excites both TE and TM modes field.add_volume_source(meep.Ex, src_time_type, srcvolume) slice_makers = [] #slice_makers += [meep_utils.Slice(model=model, field=field, components=(meep.Ex, meep.Ey, meep.Ez), at_t=3, name="ElectricAtEnd")] #slice_makers += [meep_utils.Slice(model=model, field=field, components=(meep.Hx, meep.Hy, meep.Hz), at_t=3, name="MagneticAtEnd")] #slice_makers = [meep_utils.Slice(model=model, field=field, components=(meep.Dielectric), at_t=0, name='EPS')] if not sim_param['frequency_domain']: ## time-domain computation field.step() dt = (field.time() / c) meep_utils.lorentzian_unstable_check_new(model, dt, quit_on_warning=False)
def run(self): ## TEMPORARY SETTINGS wg_bottom = 0.7 wg_top = 0.7 + 0.22 wg_center = (wg_bottom + wg_top) / 2. #top = 0.7 + 0.38 ## preparing po = self.property_object self.engine.initialise_engine(self.landscape) fields = meep.fields(self.engine.structure) self.save_engine_dielectricum_to_file(po.eps_filename) ## Sources print 'Center wavelength:', po.wavelength print 'Bandwidth:', po.pulse_width center_freq = 1.0 / (float(po.wavelength)) pulse_width_freq = (float(po.pulse_width)) / ( float(po.wavelength)) * center_freq print 'Center frequency:', center_freq print 'Bandwidth:', pulse_width_freq if (po.pulsed_source): src = meep.gaussian_src_time(center_freq, pulse_width_freq) else: src = meep.continuous_src_time(center_freq) source_port_position = po.input_port.transform_copy( Translation(translation=(po.source_input_port_offset, 0))).position print 'wg_center_old:', wg_center wg_center = (po.input_port.wg_definition.process.wg_upper_z_coord + po.input_port.wg_definition.process.wg_lower_z_coord) / 2. print 'wg_center_new:', wg_center c = Coord3(source_port_position[0], source_port_position[1], wg_center) print 'coord:', c source_position_vec = self.make_meep_vec(c) fields.add_point_source(meep.Ey, src, source_position_vec) ## 2D Cross section volumes for oc in po.output_cuts: fn = '%s_eps.h5' % oc.filename vol = oc.get_output_volume(self.engine.meepVol) f_eps = meep.prepareHDF5File(fn) fields.output_hdf5(meep.Dielectric, vol, f_eps) del f_eps system('h5topng %s' % fn) ### Fluxplanes self.fluxes = [] for p in po.output_ports: pp = p.position port_width = p.wg_definition.wg_width wg_bottom = p.wg_definition.process.wg_lower_z_coord wg_top = p.wg_definition.process.wg_upper_z_coord ## Be aware: this is only for ports along y-axis!! vec_near = self.make_meep_vec( Coord3(pp[0], pp[1] - port_width / 2.0, wg_bottom)) vec_far = self.make_meep_vec( Coord3(pp[0], pp[1] + port_width / 2.0, wg_top)) fluxplane = meep.volume(vec_near, vec_far) fx = fields.add_dft_flux_plane( fluxplane, center_freq - (pulse_width_freq / 4.0), center_freq + (pulse_width_freq / 4.0), po.dft_terms) self.fluxes.append(fx) ## Reverse one of the fluxes if necessary if po.load_reversed_flux_from_file_ID > -1: self.fluxes[po.load_reversed_flux_from_file_ID].load_hdf5( fields, po.load_reversed_flux_from_file_filename) if (po.pulsed_source): stop = po.stop_time_multiplier * fields.last_source_time() else: stop = po.stop_time print 'Simulation will run for', stop, 'time units' output_files = [] for oc in po.output_cuts: fn = '%s.h5' % oc.filename oc_file = meep.prepareHDF5File(fn) output_files.append(oc_file) i = 0 n_o_output = 0 while (fields.time() < stop): if (i > po.output_steps): j = 0 for oc in po.output_cuts: vol = oc.get_output_volume(self.engine.meepVol) fields.output_hdf5(meep.Ey, vol, output_files[j], 1) j += 1 n_o_output += 1 i = 0 fields.step() i += 1 print n_o_output, 'images outputted' print 'Outputting field images..' del output_files[:] for oc in po.output_cuts: fn = '%s.h5' % oc.filename fn_eps = '%s_eps.h5' % oc.filename st = 'h5topng -t 0:%d -R -Zc dkbluered -a yarg -A %s %s' % ( n_o_output - 1, fn_eps, fn) print st system(st) print 'Outputting done!' #print 'obtaining fluxes:' self.flux_data = [] for i in range(len(po.output_ports)): fd = meep.getFluxData(self.fluxes[i]) self.flux_data.append(fd) #print fd ## Save flux data if necesarry if po.save_reversed_flux_to_file_ID > -1: fx = self.fluxes[po.save_reversed_flux_to_file_ID] fx.scale_dfts(-1) fx.save_hdf5(fields, po.save_reversed_flux_to_file_filename) return
#model = Wedge_model(**model_param) #from model_SapphireBars import * #model = SapphireBars(**model_param) if sim_param['frequency_domain']: model.simulation_name += ("_frequency=%.4e" % sim_param['frequency']) meep.master_printf("Simulation name:\n\t%s\n" % model.simulation_name) ## TODO print parameters in a table ## Initialize volume vol = meep.vol3d(model.size_x, model.size_y, model.size_z, 1. / model.resolution) volume_except_pml = meep.volume( meep.vec(-model.size_x / 2, -model.size_y / 2, -model.size_z / 2 + model.pml_thickness * 0), meep.vec(model.size_x / 2, model.size_y / 2, model.size_z / 2 - model.pml_thickness * 0)) vol.center_origin() ## Define the Perfectly Matched Layers #perfectly_matched_layers = meep.pml(model.pml_thickness, meep.Z) ## PML on both faces at Z axis perfectly_matched_layers = meep.pml(model.pml_thickness) ## PML on all faces if not sim_param['frequency_domain']: meep.master_printf("== Time domain structure setup ==\n") ## Define each polarizability by redirecting the callback to the corresponding "where_material" function ## Define the frequency-independent epsilon for all materials (needed here, before defining s, or unstable) model.double_vec = model.eps meep.set_EPS_Callback(model.__disown__()) s = meep.structure(vol, meep.EPS, perfectly_matched_layers,
#model = PKCutSheet_model_test(**model_param) #model = Fishnet_model(**model_param) model = Wedge_model(**model_param) #from model_SapphireBars import * #model = SapphireBars(**model_param) if sim_param['frequency_domain']: model.simulation_name += ("_frequency=%.4e" % sim_param['frequency']) meep.master_printf("Simulation name:\n\t%s\n" % model.simulation_name) ## TODO print parameters in a table ## Initialize volume vol = meep.vol3d(model.size_x, model.size_y, model.size_z, 1./model.resolution) volume_except_pml = meep.volume( meep.vec(-model.size_x/2, -model.size_y/2, -model.size_z/2+model.pml_thickness*0), meep.vec(model.size_x/2, model.size_y/2, model.size_z/2-model.pml_thickness*0)) vol.center_origin() ## Define the Perfectly Matched Layers perfectly_matched_layers = meep.pml(model.pml_thickness) ## PML on both faces at Z axis if not sim_param['frequency_domain']: meep.master_printf("== Time domain structure setup ==\n") ## Define each polarizability by redirecting the callback to the corresponding "where_material" function ## Define the frequency-independent epsilon for all materials (needed here, before defining s, or unstable) model.double_vec = model.get_static_permittivity; meep.set_EPS_Callback(model.__disown__()) s = meep.structure(vol, meep.EPS, perfectly_matched_layers, meep.identity()) ## Add all the materials model.build_polarizabilities(s)
vol.center_origin() s = meep_utils.init_structure(model=model, volume=vol, sim_param=sim_param, pml_axes="All") ## XXX meep.XY ## Create the fields object, and define the Bloch-periodic boundaries (any transversal component of k-vector is allowed) field = meep.fields(s) #field.use_bloch(meep.Z, 1) ## periodic along the cylinder XXX # (removing cylinder caps -> making an infinite waveguide with periodic boundary condition, change pml_axes=meep.XY) # Add the field source (see meep_utils for an example of how an arbitrary source waveform is defined) if not sim_param['frequency_domain']: ## Select the source dependence on time #src_time_type = meep.band_src_time(-model.src_freq/c, model.src_width/c, model.simtime*c/1.1) src_time_type = meep.gaussian_src_time(-model.src_freq/c, model.src_width/c) ## negative frequency supplied -> e^(+i omega t) convention else: src_time_type = meep.continuous_src_time(-sim_param['frequency']/c) ## TODO check in freq domain that negative frequency is OK, and is it needed? srcvolume = meep.volume( meep.vec(model.radius*.15, -model.radius*.25, -model.height*.15), meep.vec(model.radius*.15, -model.radius*.25, -model.height*.15)) field.add_volume_source(meep.Ez, src_time_type, srcvolume) ## source of oblique polarization - excites both TE and TM modes field.add_volume_source(meep.Ex, src_time_type, srcvolume) slice_makers = [] #slice_makers += [meep_utils.Slice(model=model, field=field, components=(meep.Ex, meep.Ey, meep.Ez), at_t=3, name="ElectricAtEnd")] #slice_makers += [meep_utils.Slice(model=model, field=field, components=(meep.Hx, meep.Hy, meep.Hz), at_t=3, name="MagneticAtEnd")] #slice_makers = [meep_utils.Slice(model=model, field=field, components=(meep.Dielectric), at_t=0, name='EPS')] if not sim_param['frequency_domain']: ## time-domain computation field.step() dt = (field.time()/c) meep_utils.lorentzian_unstable_check_new(model, dt, quit_on_warning=False) timer = meep_utils.Timer(simtime=model.simtime); meep.quiet(True) # use custom progress messages monitor_point = meep.vec(-model.radius*.5, model.radius*.3, model.height*.3)
vol.center_origin() s = meep_utils.init_structure(model=model, volume=vol, pml_axes="None") f = meep.fields(s) # Define the Bloch-periodic boundaries (any transversal component of k-vector is allowed) f.use_bloch(meep.X, getattr(model, 'Kx', 0) / (-2*np.pi)) f.use_bloch(meep.Y, getattr(model, 'Ky', 0) / (-2*np.pi)) f.use_bloch(meep.Z, getattr(model, 'Kz', 0) / (-2*np.pi)) # Add the field source (see meep_utils for an example of how an arbitrary source waveform is defined) if not getattr(model, 'frequency_domain', None): ## Select the source dependence on time src_time_type = meep_utils.band_src_time(model.src_freq/c, model.src_width/c, model.simtime*c/10) #src_time_type = meep.gaussian_src_time(model.src_freq/c, model.src_width/c) else: src_time_type = meep.continuous_src_time(getattr(model, 'frequency', None)/c) srcvolume = meep.volume( ## Source must fill the whole simulation volume meep.vec(-model.size_x/2, -model.size_y/2, -model.size_z/2), meep.vec( model.size_x/2, model.size_y/2, model.size_z/2)) class AmplitudeFactor(meep.Callback): def __init__(self, Kx=0, Ky=0, Kz=0): meep.Callback.__init__(self) (self.Kx, self.Ky, self.Kz) = Kx, Ky, Kz def complex_vec(self, vec): ## Note: the 'vec' coordinates are _relative_ to the source center ## Current-driven homogenisation source forces the K-vector in whole unit cell return np.exp(-1j*(self.Kx*vec.x() + self.Ky*vec.y() + self.Kz*vec.z())) af = AmplitudeFactor(Kx=getattr(model, 'Kx',.0), Ky=getattr(model, 'Ky',.0), Kz=getattr(model, 'Kz',.0)) meep.set_AMPL_Callback(af.__disown__()) f.add_volume_source(meep.Ex, src_time_type, srcvolume, meep.AMPL) ## Define the volume monitor for CDH monitor_options = {'size_x':model.size_x, 'size_y':model.size_y, 'size_z':model.size_z,