Ejemplo n.º 1
0
    def is_manhattan(self):
        if self.__class__ == pya.Path:
            pts = self.get_points()
        else:
            pts = self.get_dpoints()
        if len(pts) == 2:
            return True
            
        # check that each segment is horizontal or vertical:
        for i, pt in enumerate(pts[0:-1]):
            if not (pts[i].x == pts[i + 1].x or pts[i].y == pts[i + 1].y):
                return False

        # check that all corners are 90 degrees (not 180):
        from SiEPIC.utils import inner_angle_b_vectors
        for i in range(1, len(pts)-1):
            if ((inner_angle_b_vectors(pts[i]-pts[i-1],pts[i+1]-pts[i])+90)%360-90) != 90:
                return False
        return True
Ejemplo n.º 2
0
    def produce_impl(self):

        from SiEPIC.utils import arc_xy, arc_bezier, angle_vector, angle_b_vectors, inner_angle_b_vectors, translate_from_normal
        from math import cos, sin, pi, sqrt
        import pya
        from SiEPIC.extend import to_itype

        print("GSiP.Wireguide")

        TECHNOLOGY = get_technology_by_name(
            'GSiP') if op_tag == "GUI" else Tech.load_from_xml(
                lyp_filepath).layers
        dbu = self.layout.dbu
        wg_width = to_itype(self.width, dbu)
        path = self.path.to_itype(dbu)

        if not (len(self.layers) == len(self.widths)
                and len(self.layers) == len(self.offsets)
                and len(self.offsets) == len(self.widths)):
            raise Exception(
                "There must be an equal number of layers, widths and offsets")
        path.unique_points()
        turn = 0
        for lr in range(0, len(self.layers)):
            layer = self.layout.layer(TECHNOLOGY[self.layers[lr]])

            width = to_itype(self.widths[lr], dbu)
            offset = to_itype(self.offsets[lr], dbu)

            pts = path.get_points()
            wg_pts = [pts[0]]
            for i in range(1, len(pts) - 1):
                turn = ((angle_b_vectors(pts[i] - pts[i - 1], pts[i + 1] -
                                         pts[i]) + 90) % 360 - 90) / 90
                dis1 = pts[i].distance(pts[i - 1])
                dis2 = pts[i].distance(pts[i + 1])
                angle = angle_vector(pts[i] - pts[i - 1]) / 90
                pt_radius = self.radius
                # determine the radius, based on how much space is available
                if len(pts) == 3:
                    pt_radius = min(dis1, dis2, pt_radius)
                else:
                    if i == 1:
                        if dis1 <= pt_radius:
                            pt_radius = dis1
                    elif dis1 < 2 * pt_radius:
                        pt_radius = dis1 / 2
                    if i == len(pts) - 2:
                        if dis2 <= pt_radius:
                            pt_radius = dis2
                    elif dis2 < 2 * pt_radius:
                        pt_radius = dis2 / 2
                # wireguide bends:
                if (self.adiab):
                    wg_pts += Path(
                        arc_bezier(
                            pt_radius,
                            270,
                            270 + inner_angle_b_vectors(
                                pts[i - 1] - pts[i], pts[i + 1] - pts[i]),
                            self.bezier,
                            DevRec='DevRec' in self.layers[lr]),
                        0).transformed(Trans(angle, turn < 0,
                                             pts[i])).get_points()
                else:
                    wg_pts += Path(
                        arc_xy(-pt_radius,
                               pt_radius,
                               pt_radius,
                               270,
                               270 + inner_angle_b_vectors(
                                   pts[i - 1] - pts[i], pts[i + 1] - pts[i]),
                               DevRec='DevRec' in self.layers[lr]),
                        0).transformed(Trans(angle, turn < 0,
                                             pts[i])).get_points()
            wg_pts += [pts[-1]]
            wg_pts = pya.Path(wg_pts, 0).unique_points().get_points()
            wg_polygon = Path(wg_pts, wg_width)
            self.cell.shapes(layer).insert(wg_polygon)  # insert the wireguide

            #if self.layout.layer(TECHNOLOGY['Wireguide']) == layer:
            waveguide_length = wg_polygon.area() / self.width * dbu**2

        pts = path.get_points()
        LayerPinRecN = self.layout.layer(TECHNOLOGY['PinRecM'])

        # insert pins to wireguide
        t1 = Trans(angle_vector(pts[0] - pts[1]) / 90, False, pts[0])
        self.cell.shapes(LayerPinRecN).insert(
            Path([Point(-50, 0), Point(50, 0)], wg_width).transformed(t1))
        self.cell.shapes(LayerPinRecN).insert(Text("pin1", t1, 0.3 / dbu, -1))

        t = Trans(angle_vector(pts[-1] - pts[-2]) / 90, False, pts[-1])
        self.cell.shapes(LayerPinRecN).insert(
            Path([Point(-50, 0), Point(50, 0)], wg_width).transformed(t))
        self.cell.shapes(LayerPinRecN).insert(Text("pin2", t, 0.3 / dbu, -1))

        LayerDevRecN = self.layout.layer(TECHNOLOGY['DevRec'])

        # Compact model information
        angle_vec = angle_vector(pts[0] - pts[1]) / 90
        halign = 0  # left
        angle = 0
        pt2 = pts[0]
        pt3 = pts[0]
        if angle_vec == 0:  # horizontal
            halign = 2  # right
            angle = 0
            pt2 = pts[0] + Point(0, wg_width)
            pt3 = pts[0] + Point(0, -wg_width)
        if angle_vec == 2:  # horizontal
            halign = 0  # left
            angle = 0
            pt2 = pts[0] + Point(0, wg_width)
            pt3 = pts[0] + Point(0, -wg_width)
        if angle_vec == 1:  # vertical
            halign = 2  # right
            angle = 1
            pt2 = pts[0] + Point(wg_width, 0)
            pt3 = pts[0] + Point(-wg_width, 0)
        if angle_vec == -1:  # vertical
            halign = 0  # left
            angle = 1
            pt2 = pts[0] + Point(wg_width, 0)
            pt3 = pts[0] + Point(-wg_width, 0)
