コード例 #1
0
    def translate_from_center(self, offset):
        from math import pi, cos, sin, acos, sqrt
        from .utils import angle_vector
        pts = [pt for pt in self.get_dpoints()]
        tpts = [pt for pt in self.get_dpoints()]
        for i in range(0, len(pts)):
            if i == 0:
                u = pts[i] - pts[i + 1]
                v = -u
            elif i == (len(pts) - 1):
                u = pts[i - 1] - pts[i]
                v = -u
            else:
                u = pts[i - 1] - pts[i]
                v = pts[i + 1] - pts[i]

            if offset < 0:
                o1 = pya.DPoint(abs(offset) * cos(angle_vector(u) * pi / 180 - pi / 2),
                                abs(offset) * sin(angle_vector(u) * pi / 180 - pi / 2))
                o2 = pya.DPoint(abs(offset) * cos(angle_vector(v) * pi / 180 + pi / 2),
                                abs(offset) * sin(angle_vector(v) * pi / 180 + pi / 2))
            else:
                o1 = pya.DPoint(abs(offset) * cos(angle_vector(u) * pi / 180 + pi / 2),
                                abs(offset) * sin(angle_vector(u) * pi / 180 + pi / 2))
                o2 = pya.DPoint(abs(offset) * cos(angle_vector(v) * pi / 180 - pi / 2),
                                abs(offset) * sin(angle_vector(v) * pi / 180 - pi / 2))

            p1 = u + o1
            p2 = o1
            p3 = v + o2
            p4 = o2
            d = (p1.x - p2.x) * (p3.y - p4.y) - (p1.y - p2.y) * (p3.x - p4.x)

            if round(d, 10) == 0:
                tpts[i] += p2
            else:
                tpts[i] += pya.DPoint(((p1.x * p2.y - p1.y * p2.x) * (p3.x - p4.x) - (p1.x - p2.x) * (p3.x * p4.y - p3.y * p4.x)) / d,
                                     ((p1.x * p2.y - p1.y * p2.x) * (p3.y - p4.y) - (p1.y - p2.y) * (p3.x * p4.y - p3.y * p4.x)) / d)

        if self.__class__ == pya.Path:
            return pya.Path([pya.Point(pt.x, pt.y) for pt in tpts], self.width)
        elif self.__class__ == pya.DPath:
            return pya.DPath(tpts, self.width)
コード例 #2
0
    def remove_colinear_points(self, verbose=False):
        """ remove all but 1 colinear point """
        from SiEPIC.utils import pt_intersects_segment, angle_b_vectors, angle_vector
        if self.__class__ == pya.Path:
            pts = self.get_points()
        else:
            pts = self.get_dpoints()

        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
            angle = angle_vector(pts[i]-pts[i-1])/90
            if verbose:
                print('%s, %s' %(turn, angle))

        # this version removed all colinear points, which doesn't make sense for a path
        self.points = [pts[0]] + [pts[i]
                                for i in range(1, len(pts) - 1) if not pt_intersects_segment(pts[i + 1], pts[i - 1], pts[i])] + [pts[-1]]
        return self
コード例 #3
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)
コード例 #4
0
    def produce_impl(self):

        from SiEPIC.utils.layout import layout_waveguide2
        from SiEPIC.utils import angle_vector
        from math import cos, sin, pi, sqrt
        import pya
        from SiEPIC.extend import to_itype

        # print("GSiP.Waveguide")

        from SiEPIC.utils import get_technology_by_name
        TECHNOLOGY = get_technology_by_name('GSiP')

        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()
        pts = path.get_points()

        # Draw the waveguide geometry, new in SiEPIC-Tools v0.3.64
        waveguide_length = layout_waveguide2(TECHNOLOGY, self.layout,
                                             self.cell, self.layers,
                                             self.widths, self.offsets, pts,
                                             self.radius, self.adiab,
                                             self.bezier)

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

        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
        if angle_vec == 0:  # horizontal
            halign = 2  # right
            angle = 0
            dpt = Point(0, 0.2 * wg_width)
        if angle_vec == 2:  # horizontal
            halign = 0  # left
            angle = 0
            dpt = Point(0, 0.2 * wg_width)
        if angle_vec == 1:  # vertical
            halign = 2  # right
            angle = 1
            dpt = Point(0.2 * wg_width, 0)
        if angle_vec == -1:  # vertical
            halign = 0  # left
            angle = 1
            dpt = Point(0.2 * wg_width, 0)
        pt2 = pts[0] + dpt
        pt3 = pts[0] - dpt
        pt4 = pts[0] - 2 * dpt
        pt5 = pts[0] + 2 * dpt

        t = Trans(angle, False, pt5)
        text = Text('cellName=%s' % self.cellName, t, 0.1 * wg_width, -1)
        text.halign = halign
        shape = self.cell.shapes(LayerDevRecN).insert(text)
        t = Trans(angle, False, pt3)
        text = Text('Lumerical_INTERCONNECT_library=Design kits/%s' % self.CML,
                    t, 0.1 * wg_width, -1)
        text.halign = halign
        shape = self.cell.shapes(LayerDevRecN).insert(text)
        t = Trans(angle, False, pt2)
        text = Text('Component=%s' % self.model, t, 0.1 * wg_width, -1)
        text.halign = halign
        shape = self.cell.shapes(LayerDevRecN).insert(text)
        t = Trans(angle, False, pts[0])
        pts_txt = str(
            [[round(p.to_dtype(dbu).x, 3),
              round(p.to_dtype(dbu).y, 3)] for p in pts]).replace(', ', ',')
        text = Text ( \
          'Spice_param:wg_length=%.3fu wg_width=%.3fu points="%s" radius=%s' %\
            (waveguide_length, self.width, pts_txt,self.radius ), t, 0.1*wg_width, -1  )
        text.halign = halign
        shape = self.cell.shapes(LayerDevRecN).insert(text)
        t = Trans(angle, False, pt4)
        text = Text ( \
          'Length=%.3fu' %(waveguide_length), t, 0.5*wg_width, -1  )
        text.halign = halign
        shape = self.cell.shapes(LayerDevRecN).insert(text)
