def __init__(self, simul_volume, meep_volume): try: Meep.CallbackMatrix2D.__init__(self) #ipcore properties cannot be used here in combination with swig wrapper around Meep.Callback class - FIXME - to be investigated furher if not isinstance(simul_volume, __SimulationVolume__): raise AttributeException( "Parameter simul_volume of class MeepMaterial2D must be of type __SimulationVolume__" ) resolution_factor = simul_volume.resolution_factor LOG.debug( "Meep : using a resolution factor of %i (Numpy matrix has %i times higher resolution than the Meep grid)." % (resolution_factor, resolution_factor)) meep_resolution = meep_volume.a material_matrix = simul_volume.get_material_dataset_window( meep_resolution * resolution_factor) #convert the material matrix to a matrix with epsilon values (doubles) from pysics.materials.electromagnetics import transform_material_stack_matrix_in_chi3_matrix self.material_chi3_matrix = transform_material_stack_matrix_in_chi3_matrix( material_matrix) self.set_matrix_2D(self.material_chi3_matrix, meep_volume, resolution_factor) LOG.debug( "Meep node %i -MeepMaterial2D (chi3) object initialized." % int(Meep.my_rank())) except Exception, e: print "Exception in MeepMaterial2D::__init__ : %s" % e raise e
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 visualize_2d(self, show = True, save_to_image = False, save_to_image_path = "./", save_to_image_filename_without_ext = None, fig_size_factor = 0.1, enter_tk_mainloop = True, aspect_ratio_equal = True, size = None, **kwargs): self.__initialize(**kwargs) from pysimul.visualization.visualization import SimulationVolumeVisualization2D vis = SimulationVolumeVisualization2D(simulation_volume = self.simul_def.landscape.simulation_volume) fig = vis.visualize(aspect_ratio_equal) if show: from ipkiss.visualisation.show import show show(fig, title = self.simul_def.landscape.simulation_volume.name, enter_tk_mainloop = enter_tk_mainloop) if save_to_image: name = self.simul_def.landscape.simulation_volume.name si = self.simul_def.landscape.simulation_volume.size_info fig_size_factor = fig_size_factor #default = 0.1 from dependencies.matplotlib_wrapper import Tk, FigureCanvasTkAgg fig_canvas = FigureCanvasTkAgg(fig) if not size is None: fig.set_size_inches(size) else: fig.set_size_inches((si.width * fig_size_factor, si.height * fig_size_factor)) if save_to_image_filename_without_ext is None: fname = name else: fname = save_to_image_filename_without_ext filename_svg = save_to_image_path+"%s.svg" %fname fig.savefig(filename_svg) filename_png = save_to_image_path+"%s.png" %fname fig.savefig(filename_png) LOG.debug("Virtual fabrication imaged saved as %s.\n>>> Use INKSCAPE to visualize and zoom in on the file (free download at inkscape.org)" %filename_svg) return filename_png
def prepareHDF5File(self, filename): '''Prepare a HDF5 file for output''' LOG.debug("Meep node %i -Preparing HDF5 file '%s'..." %(self.node_nr, filename)) f = open(filename, 'w') f.close() h5f = Meep.h5file(filename, Meep.h5file.READWRITE) return h5f
def closeHDF5File(self, pFileRef): '''Close the HDF5 file''' if (Meep.am_master()): LOG.debug("Meep node %i - Closing HDF5 file..." %(self.node_nr)) if pFileRef == None: raise PythonSimulateException("MeepSimulationEngine::getFieldAtMonitorPoint - call prepareHDF5File first : cannot close a file that is not open.") del(pFileRef)
def exportDielectricH5(self, fileName = None): '''Export the dielectric to a HDF5 output file''' if (fileName == None): fileName = "meep_eps.h5" LOG.debug("Meep node %i -Exporting dielectric to H5-file : %s" %(self.node_nr,fileName)) dielectric_file_handle = Meep.prepareHDF5File(fileName) self.meep_fields.output_hdf5(Meep.Dielectric, self.meepVol.surroundings(), dielectric_file_handle) self.closeHDF5File(dielectric_file_handle) LOG.debug("Meep node %i -Export to HDF5 done." %(self.node_nr))
def save_dielectricum_image(self, filename = None): #prepare the filename for the export to HDF5 if (filename is None): filename = self.landscape.simulation_id+"_Eps.h5" #let Meep export the dielectricum to HDF5 self.exportDielectricH5(filename) if (Meep.am_master()): LOG.debug("Meep node %i -Dielectricum saved to file %s..." %(self.node_nr,filename)) if self.dim == 2: cmd = "h5topng -a /home/emmanuel/workspace/Meep_tutorial/colormaps/yarg "+filename os.system(cmd) return filename
def __run_os_cmd__(self, cmd): if self.__get_meep_engine_type__() == 0: import subprocess import os fnull = open(os.devnull, 'w') LOG.debug(cmd) result_value = subprocess.call([cmd], shell = True, stdout = fnull, stderr = fnull) fnull.close() return result_value else: print "Additionally, run the following command : ", cmd return 0
def complex_vec(self,vec): #BEWARE, these are coordinates RELATIVE to the source center !!!! try: x = vec.x() y = vec.y() factor = self.source.get_amplitude_factor(Coord2(x,y)) LOG.debug("Meep node %i -Amplitude factor for x=%f - y=%f is: %f \n" %(int(Meep.my_rank()),x,y, factor) ) if (isinstance(factor, complex)): return factor else: return complex(factor) except Exception, e: print "Exception in AmplitudeFactor::complex_vec (%f,%f): %s" %(x,y,e) raise e
def write_gdsii(self, filename_or_stream, unit = TECH.METRICS.UNIT, grid = TECH.METRICS.GRID, layer_map = None): from ipkiss.primitives import Library from ipkiss.io.output_gdsii import FileOutputGdsii, OutputGdsii from ipkiss.log import IPKISS_LOG as LOG my_lib = Library(name = self.name, unit = unit, grid = grid) my_lib += self if layer_map is None: layer_map = TECH.GDSII.EXPORT_LAYER_MAP #bind only at this moment, because TECH.GDSII.EXPORT_LAYER_MAP could have been assigned a different value since original loading of this module if isinstance(filename_or_stream, str): OP = FileOutputGdsii(filename_or_stream, layer_map = layer_map) elif (filename_or_stream == sys.stdout): OP = OutputGdsii(sys.stdout, layer_map = layer_map) OP.write(my_lib) LOG.debug("Finished writing structure to GDS2.")
def __addMeepFluxplane(self, flx, meep_fields): '''Convert a fluxplane (runtime.basic.Fluxplane) into a Meep fluxplane and add it to the Meep fields object''' if not isinstance(flx, Fluxplane): raise InvalidArgumentException( "Invalid argument:: not of type runtime.basic.Fluxplane") LOG.debug( "Meep node %i -Creating Meep volume object for the flux plane..." % (self.node_nr)) vec1 = self.__make_meep_vec__(flx.north) vec2 = self.__make_meep_vec__(flx.south) print "Meep node %i : flux plane between points (%f , %f) and (%f , %f) " % ( self.node_nr, vec1.x(), vec1.y(), vec2.x(), vec2.y()) meepFlxVol = Meep.volume(vec1, vec2) center_freq = 1.0 / (float(flx.center_wavelength) / 1000.0) pw = ((float(flx.pulse_width) / 1000.0) / (float(flx.center_wavelength) / 1000.0)) * center_freq max_freq = center_freq + pw / 2.0 min_freq = center_freq - pw / 2.0 LOG.debug( "Meep node %i -Now adding the fluxplane to the Meep field..." % (self.node_nr)) meepFluxplane = meep_fields.add_dft_flux_plane( meepFlxVol, min_freq, max_freq, flx.number_of_sampling_freq) flx.flux_per_freq_callback = lambda: Meep.getFluxData(meepFluxplane) setattr(flx, "save_hdf5", lambda fn: self.__saveFluxToHDF5(meepFluxplane, fn)) setattr(flx, "scale", lambda factor: self.__scaleFluxplane(meepFluxplane, factor)) setattr(flx, "load_hdf5", lambda fn: self.__loadFluxFromHDF5(meepFluxplane, fn)) LOG.debug("Meep node %i -initializeing the fluxplane ..." % (self.node_nr)) flx.initialize() LOG.debug("Meep node %i - done with fluxplane ..." % (self.node_nr))
def __call__(self, item): """ processes the item """ LOG.debug("Applying all subfilters. Item = %s" % item) v = item for R in self._sub_filters: LOG.debug("** Applying subfilter %s to %s" % (R, v)) v = R(v) LOG.debug("** Result after filtering = %s\n" % v) LOG.debug("Finished applying all subfilters. Item = %s" % item) return v
def filter(self, item): import inspect T = type(item) if inspect.isclass(T): for M in inspect.getmro(T): N = "__filter_%s__" % M.__name__ if hasattr(self, N): LOG.debug("Applying method %s of %s to %s" %(N,self,item)) return getattr(self, N)(item) return self.__filter_default__(item) else: N = "__filter_%s" % T.__name__ if hasattr(self, N): expr = "self.%s(item)" % N LOG.debug("Executing %s" %expr) return eval(expr) else: return self.__filter_default__(item)
def __call__(self, item): """ processes the item """ LOG.debug("Applying all subfilters. Item = %s" % item) v = item k = self.__filter_status.keys() for R in self._sub_filters: if R.name not in k or self.__filter_status[R.name]: LOG.debug("** Applying subfilter %s to %s" % (R, v)) v = R(v) LOG.debug("** Result after filtering = %s\n" % v) LOG.debug("Finished applying all subfilters. Item = %s" % item) return v
def __filter_Path__(self, item): if item.line_width != 0: shapes = ShapeCutFilter.__filter_Shape__(self, item.shape) if item.absolute_line_width: line_width = -item.line_width else: line_width = item.line_width * item.transformation.magnification return [ Path(item.layer, sh, line_width, item.path_type, transformation=item.transformation) for sh in shapes ] else: LOG.debug("Path linewidth is zero: PathCutFilter not applied.") return [item]
def __addMeepSource(self, src, meep_fields): '''Convert a source (runtime.basic.__EMSource__) into a Meep source and add it to the Meep fields object''' if not isinstance(src, __EMSource__): raise InvalidArgumentException("Invalid argument:: not of type runtime.basic.__EMSource__") LOG.debug("Meep node %i -Adding source...." %(self.node_nr)) #create Meep source object meepSource = None center_freq = 1.0 / (float(src.center_wavelength) / 1000.0) if isinstance(src, __GaussianSource__): pw = ( (float(src.pulse_width)/1000.0) / (float(src.center_wavelength)/1000.0) ) * center_freq meepSource = Meep.gaussian_src_time(center_freq, pw) if isinstance(src, __ContinuousSource__): meepSource = Meep.continuous_src_time(center_freq, src.smoothing_width, src.start_time, src.stop_time, src.cutoff) #create Meep component meepComp = self.__makeMeepComponent(src.field_component) #add source to the Meep field if isinstance(src, __EMPointSource__): vec = self.__make_meep_vec__(src.point) meep_fields.add_point_source(meepComp, meepSource, vec) print "Point source at point (%f , %f)" %(vec.x(), vec.y()) elif isinstance(src, __EMVolumeSource__): vec1 = self.__make_meep_vec__(src.south) vec2 = self.__make_meep_vec__(src.north) LOG.debug("Meep node %i -Creating volume for source plane..." %(self.node_nr)) meepSrcVol = Meep.volume(vec1, vec2) print "Meep node %i - source plane between points (%f , %f) and (%f , %f)." %(self.node_nr, vec1.x(), vec1.y(), vec2.x(), vec2.y()) LOG.debug("Meep node %i -Now adding the volume source to Meep..." %(self.node_nr)) if isinstance(src, __AmplitudeShapedSource__): ampl = AmplitudeFactor(source = src) Meep.set_AMPL_Callback(ampl.__disown__()) meep_fields.add_volume_source(meepComp, meepSource, meepSrcVol, Meep.AMPL) else: meep_fields.add_volume_source(meepComp, meepSource, meepSrcVol, src.amplitude) else: raise NotImplementedException("Unexpected case in MeepSimulationEngine::__addMeepSource")
def __filter_Path__(self, item): if item.line_width != 0: LOG.debug("Converting path %s into boundary." % item) resultBoundary = Boundary(item.layer, ShapePath(original_shape=item.shape, path_width=abs( item.line_width), path_type=item.path_type), transformation=item.transformation) resultBoundaryList = [resultBoundary] LOG.debug("Result has %i points" % len(resultBoundary.shape.points)) return resultBoundaryList else: LOG.debug( "Path linewidth is zero: PathToBoundaryFilter not applied.") return [item]
def __loadFluxFromHDF5(self, pFluxplane, filename): LOG.debug( "Meep node %i -Loading initial values for fluxplane from HDF5 file %s..." % (self.node_nr, filename)) pFluxplane.load_hdf5(self.meep_fields, filename) return None
def __saveFluxToHDF5(self, pFluxplane, filename): LOG.debug("Meep node %i -Saving flux to HDF5 in file %s ..." % (self.node_nr, filename)) pFluxplane.save_hdf5(self.meep_fields, filename) return None
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) else: #dim == 3 self.material = MeepMaterial3DPolygons(landscape.simulation_volume, self.meepVol) Meep.set_EPS_Callback(self.material.__disown__()) LOG.debug("Meep node %i -Defining structure..." % (self.node_nr)) symmetry_object = Meep.identity() if (self.symmY): LOG.debug("Meep node %i -Using y symmetry!" % (self.node_nr)) symmetry_object = Meep.mirror(Meep.Y, self.meepVol) symmetry_object = symmetry_object * complex(1.0, 0.0) # When there is a certain PML direction, use that one. if isinstance(landscape.pml_direction, str): dirint = 'XYZ'.rfind(str.upper(landscape.pml_direction)) assert dirint <= 0, 'PML direction should be either X, Y or Z' if dirint == 0: direction = Meep.X if dirint == 1: direction = Meep.Y if dirint == 2: direction = Meep.Z pml = Meep.pml(landscape.pml_thickness, direction)
def __filter_default__(self, item): if hasattr(item, "is_empty"): if item.is_empty(): LOG.debug("Emptyfilter is filtering out : %s" % item) return [] return [item]