Ejemplo n.º 3
0
def layout_waveguide2(TECHNOLOGY, layout, cell, layers, widths, offsets, pts, radius, adiab, bezier):
  '''
    Create a waveguide, in a specific technology
    inputs
    - TECHNOLOGY, layout, cell:
        from SiEPIC.utils import get_layout_variables
        TECHNOLOGY, lv, layout, cell = get_layout_variables()
    - layers: list of text names, e.g., ['Waveguide']
    - widths: list of floats in units Microns, e.g., [0.50]
    - offsets: list of floats in units Microns, e.g., [0]
    - pts: a list of pya.Points, e.g. 
        L=15/dbu
        pts = [Point(0,0), Point(L,0), Point(L,L)]
    - radius: in Microns, e.g., 5
    - adiab: 1 = Bezier curve, 0 = radial bend (arc)
    - bezier: the bezier parameter, between 0 and 0.45 (almost a radial bend)

    Note: bezier parameters need to be simulated and optimized, and will depend on 
        wavelength, polarization, width, etc.  TM and rib waveguides don't benefit from bezier curves
        most useful for TE 
  '''
  from SiEPIC.utils import arc_xy, arc_bezier, angle_vector, angle_b_vectors, inner_angle_b_vectors, translate_from_normal
  from SiEPIC.extend import to_itype
  from pya import Path, Polygon, Trans
  dbu = layout.dbu

  width=widths[0]
  turn=0
  waveguide_length = 0
  for lr in range(0, len(layers)):
    wg_pts = [pts[0]]
    layer = layout.layer(TECHNOLOGY[layers[lr]])
    width = to_itype(widths[lr],dbu)
    offset = to_itype(offsets[lr],dbu)
    for i in range(1,len(pts)-1):
      turn = ((angle_b_vectors(pts[i]-pts[i-1],pts[i+1]-pts[i])+90)%360-90)/90
      dis1 = pts[i].distance(pts[i-1])
      dis2 = pts[i].distance(pts[i+1])
      angle = angle_vector(pts[i]-pts[i-1])/90
      pt_radius = to_itype(radius,dbu)
      # determine the radius, based on how much space is available
      if len(pts)==3:
        pt_radius = min (dis1, dis2, pt_radius)
      else:
        if i==1:
          if dis1 <= pt_radius:
            pt_radius = dis1
        elif dis1 < 2*pt_radius:
          pt_radius = dis1/2
        if i==len(pts)-2:
          if dis2 <= pt_radius:
            pt_radius = dis2
        elif dis2 < 2*pt_radius:
          pt_radius = dis2/2
      # waveguide bends:
      if abs(turn)==1:
        if(adiab):
          wg_pts += Path(arc_bezier(pt_radius, 270, 270 + inner_angle_b_vectors(pts[i-1]-pts[i], pts[i+1]-pts[i]), bezier, DevRec='DevRec' in layers[lr]), 0).transformed(Trans(angle, turn < 0, pts[i])).get_points()
        else:
          wg_pts += Path(arc_xy(-pt_radius, pt_radius, pt_radius, 270, 270 + inner_angle_b_vectors(pts[i-1]-pts[i], pts[i+1]-pts[i]),DevRec='DevRec' in layers[lr]), 0).transformed(Trans(angle, turn < 0, pts[i])).get_points()
        
    wg_pts += [pts[-1]]
    wg_pts = pya.Path(wg_pts, 0).unique_points().get_points()
    wg_polygon = Polygon(translate_from_normal(wg_pts, width/2 + (offset if turn > 0 else - offset))+translate_from_normal(wg_pts, -width/2 + (offset if turn > 0 else - offset))[::-1])
    cell.shapes(layer).insert(wg_polygon)
  
    if layout.layer(TECHNOLOGY['Waveguide']) == layer:
      waveguide_length = wg_polygon.area() / width * dbu
  return waveguide_length