コード例 #5
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
コード例 #6
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
コード例 #7
0
ファイル: geometry.py プロジェクト: seanlam97/SiEPIC-Tools
def translate_from_normal2(pts, trans, trans2=None):
    '''
    Translate each point in the array pts, by its local normal by a distance that 
     varies linearly starting at 'trans' and ending 'trans2' 
    Useful for making an S-bend with different waveguide widths at the ends
    
    Author: Lukas Chrostowski
    
    Inputs:
     pts: DPoint array, length at least 3
     trans: float
     trans2: float
     
    Output:
     tpts: DPoint array
     
    Example, SBend Waveguide with variable width:
    
    from SiEPIC.utils.geometry import bezier_parallel
    
    w1 = 0.15 # input waveguide width
    wo = 0.35 # output waveguide width
    l = 5     # horizontal length
    offset = 2# vertical offset
    
    p = bezier_parallel(DPoint(0,0), DPoint(l,offset), 0)
    pt1 = translate_from_normal2(p,w1/2,wo/2)
    pt2 = translate_from_normal2(p,-w1/2, -wo/2)
    pt = pt1+pt2[::-1]
    
    from SiEPIC.utils import get_layout_variables
    TECHNOLOGY, lv, ly, cell = get_layout_variables()
    layer = cell.layout().layer(TECHNOLOGY['Waveguide'])
    poly = pya.DPolygon(pt)
    cell.shapes(layer).insert(poly)
    '''

    if trans2 == None:
        trans2 = trans
    if len(pts) < 2:
        return pts

    length = 0  # total length
    for i in range(1, len(pts) - 1):
        length += (pts[i + 1] - pts[i - 1]).length()

    transv = []  # translation vector, linearly varying along the length
    lengthc = 0  # cumulative length
    for i in range(1, len(pts) - 1):
        lengthc += (pts[i + 1] - pts[i - 1]).length()
        transv.append((lengthc / length) * trans2 +
                      (1 - lengthc / length) * trans)

    from math import cos, sin, pi
    from SiEPIC.utils import angle_vector

    d = 1. / (len(pts) - 1)
    a = angle_vector(pts[1] - pts[0]) * pi / 180 + (pi / 2
                                                    if trans > 0 else -pi / 2)
    tpts = [pts[0] + pya.DPoint(abs(trans) * cos(a), abs(trans) * sin(a))]

    for i in range(1, len(pts) - 1):
        dpt = (pts[i + 1] - pts[i - 1]) * (2 / d)
        tpts.append(pts[i] + pya.DPoint(-dpt.y, dpt.x) *
                    (transv[i - 1] / 1 / dpt.abs()))

    a = angle_vector(pts[-1] - pts[-2]) * pi / 180 + (pi / 2 if trans > 0 else
                                                      -pi / 2)
    tpts.append(pts[-1] +
                pya.DPoint(abs(trans2) * cos(a),
                           abs(trans2) * sin(a)))

    # Make ends manhattan
    if abs(tpts[0].x - pts[0].x) > abs(tpts[0].y - pts[0].y):
        tpts[0].y = pts[0].y
    else:
        tpts[0].x = pts[0].x
    if abs(tpts[-1].x - pts[-1].x) > abs(tpts[-1].y - pts[-1].y):
        tpts[-1].y = pts[-1].y
    else:
        tpts[-1].x = pts[-1].x
    return tpts
