Ejemplo n.º 1
0
 def collect_Boundary(self, item, additional_transform=None, **kwargs):
     shape = item.shape.transform_copy(item.transformation +
                                       additional_transform)
     shape.snap_to_grid(self.grids_per_unit)
     shape.remove_identicals()
     coordinates = shape
     # BOUNDARIES
     if len(shape) < 3:
         LOG.warning(
             "BOUNDARY with fewer than 3 coordinates not allowed in structure %s"
             % self.__current_structure__.name)
         return
     if len(shape) > TECH.GDSII.MAX_VERTEX_COUNT:
         LOG.warning("BOUNDARY with more than " +
                     str(TECH.GDSII.MAX_VERTEX_COUNT) +
                     " coordinates not supported in structure " +
                     self.__current_structure__.name)
     # shape must be closed!
     if not (coordinates[0] == coordinates[-1]):
         coordinates.append(coordinates[0])
     self.collect_boundary_element(layer=item.layer,
                                   coordinates=coordinates)
     return
Ejemplo n.º 2
0
 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))
Ejemplo n.º 3
0
 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")
Ejemplo n.º 4
0
 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]
Ejemplo n.º 5
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)
Ejemplo n.º 6
0
    def define_points(self, pts):
        sa = self.angle_start * DEG2RAD
        ea = self.angle_end * DEG2RAD
        bae = (ea + pi) % (2 * pi)

        # normalize angles between 0 and 2pi
        sa = (sa) % (2 * pi)
        ea = (ea) % (2 * pi)

        #angle bvetween two points
        connect_angle = angle_rad(self.coord_end, self.coord_start)
        ca_start = (connect_angle - sa) % (2 * pi)
        ca_end = (connect_angle - ea) % (2 * pi)
        #LOG.debug("ca: %f %f %f" %(, connect_angle , ca_start, ca_end))

        #check both positive and negative radii
        valid = False
        signs = [(1, 1), (1, -1), (-1, 1), (-1, -1)]
        for s in signs:
            radius_start = abs(self.radius_start) * s[0]
            radius_end = abs(self.radius_end) * s[1]

            # Centers of circles through the points.
            c_start = (self.coord_start[0] + radius_start * sin(sa),
                       self.coord_start[1] - radius_start * cos(sa))
            c_end = (self.coord_end[0] + radius_end * sin(ea),
                     self.coord_end[1] - radius_end * cos(ea))

            #distance between centers
            dm = distance(c_start, c_end)
            if abs(radius_start - radius_end) > dm:
                # no valid solution possible
                continue

            # unit vector between circle centers
            mm = ((c_end[0] - c_start[0]) / dm, (c_end[1] - c_start[1]) / dm)
            # angle between normal to connector line and circle centers
            alpha = -acos((radius_start - radius_end) / dm)

            # unit vector from m to p.
            mp = (mm[0] * cos(alpha) + mm[1] * sin(alpha),
                  -mm[0] * sin(alpha) + mm[1] * cos(alpha))

            # Point at first circle.
            p0 = (c_start[0] + radius_start * mp[0],
                  c_start[1] + radius_start * mp[1])
            # Point at second circle.
            p1 = (c_end[0] + radius_end * mp[0], c_end[1] + radius_end * mp[1])

            #LOG.debug("p0, p1:" %( p0, p1))

            forward_angle = angle_rad(p1, p0) % (2 * pi)
            backward_angle = angle_rad(p0, p1) % (2 * pi)

            forward_turn = (forward_angle - sa + pi) % (2 * pi) - pi
            backward_turn = (backward_angle - bae + pi) % (2 * pi) - pi

            # LOG.debug("F: %f B:%f %f %f" % (s[0],  s[1], forward_turn, backward_turn))

            if (forward_turn * s[0] <= 0) and (backward_turn * s[1] >= 0):
                valid = True
                break

        if not valid:
            LOG.error("Can't connect two points with arc_line_arc")
            raise SystemExit

        #LOG.debug("angles: %f %f %f %f" %( angle_start, straight_angle*180/pi, angle_end, backward_angle*180/pi))
        if forward_turn == 0.0:
            pts += [self.coord_start]
        else:
            pts += ShapeBendRelative(self.coord_start,
                                     abs(radius_start),
                                     sa * RAD2DEG,
                                     forward_turn * RAD2DEG,
                                     angle_step=self.angle_step)

        if backward_turn == 0.0:
            pts += [self.coord_end]
        else:
            bend2 = ShapeBendRelative(self.coord_end,
                                      abs(radius_end),
                                      bae * RAD2DEG,
                                      backward_turn * RAD2DEG,
                                      angle_step=self.angle_step)
            bend2.reverse()
            pts += bend2

        return pts
Ejemplo n.º 7
0
 def __str_structure_header__(self, item):
     LOG.info("STRUCTURE: " + item.name)
     return self.__str_object__(item)
Ejemplo n.º 8
0
 def __scaleFluxplane(self, pFluxplane, pScalefactor):
     LOG.info("Scaling fluxplane with factor %f ...." % pScalefactor)
     pFluxplane.scale_dfts(pScalefactor)
     return None