Ejemplo n.º 4
0
def layout_waveguide2(TECHNOLOGY, layout, cell, layers, widths, offsets, pts,
                      radius, adiab, bezier):
    from SiEPIC.utils import arc_xy, arc_bezier, angle_vector, angle_b_vectors, inner_angle_b_vectors, translate_from_normal
    from SiEPIC.extend import to_itype
    from pya import Path, Polygon, Trans
    dbu = layout.dbu

    width = widths[0]
    turn = 0
    waveguide_length = 0
    for lr in range(0, len(layers)):
        wg_pts = [pts[0]]
        layer = layout.layer(TECHNOLOGY[layers[lr]])
        width = to_itype(widths[lr], dbu)
        offset = to_itype(offsets[lr], dbu)
        for i in range(1, len(pts) - 1):
            turn = (
                (angle_b_vectors(pts[i] - pts[i - 1], pts[i + 1] - pts[i]) +
                 90) % 360 - 90) / 90
            dis1 = pts[i].distance(pts[i - 1])
            dis2 = pts[i].distance(pts[i + 1])
            angle = angle_vector(pts[i] - pts[i - 1]) / 90
            pt_radius = to_itype(radius, dbu)
            # determine the radius, based on how much space is available
            if len(pts) == 3:
                pt_radius = min(dis1, dis2, pt_radius)
            else:
                if i == 1:
                    if dis1 <= pt_radius:
                        pt_radius = dis1
                elif dis1 < 2 * pt_radius:
                    pt_radius = dis1 / 2
                if i == len(pts) - 2:
                    if dis2 <= pt_radius:
                        pt_radius = dis2
                elif dis2 < 2 * pt_radius:
                    pt_radius = dis2 / 2
            # waveguide bends:
            if abs(turn) == 1:
                if (adiab):
                    wg_pts += Path(
                        arc_bezier(
                            pt_radius,
                            270,
                            270 + inner_angle_b_vectors(
                                pts[i - 1] - pts[i], pts[i + 1] - pts[i]),
                            float(bezier),
                            DevRec='DevRec' in layers[lr]),
                        0).transformed(Trans(angle, turn < 0,
                                             pts[i])).get_points()
                else:
                    wg_pts += Path(
                        arc_xy(-pt_radius,
                               pt_radius,
                               pt_radius,
                               270,
                               270 + inner_angle_b_vectors(
                                   pts[i - 1] - pts[i], pts[i + 1] - pts[i]),
                               DevRec='DevRec' in layers[lr]),
                        0).transformed(Trans(angle, turn < 0,
                                             pts[i])).get_points()

        wg_pts += [pts[-1]]
        wg_pts = pya.Path(wg_pts, 0).unique_points().get_points()
        wg_polygon = Polygon(
            translate_from_normal(
                wg_pts, width / 2 + (offset if turn > 0 else -offset)) +
            translate_from_normal(
                wg_pts, -width / 2 + (offset if turn > 0 else -offset))[::-1])
        cell.shapes(layer).insert(wg_polygon)

        if layout.layer(TECHNOLOGY['Waveguide']) == layer:
            waveguide_length = wg_polygon.area() / width * dbu
    return waveguide_length