コード例 #8
0
ファイル: layout.py プロジェクト: seanlam97/SiEPIC-Tools
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
コード例 #9
0
ファイル: layout.py プロジェクト: seanlam97/SiEPIC-Tools
def layout_waveguide3(cell, pts, params, debug=True):

    if debug:
        print('SiEPIC.utils.layout.layout_waveguide3: ')

    layout = cell.layout()
    dbu = layout.dbu
    technology_name = layout.technology_name
    from SiEPIC.utils import get_technology_by_name
    TECHNOLOGY = get_technology_by_name(technology_name)

    from SiEPIC.extend import to_itype
    wg_width = to_itype(params['width'], dbu)
    radius = float(params['radius'])
    model = params['model']
    cellName = 'Waveguide2'
    CML = params['CML']

    if debug:
        print(' - waveguide params: %s' % (params))

    if 'compound_waveguide' in params:
        print('error: this function cannot handle compound waveguides')
        raise Exception(
            'error: this function cannot handle compound waveguides (%s)' %
            waveguide_type)

    # draw the waveguide
    waveguide_length = layout_waveguide2(
        TECHNOLOGY, layout, cell, [wg['layer'] for wg in params['component']],
        [wg['width'] for wg in params['component']],
        [wg['offset'] for wg in params['component']], pts, radius,
        params['adiabatic'], params['bezier'])

    # Draw the marking layers
    from SiEPIC.utils import angle_vector
    LayerPinRecN = layout.layer(TECHNOLOGY['PinRec'])

    make_pin(cell, 'opt1', pts[0], wg_width, LayerPinRecN,
             angle_vector(pts[0] - pts[1]) % 360)
    make_pin(cell, 'opt2', pts[-1], wg_width, LayerPinRecN,
             angle_vector(pts[-1] - pts[-2]) % 360)

    from pya import Trans, Text, Path, Point
    '''
    t1 = Trans(angle_vector(pts[0]-pts[1])/90, False, pts[0])
    cell.shapes(LayerPinRecN).insert(Path([Point(-10, 0), Point(10, 0)], wg_width).transformed(t1))
    cell.shapes(LayerPinRecN).insert(Text("opt1", t1, 0.3/dbu, -1))
    
    t = Trans(angle_vector(pts[-1]-pts[-2])/90, False, pts[-1])
    cell.shapes(LayerPinRecN).insert(Path([Point(-10, 0), Point(10, 0)], wg_width).transformed(t))
    cell.shapes(LayerPinRecN).insert(Text("opt2", t, 0.3/dbu, -1))
    '''

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

    # Compact model information
    angle_vec = angle_vector(pts[0] - pts[1]) / 90
    halign = 0  # left
    angle = 0
    dpt = Point(0, 0)
    if angle_vec == 0:  # horizontal
        halign = 2  # right
        angle = 0
        dpt = Point(0, 0.2 * wg_width)
    if angle_vec == 2:  # horizontal
        halign = 0  # left
        angle = 0
        dpt = Point(0, 0.2 * wg_width)
    if angle_vec == 1:  # vertical
        halign = 2  # right
        angle = 1
        dpt = Point(0.2 * wg_width, 0)
    if angle_vec == -1:  # vertical
        halign = 0  # left
        angle = 1
        dpt = Point(0.2 * wg_width, 0)
    pt2 = pts[0] + dpt
    pt3 = pts[0] - dpt
    pt4 = pts[0] - 6 * dpt
    pt5 = pts[0] + 2 * dpt

    t = Trans(angle, False, pt3)
    text = Text('Lumerical_INTERCONNECT_library=Design kits/%s' % CML, t,
                0.1 * wg_width, -1)
    text.halign = halign
    shape = cell.shapes(LayerDevRecN).insert(text)
    t = Trans(angle, False, pt2)
    text = Text('Component=%s' % model, t, 0.1 * wg_width, -1)
    text.halign = halign
    shape = cell.shapes(LayerDevRecN).insert(text)
    t = Trans(angle, False, pt5)
    text = Text('cellName=%s' % cellName, t, 0.1 * wg_width, -1)
    text.halign = halign
    shape = cell.shapes(LayerDevRecN).insert(text)
    t = Trans(angle, False, pts[0])
    pts_txt = str([[round(p.to_dtype(dbu).x, 3),
                    round(p.to_dtype(dbu).y, 3)]
                   for p in pts]).replace(', ', ',')
    text = Text(
        'Spice_param:wg_length=%.9f wg_width=%.3g points="%s" radius=%.3g' %
        (waveguide_length * 1e-6, wg_width * 1e-9, pts_txt, radius * 1e-6), t,
        0.1 * wg_width, -1)
    text.halign = halign
    shape = cell.shapes(LayerDevRecN).insert(text)
    t = Trans(angle, False, pt4)
    text = Text('Length=%.3f (microns)' % (waveguide_length), t,
                0.5 * wg_width, -1)
    text.halign = halign
    shape = cell.shapes(LayerDevRecN).insert(text)

    return waveguide_length