Ejemplo n.º 9
0
 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
Ejemplo n.º 10
0
 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
Ejemplo n.º 11
0
 def __warn__(self, key):
     LOG.error(
         "Warning during export : no corresponding GDSII layer found for process %s and purpose %s"
         % (key.process, key.purpose))
Ejemplo n.º 12
0
 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]
Ejemplo n.º 13
0
    def initialize(self):

        ## standard gratings 1550nm
        def STANDARD_GRATING_1550_TE():
            from picazzo.fibcoup.uniform import UniformLineGrating as _ULG
            from ipkiss.plugins.photonics.wg.basic import WgElDefinition
            std1550_grating_trench = 0.315
            std1550_grating_period = 0.630
            std1550_grating_n_o_periods = 25
            std_lin_grating_wg_def = WgElDefinition(wg_width=10.0)
            G = _ULG(name="std_grating_1550",
                     origin=(0.0, 0.0),
                     period=std1550_grating_period,
                     line_width=std1550_grating_trench,
                     n_o_periods=std1550_grating_n_o_periods,
                     wg_definition=std_lin_grating_wg_def,
                     process=TECH.PROCESS.FC)
            return G

        ## standard gratings 1550nm TM polarization
        def STANDARD_GRATING_1550_TM():
            from picazzo.fibcoup.uniform import UniformLineGrating as _ULG
            from ipkiss.plugins.photonics.wg.basic import WgElDefinition
            std1550_grating_trench = 0.540
            std1550_grating_period = 1.080
            std1550_grating_n_o_periods = 16
            std_lin_grating_wg_def = WgElDefinition(wg_width=10.0)
            G = _ULG(name="std_grating_1550_tm",
                     origin=(0.0, 0.0),
                     period=std1550_grating_period,
                     line_width=std1550_grating_trench,
                     n_o_periods=std1550_grating_n_o_periods,
                     wg_definition=std_lin_grating_wg_def,
                     process=TECH.PROCESS.FC)
            return G

        def STANDARD_2DGRATING_1550_TE():
            from picazzo.fibcoup.uniform_2d import SymmetricUniformRect2dGrating as _UG2D
            from ipkiss.plugins.photonics.wg.basic import WgElDefinition
            std1550_2dgrating_period = 0.605
            std1550_2dgrating_hole_diameter = 0.390  # desired after litho: 370
            std1550_2dgrating_n_o_periods = 19
            std1550_2dgrating_wg_def = WgElDefinition(wg_width=12.0)
            std1550_2dgrating_wg_length = 11  # length of trench before the taper starts
            std1550_2dgrating_trench_overlap = 4  # length of overlap between taper and fiber coupler trench
            std1550_2dgrating_dev_angle = 3.1  # angle deviation w/respect to 90 degrees.
            G = _UG2D(name="std_2dgrating_1550",
                      period=std1550_2dgrating_period,
                      hole_diameter=std1550_2dgrating_hole_diameter,
                      n_o_periods=std1550_2dgrating_n_o_periods,
                      wg_definition=std1550_2dgrating_wg_def,
                      wg_length=std1550_2dgrating_wg_length,
                      dev_angle=std1550_2dgrating_dev_angle,
                      process=TECH.PROCESS.WG)
            return G

        self.DEFAULT_GRATING_TE = STANDARD_GRATING_1550_TE()
        self.DEFAULT_GRATING_TM = STANDARD_GRATING_1550_TM()
        self.DEFAULT_GRATING = self.DEFAULT_GRATING_TE

        try:
            self.DEFAULT_2D_GRATING = STANDARD_2DGRATING_1550_TE()
        except Exception, exc:
            LOG.warn("TECH.IO.FIBCOUP.DEFAULT_2D_GRATING will not be set : " +
                     str(exc))