Ejemplo n.º 5
0
def layout_waveguide2(TECHNOLOGY, layout, cell, layers, widths, offsets, pts,
                      radius, adiab, bezier):
    from SiEPIC.utils import arc_xy, arc_bezier, angle_vector, angle_b_vectors, inner_angle_b_vectors, translate_from_normal
    from SiEPIC.extend import to_itype
    from pya import Path, Polygon, Trans
    dbu = layout.dbu

    if 'Errors' in TECHNOLOGY:
        error_layer = layout.layer(TECHNOLOGY['Errors'])
    else:
        error_layer = None

    width = widths[0]
    turn = 0
    waveguide_length = 0
    for lr in range(0, len(layers)):
        wg_pts = [pts[0]]
        layer = layout.layer(TECHNOLOGY[layers[lr]])
        width = to_itype(widths[lr], dbu)
        offset = to_itype(offsets[lr], dbu)
        for i in range(1, len(pts) - 1):
            turn = (
                (angle_b_vectors(pts[i] - pts[i - 1], pts[i + 1] - pts[i]) +
                 90) % 360 - 90) / 90
            dis1 = pts[i].distance(pts[i - 1])
            dis2 = pts[i].distance(pts[i + 1])
            angle = angle_vector(pts[i] - pts[i - 1]) / 90
            pt_radius = to_itype(radius, dbu)
            error_seg1 = False
            error_seg2 = False
            # determine the radius, based on how much space is available
            if len(pts) == 3:
                # simple corner, limit radius by the two edges
                if dis1 < pt_radius:
                    error_seg1 = True
                if dis2 < pt_radius:
                    error_seg2 = True
                pt_radius = min(dis1, dis2, pt_radius)
            else:
                if i == 1:
                    # first corner, limit radius by first edge, or 1/2 of second one
                    if dis1 < pt_radius:
                        error_seg1 = True
                    if dis2 / 2 < pt_radius:
                        error_seg2 = True
                    pt_radius = min(dis1, dis2 / 2, pt_radius)
                elif i == len(pts) - 2:
                    # last corner, limit radius by second edge, or 1/2 of first one
                    if dis1 / 2 < pt_radius:
                        error_seg1 = True
                    if dis2 < pt_radius:
                        error_seg2 = True
                    pt_radius = min(dis1 / 2, dis2, pt_radius)
                else:
                    if dis1 / 2 < pt_radius:
                        error_seg1 = True
                    if dis2 / 2 < pt_radius:
                        error_seg2 = True
                    pt_radius = min(dis1 / 2, dis2 / 2, pt_radius)

            if error_seg1 or error_seg2:
                if not error_layer:
                    # we have an error, but no Error layer
                    print('- SiEPIC:layout_waveguide2: missing Error layer')
                # and pt_radius < to_itype(radius,dbu):
                elif layer == layout.layer(TECHNOLOGY['Waveguide']):
                    # add an error polygon to flag the incorrect bend
                    if error_seg1:
                        error_pts = pya.Path([pts[i - 1], pts[i]], width)
                        cell.shapes(error_layer).insert(error_pts)
                    if error_seg2:
                        error_pts = pya.Path([pts[i], pts[i + 1]], width)
                        cell.shapes(error_layer).insert(error_pts)
    #                error_pts = pya.Path([pts[i-1], pts[i], pts[i+1]], width)
    #                cell.shapes(error_layer).insert(error_pts)
    # waveguide bends:
            if abs(turn) == 1:
                if (adiab):
                    wg_pts += Path(
                        arc_bezier(
                            pt_radius,
                            270,
                            270 + inner_angle_b_vectors(
                                pts[i - 1] - pts[i], pts[i + 1] - pts[i]),
                            float(bezier),
                            DevRec='DevRec' in layers[lr]),
                        0).transformed(Trans(angle, turn < 0,
                                             pts[i])).get_points()
                else:
                    wg_pts += Path(
                        arc_xy(-pt_radius,
                               pt_radius,
                               pt_radius,
                               270,
                               270 + inner_angle_b_vectors(
                                   pts[i - 1] - pts[i], pts[i + 1] - pts[i]),
                               DevRec='DevRec' in layers[lr]),
                        0).transformed(Trans(angle, turn < 0,
                                             pts[i])).get_points()

        wg_pts += [pts[-1]]
        wg_pts = pya.Path(wg_pts, 0).unique_points().get_points()
        wg_polygon = Polygon(
            translate_from_normal(
                wg_pts, width / 2 + (offset if turn > 0 else -offset)) +
            translate_from_normal(
                wg_pts, -width / 2 + (offset if turn > 0 else -offset))[::-1])
        cell.shapes(layer).insert(wg_polygon)

        if layout.layer(TECHNOLOGY['Waveguide']) == layer:
            waveguide_length = wg_polygon.area() / width * dbu

    return waveguide_length