Ejemplo n.º 14
0
    def define_points(self, pts):

        (s, R, A) = self.__original_shape_without_straight_angles__()

        if len(R) != len(s):
            raise AttributeError(
                "ShapeRoundAdiabaticSplineGeneric: length of radius vector should be identical to that of points in shape"
            )
        if len(A) != len(s):
            raise AttributeError(
                "ShapeRoundAdiabaticSplineGeneric: length of adiabatic_angles vector should be identical to that of points in shape"
            )

        if len(s) < 3:
            self.__points__ = s.points
            return
        margin = 0.5 / get_grids_per_unit()

        S = []

        if not self.original_shape.closed:
            S.append(numpy.array([s.points[0]]))
        L1 = 0.0

        for i in range(1, len(s) - 1):
            sh = AdiabaticSplineCircleSplineShape(start_point=s[i - 1],
                                                  turn_point=s[i],
                                                  end_point=s[i + 1],
                                                  radius=R[i],
                                                  adiabatic_angles=A[i],
                                                  angle_step=self.angle_step)
            L0 = sh[0].distance(s[i])
            if L0 + L1 - margin > s[i - 1].distance(s[i]):
                LOG.warning(
                    "Insufficient space for spline rounding in (%f, %f)" %
                    (s[i].x, s[i].y))
            L1 = sh[-1].distance(s[i])
            S.append(sh.points)

        if self.original_shape.closed:
            sh = AdiabaticSplineCircleSplineShape(start_point=s[-2],
                                                  turn_point=s[-1],
                                                  end_point=s[0],
                                                  radius=R[-1],
                                                  adiabatic_angles=A[-1],
                                                  angle_step=self.angle_step)
            L0 = sh[0].distance(s[-1])
            if L0 + L1 - margin > s[-2].distance(s[-1]):
                LOG.warning(
                    "Insufficient space for spline rounding in (%f, %f)" %
                    (s[-1].x, s[-1].y))
            L1 = sh[-1].distance(s[-1])
            S.append(sh.points)
            sh = AdiabaticSplineCircleSplineShape(start_point=s[-1],
                                                  turn_point=s[0],
                                                  end_point=s[1],
                                                  radius=R[0],
                                                  adiabatic_angles=A[0],
                                                  angle_step=self.angle_step)
            L0 = sh[0].distance(s[0])
            if L0 + L1 - margin > s[-1].distance(s[0]):
                LOG.warning(
                    "Insufficient space for spline rounding in (%f, %f)" %
                    (s[0].x, s[0].y))
            L1 = sh[-1].distance(s[0])
            S.append(sh.points)
            self.__closed__ = True
        else:
            # open curve
            S.append(numpy.array([s.points[-1]]))
            L0 = 0.0
            if L0 + L1 - margin > s[-2].distance(s[-1]):
                LOG.warning(
                    "Insufficient space for spline rounding in (%f, %f)" %
                    (s[-1].x, s[-1].y))
            L1 = sh[-1].distance(s[0])
            self.__closed__ = False
        return numpy.vstack(S)
Ejemplo n.º 15
0
        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)
Ejemplo n.º 16
0
    def define_points(self, pts):
        c = Shape(self.original_shape)
        if len(c) == 0:
            return

        if self.original_shape.is_closed():
            if not c[0] == c[-1]:
                c.append(c[0])
            #closed curve
            c.append(c[1])
        else:
            # open curve
            pts.append(c[0])

        c.remove_identicals()

        min_sw = self.stub_width
        for i in range(1, len(c) - 1):
            angle1 = angle_rad(c[i], c[i - 1])
            angle2 = angle_rad(c[i + 1], c[i])
            turn = (angle2 - angle1 + pi) % (2 * pi) - pi
            if turn == 0 or (abs(turn) <=
                             (pi / 2.0) and self.only_sharp_angles):
                pts.append(c[i])
            elif abs(turn == pi):
                LOG.error("Cannot stub shape with a 180 degree turn")
            else:
                d1 = distance(c[i], c[i - 1])
                d2 = distance(c[i + 1], c[i])
                L = self.stub_width * sin(turn / 2.0) / sin(turn)
                max_L = max([d1 / 2.0, d2 / 2.0])
                if L > max_L:
                    L = max_L
                    sw = L * sin(turn) / sin(turn / 2.0)
                else:
                    sw = self.stub_width
                if sw < min_sw:
                    min_sw = sw

                theta_div2 = (pi - angle1 + angle2) % (2 * pi) / 2.0

                s1 = Coord2(c[i][0] - L * cos(angle1),
                            c[i][1] - L * sin(angle1))
                s2 = (c[i][0] + L * cos(angle2), c[i][1] + L * sin(angle2))

                B = -self.stub_height * sign(turn)
                delta = 0.5 * (self.stub_width - self.tip_width)
                s2 = (s1[0] + B * cos(angle1 + theta_div2) +
                      delta * cos(angle1 + theta_div2 - pi / 2.0),
                      s1[1] + B * sin(angle1 + theta_div2) +
                      delta * sin(angle1 + theta_div2 - pi / 2.0))
                s4 = Coord2(c[i][0] + L * cos(angle2),
                            c[i][1] + L * sin(angle2))
                s3 = (s4[0] + B * cos(angle2 + pi - theta_div2) +
                      delta * cos(angle2 + pi - theta_div2 + pi / 2.0),
                      s4[1] + B * sin(angle2 + pi - theta_div2) +
                      delta * sin(angle2 + pi - theta_div2 + pi / 2.0))
                pts.append(s1)
                pts.append(s2)
                pts.append(s3)
                pts.append(s4)

        if not self.original_shape.closed:
            # open curve
            pts.append(c[-1])

        if min_sw < self.stub_width:
            LOG.warning("Stub width is reduced from " + str(self.stub_width) +
                        " to " + str(min_sw) + "to stub shape.")

        return pts
Ejemplo n.º 17
0
 def __warn__(self, key):
     from ipkiss.log import IPKISS_LOG as LOG
     LOG.error(
         "Warning during GDSII import : no corresponding process/purpose layer found for number = %i and datatype = %s"
         % (key.number, key.datatype))