Esempio n. 1
0
    def produce_impl(self):

        # fetch the parameters
        dbu = self.layout.dbu
        ly = self.layout
        shapes = self.cell.shapes

        LayerSi = self.layer
        LayerSiN = ly.layer(LayerSi)
        LayerPinRecN = ly.layer(self.pinrec)
        LayerDevRecN = ly.layer(self.devrec)

        # Determine the period such that the waveguide length is as desired.  Slight adjustment to period
        N_boxes = int(round(self.length / self.target_period - 0.5))
        grating_period = self.length / (N_boxes) / dbu

        # Draw the Bragg grating:
        box_width = int(round(grating_period * self.duty))

        w = self.swg_wg_width / dbu
        half_w = w / 2
        for i in range(0, N_boxes + 1):
            x = int(round((i * grating_period - box_width / 2)))
            box1 = Box(x, -half_w, x + box_width, half_w)
            shapes(LayerSiN).insert(box1)
        length = self.length / dbu

        # Strip waveguide:
        w_strip = self.strip_wg_width / dbu
        if w_strip > 0:
            box1 = Box(0, -w_strip / 2, length, w_strip / 2)
            shapes(LayerSiN).insert(box1)

        # Create the device recognition layer
        points = [pya.Point(0, 0), pya.Point(length, 0)]
        path = pya.Path(points, w)
        path = pya.Path(points, w * 3)
        shapes(LayerDevRecN).insert(path.simple_polygon())

        # Pins on the waveguide:
        from SiEPIC._globals import PIN_LENGTH as pin_length
        make_pin(self.cell, "opt1", [0, 0], w, pin_length, LayerPinRecN)
        make_pin(self.cell, "opt2", [length, 0], w, -pin_length, LayerPinRecN)

        # Compact model information
        t = Trans(Trans.R0, 0, -w * 1.5 + 0.1 / dbu)
        text = Text('Lumerical_INTERCONNECT_library=Design kits/ebeam', t)
        shape = shapes(LayerDevRecN).insert(text)
        shape.text_size = 0.1 / dbu
        t = Trans(Trans.R0, 0, -w * 1.5 + 0.2 / dbu)
        text = Text('Component=NO_MODEL_AVAILABLE', t)
        shape = shapes(LayerDevRecN).insert(text)
        shape.text_size = 0.1 / dbu
        t = Trans(Trans.R0, 0, -w * 1.5)
        text = Text \
          ('Spice_param:length=%.3fu target_period=%.3fu grating_period=%.3fu swg_wg_width=%.3fu strip_wg_width=%.3fu duty=%.3f ' %\
          (self.length, self.target_period, round(grating_period)*dbu, self.swg_wg_width, self.strip_wg_width, self.duty), t )
        shape = shapes(LayerDevRecN).insert(text)
        shape.text_size = 0.1 / dbu
Esempio n. 2
0
  def test_1_Trans(self):

    a = pya.Trans()
    b = pya.Trans( pya.Trans.M135, pya.Point( 17, 5 ))
    c = pya.Trans( 3, True, pya.Point( 17, 5 ))
    d = pya.Trans( pya.Point( 17, 5 ))
    e = pya.Trans( pya.Trans.M135 )
    e2 = pya.Trans.from_dtrans( pya.DTrans.M135 )
    f = pya.Trans( pya.DTrans( pya.DTrans.M135, pya.DPoint( 17, 5 )) )

    self.assertEqual( str(a), "r0 0,0" )
    self.assertEqual( str(pya.Trans.from_s(str(a))), str(a) )
    self.assertEqual( str(b), "m135 17,5" )
    self.assertEqual( str(c), "m135 17,5" )
    self.assertEqual( str(d), "r0 17,5" )
    self.assertEqual( str(e), "m135 0,0" )
    self.assertEqual( str(e2), "m135 0,0" )
    self.assertEqual( str(f), "m135 17,5" )
    self.assertEqual( str(pya.Trans.from_s(str(f))), str(f) )

    self.assertEqual( str(b.trans( pya.Point( 1, 0 ))), "17,4" )

    self.assertEqual( a == b, False )
    self.assertEqual( a == a, True )
    self.assertEqual( a != b, True )
    self.assertEqual( a != a, False )
    self.assertEqual( (d * e) == b, True )
    self.assertEqual( (e * d) == b, False )

    i = c.inverted()

    self.assertEqual( str(i), "m135 5,17" )
    self.assertEqual( (i * b) == a, True )
    self.assertEqual( (b * i) == a, True )

    c = pya.Trans( 3, True, pya.Point( 17, 5 ))
    self.assertEqual( str(c), "m135 17,5" )
    c.disp = pya.Point(1, 7)
    self.assertEqual( str(c), "m135 1,7" )
    c.angle = 1
    self.assertEqual( str(c), "m45 1,7" )
    c.rot = 3
    self.assertEqual( str(c), "r270 1,7" )
    c.mirror = True
    self.assertEqual( str(c), "m135 1,7" )

    self.assertEqual( str(e.trans( pya.Edge(0, 1, 2, 3) )), "(-3,-2;-1,0)" )
    self.assertEqual( str(( e * pya.Edge(0, 1, 2, 3) )), "(-3,-2;-1,0)" )
    self.assertEqual( str(e.trans( pya.Box(0, 1, 2, 3) )), "(-3,-2;-1,0)" )
    self.assertEqual( str(( e * pya.Box(0, 1, 2, 3) )), "(-3,-2;-1,0)" )
    self.assertEqual( str(e.trans( pya.Text("text", pya.Vector(0, 1)) )), "('text',m135 -1,0)" )
    self.assertEqual( str(( e * pya.Text("text", pya.Vector(0, 1)) )), "('text',m135 -1,0)" )
    self.assertEqual( str(e.trans( pya.Polygon( [ pya.Point(0, 1), pya.Point(2, -3), pya.Point(4, 5) ] ) )), "(-5,-4;-1,0;3,-2)" )
    self.assertEqual( str(( e * pya.Polygon( [ pya.Point(0, 1), pya.Point(2, -3), pya.Point(4, 5) ] ) )), "(-5,-4;-1,0;3,-2)" )
    self.assertEqual( str(e.trans( pya.Path( [ pya.Point(0, 1), pya.Point(2, 3) ], 10 ) )), "(-1,0;-3,-2) w=10 bx=0 ex=0 r=false" )
    self.assertEqual( str(( e * pya.Path( [ pya.Point(0, 1), pya.Point(2, 3) ], 10 ) )), "(-1,0;-3,-2) w=10 bx=0 ex=0 r=false" )
Esempio n. 3
0
def make_pin(cell, name, center, w, pin_length, layer, vertical=0):
    """Handy method to create a pin on a device to avoid repetitive code.

  Args:
      cell (pya cell): cell to create the pin on
      name (string): name of the pin
      center (list): center of the pin in dbu. Format: [x, y]
      w (int): width of the pin in dbu
      pin_length (int): length of the pin in dbu, change the sign to determine pin direction. Default is left-to-right.
      layer (pya layer): layer to create the pin on
      vertical (int, optional): flag to determine if pin is vertical or horizontal. Defaults to 0.
  """
    if vertical == 0:
        p1 = pya.Point(center[0] + pin_length / 2, center[1])
        p2 = pya.Point(center[0] - pin_length / 2, center[1])
    elif vertical == 1:
        p1 = pya.Point(center[0], center[1] + pin_length / 2)
        p2 = pya.Point(center[0], center[1] - pin_length / 2)

    pin = pya.Path([p1, p2], w)
    t = Trans(Trans.R0, center[0], center[1])
    text = Text(name, t)
    shape = cell.shapes(layer).insert(text)
    shape.text_size = 0.1
    cell.shapes(layer).insert(pin)

    return shape
Esempio n. 4
0
    def get_polygons(self, include_pins=True):
        from .utils import get_layout_variables
        TECHNOLOGY, lv, ly, cell = get_layout_variables()

        r = pya.Region()

        s = self.cell.begin_shapes_rec(ly.layer(TECHNOLOGY['Waveguide']))
        while not (s.at_end()):
            if s.shape().is_polygon() or s.shape().is_box() or s.shape(
            ).is_path():
                r.insert(s.shape().polygon.transformed(s.itrans()))
            s.next()

        if include_pins:
            s = self.cell.begin_shapes_rec(ly.layer(TECHNOLOGY['PinRec']))
            import math
            from .utils import angle_vector
            while not (s.at_end()):
                if s.shape().is_path():
                    p = s.shape().path.transformed(s.itrans())
                    # extend the pin path by 1 micron for FDTD simulations
                    pts = [pt for pt in p.each_point()]
                    # direction / angle of the optical pin
                    rotation = angle_vector(pts[0] - pts[1]) * math.pi / 180
                    pts[1] = (
                        pts[1] -
                        pya.Point(int(math.cos(rotation) * 1000),
                                  int(math.sin(rotation) * 1000))).to_p()
                    r.insert(pya.Path(pts, p.width).polygon())
                s.next()

        r.merge()
        polygons = [p for p in r.each_merged()]

        return polygons
Esempio n. 5
0
    def next_level(self):
        self.level += 1
        print("Drawing Hilbert Level %g" % self.level)
        newcell = self.layout.create_cell(self.cell_prefix + "level_" +
                                          str(self.level))
        transll = pya.Trans(0, 0)
        translr = pya.Trans(self.box_size + self.length, 0)
        transul = pya.Trans(1, False, self.box_size + self.cd,
                            self.box_size + self.length)
        transur = pya.Trans(3, False, self.box_size + self.length,
                            self.box_size * 2 + self.length + self.cd)
        print("    Placing Cells...")
        ll_inst = pya.CellInstArray(self.cell.cell_index(), transll)
        lr_inst = pya.CellInstArray(self.cell.cell_index(), translr)
        ul_inst = pya.CellInstArray(self.cell.cell_index(), transul)
        ur_inst = pya.CellInstArray(self.cell.cell_index(), transur)

        newcell.insert(ll_inst)
        newcell.insert(lr_inst)
        newcell.insert(ur_inst)
        newcell.insert(ul_inst)
        print("    Connecting Quadrants...")
        p11 = pya.Point(self.box_size + self.cd / 2,
                        self.box_size + self.cd / 2)
        p12 = pya.Point(self.box_size + self.cd / 2 + self.length,
                        self.box_size + self.cd / 2)
        p21 = pya.Point(self.cd / 2, self.cd / 2 + self.box_size)
        p22 = pya.Point(self.cd / 2, self.cd / 2 + self.box_size + self.length)
        p31 = pya.Point(self.box_size * 2 + self.length + self.cd / 2,
                        self.cd / 2 + self.box_size)
        p32 = pya.Point(self.box_size * 2 + self.length + self.cd / 2,
                        self.cd / 2 + self.box_size + self.length)
        path1 = pya.Path([p11, p12], self.cd, self.cd / 2,
                         self.cd / 2).polygon()
        path2 = pya.Path([p21, p22], self.cd, self.cd / 2,
                         self.cd / 2).polygon()
        path3 = pya.Path([p31, p32], self.cd, self.cd / 2,
                         self.cd / 2).polygon()

        newcell.shapes(self.layer).insert(path1)
        newcell.shapes(self.layer).insert(path2)
        newcell.shapes(self.layer).insert(path3)
        print("    Updating Box Size...")
        self.box_size = self.box_size * 2 + self.length
        self.cell = newcell
        print("Done!")
Esempio n. 6
0
def pointlist_to_path(pointlist, dbu):
    # convert [[230.175,169.18],[267.0,169.18],[267.0,252.0],[133.0,252.0],[133.0,221.82],[140.175,221.82]]
    # to pya.Path

    points = []
    for p in points:
        points.append(pya.Point(p[0], p[1]))
    path = pya.Path(points)
    return path
Esempio n. 7
0
 def draw_init(self, type):
     p1 = pya.Point(self.cd / 2, self.cd / 2)
     p2 = pya.Point(self.cd / 2 + self.length * 2, self.cd / 2)
     p31 = pya.Point(self.cd / 2 + self.length,
                     self.cd / 2 + self.length * 2)
     p32 = pya.Point(self.cd / 2 + self.length * 2,
                     self.cd / 2 + self.length)
     p41 = pya.Point(self.cd / 2 + self.length, self.cd / 2)
     p42 = pya.Point(self.cd / 2, self.cd / 2 + self.length)
     p5 = pya.Point(self.cd / 2, self.cd / 2 + self.length * 2)
     p6 = pya.Point(self.cd / 2 + self.length * 2,
                    self.cd / 2 + self.length * 2)
     if type == 1:
         self.cell.shapes(self.layer).insert(
             pya.Path([p1, p5, p31, p41, p2, p6], self.cd, self.cd / 2,
                      self.cd / 2).polygon())
     elif type == 2:
         self.cell.shapes(self.layer).insert(
             pya.Path([p1, p2, p32, p42, p5, p6], self.cd, self.cd / 2,
                      self.cd / 2).polygon())
Esempio n. 8
0
    def draw_init(self):
        p1 = pya.Point(self.cd / 2, self.cd / 2 + self.length)
        p2 = pya.Point(self.cd / 2, self.cd / 2)
        p3 = pya.Point(self.cd / 2 + self.length, self.cd / 2)
        p4 = pya.Point(self.cd / 2 + self.length, self.cd / 2 + self.length)
        self.cell.shapes(self.layer).insert(
            pya.Path([p1, p2, p3, p4], self.cd, self.cd / 2,
                     self.cd / 2).polygon())

        #        self.cell.shapes(self.layout.layer(10,0)).insert(pya.Box(self.cd,0,self.cd*2,self.cd))
        self.cell.shapes(self.layout.layer(self.via_layer, 0)).insert(
            pya.Box(0, 0, self.cd * 2, self.cd))
Esempio n. 9
0
def snap(self, pins):
  # Import functionality from SiEPIC-Tools:
  from .utils import angle_vector, get_technology
  from . import _globals
  TECHNOLOGY = get_technology()
    
  # Search for pins within this distance to the path endpoints, e.g., 10 microns
  d_min = _globals.PATH_SNAP_PIN_MAXDIST/TECHNOLOGY['dbu'];

  if not len(pins): return

  # array of path vertices:
  pts = self.get_points()

  # angles of all segments:
  ang = angle_vector(pts[0]-pts[1])
  
  # sort all the pins based on distance to the Path endpoint
  # only consider pins that are facing each other, 180 degrees 
  pins_sorted = sorted([pin for pin in pins if round((ang - pin.rotation)%360) == 180 and pin.type == _globals.PIN_TYPES.OPTICAL], key=lambda x: x.center.distance(pts[0]))

  if len(pins_sorted):
    # pins_sorted[0] is the closest one
    dpt = pins_sorted[0].center - pts[0]
    # check if the pin is close enough to the path endpoint
    if dpt.abs() <= d_min:
      # snap the endpoint to the pin
      pts[0] += dpt
      # move the first corner
      if(round(ang % 180) == 0):
        pts[1].y += dpt.y
      else:
        pts[1].x += dpt.x
        
  # do the same thing on the other end:  
  ang = angle_vector(pts[-1]-pts[-2])
  pins_sorted = sorted([pin for pin in pins if round((ang - pin.rotation)%360) == 180 and pin.type == _globals.PIN_TYPES.OPTICAL], key=lambda x: x.center.distance(pts[-1]))
  if len(pins_sorted):
    dpt = pins_sorted[0].center - pts[-1]
    if dpt.abs() <= d_min:
      pts[-1] += dpt
      if(round(ang % 180) == 0):
        pts[-2].y += dpt.y
      else:
        pts[-2].x += dpt.x

  # check that the path has non-zero length after the snapping operation
  test_path = pya.Path()
  test_path.points = pts
  if test_path.length() > 0:
    self.points = pts
Esempio n. 10
0
def make_pin(cell, name, center, w, pin_length, layer, vertical=0):
    if vertical == 0:
        p1 = pya.Point(center[0] + pin_length / 2, center[1])
        p2 = pya.Point(center[0] - pin_length / 2, center[1])
    elif vertical == 1:
        p1 = pya.Point(center[0], center[1] + pin_length / 2)
        p2 = pya.Point(center[0], center[1] - pin_length / 2)

    pin = pya.Path([p1, p2], w)
    t = Trans(Trans.R0, center[0], center[1])
    text = Text(name, t)
    shape = cell.shapes(layer).insert(text)
    shape.text_size = 0.1
    cell.shapes(layer).insert(pin)
Esempio n. 11
0
    def create_path(self, points: list, width: float, layer: 'pya.LayerInfo'):
        """Creates a pya.Path object and inserts it into the Library-PCell.

        :param points: The points describing the path [[x1,y1],[x2,y2],...] in microns
        :param width: Path width
        :param layer: layer on which the path should be made
        """
        pts = []
        for p in points:
            pts.append(
                pya.Point(
                    pya.DPoint(p[0] / self.layout.dbu,
                               p[1] / self.layout.dbu)))
        w = int(width / self.layout.dbu)
        self.cell.shapes(self.layout.find_layer(layer)).insert(pya.Path(
            pts, w))
Esempio n. 12
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)
Esempio n. 13
0
  def produce_impl(self):

    # This is the main part of the implementation: create the layout
    from math import pi, cos, sin
    from SiEPIC.extend import to_itype
    
    # fetch the parameters
#    TECHNOLOGY = get_technology_by_name('GSiP')
    dbu = self.layout.dbu
    ly = self.layout
    shapes = self.cell.shapes
    
    LayerSi3N = ly.layer(self.si3layer)
    LayerSiN = ly.layer(self.silayer)
    LayernN = ly.layer(self.nlayer)
    LayerpN = ly.layer(self.player)
    LayernpN = ly.layer(self.nplayer)
    LayerppN = ly.layer(self.pplayer)
    LayernppN = ly.layer(self.npplayer)
    LayerpppN = ly.layer(self.ppplayer)
    LayervcN = ly.layer(self.vclayer)
    Layerm1N = ly.layer(self.m1layer)
    LayervlN = ly.layer(self.vllayer)
    LayermlN = ly.layer(self.mllayer)
    LayermhN = ly.layer(self.mhlayer)
    TextLayerN = ly.layer(self.textl)
    LayerPinRecN = ly.layer(self.pinrec)
    LayerDevRecN = ly.layer(self.devrec)

    # Define variables for the Modulator
    # Variables for the Si waveguide
    w = to_itype(self.w,dbu)
    r = to_itype(self.r,dbu)
    g = to_itype(self.g,dbu)
    gmon = to_itype(self.gmon,dbu)
    
    #Variables for the N layer
    w_1 = 2.0/dbu  #same for N, P, N+, P+ layer
    r_n = to_itype(self.r - 1.0,dbu)
    
    #Variables for the P layer
    r_p = to_itype(self.r + 1.0, dbu)
     
    #Variables for the N+layer
    r_np = to_itype(self.r - 1.5,dbu)
    
    #Variables for the P+layer
    r_pp = to_itype(self.r + 1.5,dbu)

    #Variables for the N++ layer
    w_2 = to_itype(5.5,dbu)  #same for N++, P++ layer
    r_npp = to_itype(self.r - 3.75,dbu)

    #Variables for the P+layer
    r_ppp = to_itype(self.r + 3.75,dbu)

    #Variables for the VC layer
    w_vc = to_itype(4.0,dbu)
    r_vc1 = to_itype(self.r - 3.75,dbu)
    r_vc2 = to_itype(self.r + 3.75,dbu)
   
    #Variables for the M1 layer
    w_m1_in = r_vc1 + w_vc/2.0 + to_itype(0.5,dbu)
    r_m1_in = r_vc1 + w_vc/2.0 + to_itype(0.5,dbu) /2.0
    w_m1_out = to_itype(6.0,dbu)
    r_m1_out = to_itype(self.r + 4.25,dbu)
    
    #Variables for the VL layer
    #r_vl =  w_m1_in/2.0 -  2.1/dbu
    r_vl =  r_vc1 - w_vc/2.0 - to_itype(2.01,dbu)
    if r_vl < to_itype(1.42,dbu):
      r_vl = to_itype(1.42,dbu)
      w_vc = r - to_itype(1.75,dbu) - (r_vl + 2.01)
      r_vc1 = r - to_itype(1.75,dbu) - w_vc/2.0
      r_vc2 = r + to_itype(1.75,dbu) + w_vc/2.0
      w_2 = (r-w/2.0 - to_itype(0.75,dbu)) - (r_vc1 - w_vc/2.0 - 0.75) # same for N++, P++ layer
      r_npp = ((r-w/2.0 - to_itype(0.75,dbu)) + (r_vc1 - w_vc/2.0 - 0.75))/2.0
      r_ppp = 2*r - r_npp
    w_via = to_itype(5.0,dbu)
    h_via = to_itype(5.0,dbu)

    # Variables for the SiEtch2 layer  (Slab)
    w_Si3 = round(w_m1_out + 2*(r_m1_out)+ 0/dbu)
    h_Si3 = w_Si3
    taper_bigend =  to_itype(2,dbu)
    taper_smallend =  to_itype(0.3,dbu)
    taper_length =  to_itype(5,dbu)

    #Variables for the MH layer
    w_mh = to_itype(2.0,dbu)
    r_mh = r
    r_mh_in = r_mh - w_mh/2.0
    
    #Define Ring centre   
    x0 = r + w/2
    y0 = r + g + w 

    ######################
    # Generate the layout:
   
    # Create the ring resonator
    t = pya.Trans(pya.Trans.R0,x0, y0)
    pcell = ly.create_cell("Ring", "GSiP", { "layer": self.silayer, "radius": self.r, "width": self.w } )
    self.cell.insert(pya.CellInstArray(pcell.cell_index(), t))

    
    # Create the two waveguides
    wg1 = pya.Box(x0 - (w_Si3 / 2 + taper_length), -w/2, x0 + (w_Si3 / 2 + taper_length), w/2)
    shapes(LayerSiN).insert(wg1)
    y_offset = 2*r + g + gmon + 2*w
    wg2 = pya.Box(x0 - (w_Si3 / 2 + taper_length), y_offset-w/2, x0 + (w_Si3 / 2 + taper_length), y_offset+w/2)
    shapes(LayerSiN).insert(wg2)

    
    #Create the SiEtch2 (Slab) layer
    boxSi3 = pya.Box(x0-w_Si3/2.0, y0 - h_Si3/2.0, x0+w_Si3/2.0, y0 + h_Si3/2.0)
    shapes(LayerSi3N).insert(boxSi3)
    pin1pts = [pya.Point(x0-w_Si3/2.0, -taper_bigend/2.0),
               pya.Point(x0-w_Si3/2.0-taper_length,-taper_smallend/2.0),
               pya.Point(x0-w_Si3/2.0-taper_length,taper_smallend/2.0),
               pya.Point(x0-w_Si3/2.0, taper_bigend/2.0)]
    pin2pts = [pya.Point(x0+w_Si3/2.0,-taper_bigend/2.0),
               pya.Point(x0+w_Si3/2.0+taper_length,-taper_smallend/2.0),
               pya.Point(x0+w_Si3/2.0+taper_length,taper_smallend/2.0),
               pya.Point(x0+w_Si3/2.0,+taper_bigend/2.0)]
    pin3pts = [pya.Point(x0-w_Si3/2.0,y_offset-taper_bigend/2.0),
               pya.Point(x0-w_Si3/2.0-taper_length,y_offset-taper_smallend/2.0),
               pya.Point(x0-w_Si3/2.0-taper_length,y_offset+taper_smallend/2.0),
               pya.Point(x0-w_Si3/2.0,y_offset+ taper_bigend/2.0)]
    pin4pts = [pya.Point(x0+w_Si3/2.0,y_offset-taper_bigend/2.0),
               pya.Point(x0+w_Si3/2.0+taper_length,y_offset-taper_smallend/2.0),
               pya.Point(x0+w_Si3/2.0+taper_length,y_offset+taper_smallend/2.0),
               pya.Point(x0+w_Si3/2.0,y_offset+taper_bigend/2.0)]
    shapes(LayerSi3N).insert(pya.Polygon(pin1pts))
    shapes(LayerSi3N).insert(pya.Polygon(pin2pts))
    shapes(LayerSi3N).insert(pya.Polygon(pin3pts))
    shapes(LayerSi3N).insert(pya.Polygon(pin4pts))
    
    # arc angles
    # doping:
    angle_min_doping = -35
    angle_max_doping = 215
    # VC contact:
    angle_min_VC = angle_min_doping + 8
    angle_max_VC = angle_max_doping - 8
    # M1:
    angle_min_M1 = angle_min_VC - 4
    angle_max_M1 = angle_max_VC + 4
    # MH:
    angle_min_MH = -75.0
    angle_max_MH = 255

    from SiEPIC.utils import arc

    #Create the N Layer
    self.cell.shapes(LayernN).insert(pya.Path(arc(r_n, angle_min_doping, angle_max_doping), w_1).transformed(t).simple_polygon())

    #Create the P Layer
    self.cell.shapes(LayerpN).insert(pya.Path(arc(r_p, angle_min_doping, angle_max_doping), w_1).transformed(t).simple_polygon())
    
    #Create the N+ Layer
    self.cell.shapes(LayernpN).insert(pya.Path(arc(r_np, angle_min_doping, angle_max_doping), w_1).transformed(t).simple_polygon())

    #Create the P+ Layer
    self.cell.shapes(LayerppN).insert(pya.Path(arc(r_pp, angle_min_doping, angle_max_doping), w_1).transformed(t).simple_polygon())
    
    #Create the N++ Layer
    self.cell.shapes(LayernppN).insert(pya.Path(arc(r_npp, angle_min_doping, angle_max_doping), w_2).transformed(t).simple_polygon())

    #Create the P+ +Layer
    poly = pya.Path(arc(r_ppp, angle_min_doping, angle_max_doping), w_2).transformed(t).simple_polygon()
    self.cell.shapes(LayerpppN).insert(pya.Region(poly) - pya.Region(pya.Box(x0-r_ppp-w_2/2, y_offset-w/2 - 0.75/dbu, x0+r_ppp+w/2, y_offset+w/2 + 0.75/dbu)))
    
    #Create the VC Layer
    self.cell.shapes(LayervcN).insert(pya.Path(arc(r_vc1, angle_min_VC, angle_max_VC), w_vc).transformed(t).simple_polygon())

    poly = pya.Path(arc(r_vc2, angle_min_VC, angle_max_VC), w_vc).transformed(t).simple_polygon()
    self.cell.shapes(LayervcN).insert(pya.Region(poly) - pya.Region(pya.Box(x0-r_vc2-w_vc/2, y_offset-w/2 - 1.5/dbu, x0+r_vc2+w_vc/2, y_offset+w/2 + 1.5/dbu)))

        
    #Create the M1 Layer
    self.cell.shapes(Layerm1N).insert(pya.Polygon(arc(w_m1_in, angle_min_doping, angle_max_doping) + [pya.Point(0, 0)]).transformed(t))
    self.cell.shapes(Layerm1N).insert(pya.Polygon(arc(w_m1_in/2.0, 0, 360)).transformed(t))
    self.cell.shapes(Layerm1N).insert(pya.Path(arc(r_m1_out, angle_min_M1, angle_max_M1), w_m1_out).transformed(t).simple_polygon())
    boxM11 = pya.Box(x0-w_via, y0 + r_m1_out + w_m1_out-h_via, x0+w_via, y0 + r_m1_out + w_m1_out+h_via)
    shapes(Layerm1N).insert(boxM11)
    
    #Create the ML Layer
    self.cell.shapes(LayermlN).insert(pya.Polygon(arc(w_m1_in/2.0, 0, 360)).transformed(t))
    
    #Create the VL Layer, as well as the electrical PinRec geometries
    # centre contact (P, anode):
    self.cell.shapes(LayervlN).insert(pya.Polygon(arc(r_vl, 0, 360)).transformed(t))
    self.cell.shapes(LayerPinRecN).insert(pya.Polygon(arc(r_vl, 0, 360)).transformed(t))
    shapes(LayerPinRecN).insert(pya.Text ("elec1a", pya.Trans(pya.Trans.R0,x0,y0))).text_size = 0.5/dbu
    shapes(LayerPinRecN).insert(pya.Box(x0-w_via/2, y0-w_via/2, x0+w_via/2, y0+w_via/2))
    
    # top contact (N, cathode):
    boxVL1 = pya.Box(x0-w_via/2, y0 +  r_vc2 +  w_vc/2 + 2.0/dbu, x0+w_via/2, y0 + r_vc2 +  w_vc/2 + 2.0/dbu+ h_via)
    shapes(LayervlN).insert(boxVL1)
    shapes(LayerPinRecN).insert(boxVL1)
    shapes(LayerPinRecN).insert(pya.Text ("elec1c", pya.Trans(pya.Trans.R0,x0,y0 + r_vc2 +  w_vc/2 + 2.0/dbu+ h_via/2))).text_size = 0.5/dbu
    # heater contacts
    boxVL3 = pya.Box(x0+(r_mh_in)*cos(angle_min_MH/180*pi) + 2.5/dbu, -w/2.0 -  10/dbu, x0 + (r_mh_in)*cos(angle_min_MH/180*pi) + 7.5/dbu, -w/2.0 -  5/dbu)
    shapes(LayervlN).insert(boxVL3)
    shapes(LayerPinRecN).insert(boxVL3)
    shapes(LayerPinRecN).insert(pya.Text ("elec2h2", pya.Trans(pya.Trans.R0,x0+(r_mh_in)*cos(angle_min_MH/180*pi) + 5.0/dbu,-w/2.0 -  7.5/dbu))).text_size = 0.5/dbu
    boxVL4 = pya.Box(x0-(r_mh_in)*cos(angle_min_MH/180*pi)- 7.5/dbu, -w/2.0 -  10/dbu, x0 - (r_mh_in)*cos(angle_min_MH/180*pi) - 2.5/dbu, -w/2.0 -  5/dbu)
    shapes(LayervlN).insert(boxVL4)
    shapes(LayerPinRecN).insert(boxVL4)
    shapes(LayerPinRecN).insert(pya.Text ("elec2h1", pya.Trans(pya.Trans.R0,x0-(r_mh_in)*cos(angle_min_MH/180*pi) - 5.0/dbu,-w/2.0 -  7.5/dbu))).text_size = 0.5/dbu

    #Create the MH Layer
    self.cell.shapes(LayermhN).insert(pya.Path(arc(r_mh, angle_min_MH, angle_max_MH), w_mh).transformed(t).simple_polygon())
    boxMH1 = pya.Box(x0+(r_mh_in)*cos(angle_min_MH/180*pi), -w/2.0 -  2.5/dbu, x0 + (r_mh_in)*cos(angle_min_MH/180*pi) + w_mh, y0 +(r_mh_in)*sin(angle_min_MH/180*pi))
    shapes(LayermhN).insert(boxMH1)
    boxMH2 = pya.Box(x0-(r_mh_in)*cos(angle_min_MH/180*pi)  - w_mh, -w/2.0 -  2.5/dbu, x0 - (r_mh_in)*cos(angle_min_MH/180*pi), y0 +(r_mh_in)*sin(angle_min_MH/180*pi))
    shapes(LayermhN).insert(boxMH2)
    boxMH3 = pya.Box(x0+(r_mh_in)*cos(angle_min_MH/180*pi), -w/2.0 -  12.5/dbu, x0 + (r_mh_in)*cos(angle_min_MH/180*pi) + 10/dbu, -w/2.0 -  2.5/dbu)
    shapes(LayermhN).insert(boxMH3)
    boxMH4 = pya.Box(x0-(r_mh_in)*cos(angle_min_MH/180*pi)- 10/dbu, -w/2.0 -  12.5/dbu, x0 - (r_mh_in)*cos(angle_min_MH/180*pi), -w/2.0 -  2.5/dbu)
    shapes(LayermhN).insert(boxMH4)
    
    # Create the pins, as short paths:
    from SiEPIC._globals import PIN_LENGTH as pin_length
        
    shapes(LayerPinRecN).insert(pya.Path([pya.Point(x0 - (w_Si3 / 2. + taper_length) + pin_length/2., 0),
                                          pya.Point(x0 - (w_Si3 / 2. + taper_length) - pin_length/2., 0)], w))
    shapes(LayerPinRecN).insert(pya.Text("opt1", pya.Trans(pya.Trans.R0,x0 - (w_Si3 / 2. + taper_length), 0))).text_size = 0.5/dbu

    shapes(LayerPinRecN).insert(pya.Path([pya.Point(x0 + (w_Si3 / 2. + taper_length) - pin_length/2., 0),
                                          pya.Point(x0 + (w_Si3 / 2. + taper_length)           + pin_length/2., 0)], w))
    shapes(LayerPinRecN).insert(pya.Text("opt2", pya.Trans(pya.Trans.R0,x0 + (w_Si3 / 2. + taper_length), 0))).text_size = 0.5/dbu

    shapes(LayerPinRecN).insert(pya.Path([pya.Point(x0 - (w_Si3 / 2. + taper_length) + pin_length/2., y_offset),
                                          pya.Point(x0 - (w_Si3 / 2. + taper_length) - pin_length/2., y_offset)], w))
    shapes(LayerPinRecN).insert(pya.Text("opt3", pya.Trans(pya.Trans.R0,x0 - (w_Si3 / 2. + taper_length), y_offset))).text_size = 0.5/dbu

    shapes(LayerPinRecN).insert(pya.Path([pya.Point(x0 + (w_Si3 / 2. + taper_length) - pin_length/2., y_offset),
                                          pya.Point(x0 + (w_Si3 / 2. + taper_length) + pin_length/2., y_offset)], w))
    shapes(LayerPinRecN).insert(pya.Text("opt4", pya.Trans(pya.Trans.R0,x0 + (w_Si3 / 2. + taper_length), y_offset))).text_size = 0.5/dbu

    # Create the device recognition layer
    shapes(LayerDevRecN).insert(pya.Box(x0 - (w_Si3 / 2 + taper_length), -w/2.0 -  12.5/dbu, x0 + (w_Si3 / 2 + taper_length), y0 + r_m1_out + w_m1_out+h_via ))

    # Compact model information
    shape = shapes(LayerDevRecN).insert(pya.Text('Lumerical_INTERCONNECT_library=Design kits/GSiP', \
      pya.Trans(pya.Trans.R0,0, 0))).text_size = 0.3/dbu
    shapes(LayerDevRecN).insert(pya.Text('Component=Ring_Modulator_DB', \
      pya.Trans(pya.Trans.R0,0, w*2))).text_size = 0.3/dbu
    shapes(LayerDevRecN).insert(pya.Text('Component_ID=%s' % self.component_ID, \
      pya.Trans(pya.Trans.R0,0, w*4))).text_size = 0.3/dbu
    shapes(LayerDevRecN).insert(pya.Text \
      ('Spice_param:radius=%.3fu wg_width=%.3fu gap=%.3fu gap_monitor=%.3fu' %\
      (self.r, self.w, self.g, self.gmon), \
      pya.Trans(pya.Trans.R0,0, -w*2) ) ).text_size = 0.3/dbu
    
    # Add a polygon text description
    from SiEPIC.utils import layout_pgtext
    if self.textpolygon : layout_pgtext(self.cell, self.textl, self.w, self.r+self.w, "%.3f-%g" % ( self.r, self.g), 1)

    # Reference publication:
    shapes(TextLayerN).insert(pya.Text ("Ref: Raphael Dube-Demers, JLT, 2015", pya.Trans(pya.Trans.R0,x0 - (w_Si3 / 2 + taper_length), -w/2.0 -  12.5/dbu+4.0/dbu))).text_size = 0.7/dbu
    shapes(TextLayerN).insert(pya.Text ("http://dx.doi.org/10.1109/JLT.2015.2462804", pya.Trans(pya.Trans.R0,x0 - (w_Si3 / 2 + taper_length), -w/2.0 -  12.5/dbu+1.0/dbu))).text_size = 0.7/dbu
Esempio n. 14
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
Esempio n. 15
0
def make_pin(cell, name, center, w, layer, direction):
    '''
    Makes a pin that SiEPIC-Tools will recognize
    cell: which cell to draw it in
    name: text label for the pin
    center: location, int [x,y]
    w: pin width
    layer: layout.layer() type
    direction = 
        0: right
        90: up
        180: left
        270: down

    Units: intput can be float for microns, or int for nm
    '''

    from SiEPIC.extend import to_itype
    import numpy
    dbu = cell.layout().dbu
    if type(w) == type(float()):
        w = to_itype(w, dbu)
        print('SiEPIC.utils.layout.make_pin: w converted to %s' % w)
    else:
        print('SiEPIC.utils.layout.make_pin: w %s' % w)


#    print(type(center[0]))
    if type(center[0]) == type(float()) or type(center[0]) == type(
            numpy.float64()):
        center[0] = to_itype(center[0], dbu)
        center[1] = to_itype(center[1], dbu)
        print('SiEPIC.utils.layout.make_pin: center converted to %s' %
              (center))
    else:
        print('SiEPIC.utils.layout.make_pin: center %s' % (center))

    from SiEPIC._globals import PIN_LENGTH as pin_length

    if direction not in [0, 90, 180, 270]:
        raise ('error in make_pin: direction must be one of [0, 90, 180, 270]')

    # text label
    t = pya.Trans(pya.Trans.R0, center[0], center[1])
    text = pya.Text(name, t)
    shape = cell.shapes(layer).insert(text)
    shape.text_dsize = float(w * dbu)
    shape.text_valign = 1

    if direction == 0:
        p1 = pya.Point(center[0] - pin_length / 2, center[1])
        p2 = pya.Point(center[0] + pin_length / 2, center[1])
        shape.text_halign = 2
    if direction == 90:
        p1 = pya.Point(center[0], center[1] - pin_length / 2)
        p2 = pya.Point(center[0], center[1] + pin_length / 2)
        shape.text_halign = 2
        shape.text_rot = 1
    if direction == 180:
        p1 = pya.Point(center[0] + pin_length / 2, center[1])
        p2 = pya.Point(center[0] - pin_length / 2, center[1])
        shape.text_halign = 3
    if direction == 270:
        p1 = pya.Point(center[0], center[1] + pin_length / 2)
        p2 = pya.Point(center[0], center[1] - pin_length / 2)
        shape.text_halign = 3
        shape.text_rot = 1

    pin = pya.Path([p1, p2], w)
    cell.shapes(layer).insert(pin)
Esempio n. 16
0
def to_itype(self, dbu):
  path = pya.Path([pt.to_itype(dbu) for pt in self.each_point()], round(self.width/dbu))
  path.width = round(self.width / dbu)
  return path
Esempio n. 17
0
    def produce_impl(self):
        # fetch the parameters
        dbu = self.layout.dbu
        ly = self.layout
        shapes = self.cell.shapes

        LayerSi = self.layer
        LayerSiN = ly.layer(self.layer)
        LayerPinRecN = ly.layer(self.pinrec)
        LayerDevRecN = ly.layer(self.devrec)
        LayerTextN = ly.layer(self.textl)

        from math import pi, cos, sin, log, sqrt, tan

        lambda_0 = self.wavelength  ##um wavelength of light
        pin_length = 0.5  ##um extra nub for the waveguide attachment

        # Geometry
        wh = self.period * self.dc  ##thick grating
        wl = self.ff * (self.period - wh)  ## thin grating

        # Width scale parameter is a first pass attempt at designing for length contraction
        # at cryogenic temperature. It is applied BEFORE the width error; this is because
        # the order of operations in the reverse is over/under-etch, then cool and contract.
        # So first scale so that target width is reached after contraction, then add
        # fabrication error so that the scaled width is reached.

        wh = (wh * self.w_scale + self.w_err)
        wl = (wl * self.w_scale + self.w_err)

        spacing = (self.period - wh - wl) / 2  ##space between thick and thin

        gc_number = int(round(self.grating_length /
                              self.period))  ##number of periods
        e = self.n_t * sin((pi / 180) * self.theta_c) / self.n_e
        N = round(self.taper_length * (1 + e) * self.n_e /
                  lambda_0)  ##allows room for the taper

        start = (pi - (pi / 180) * self.angle_e / 2)
        stop = (pi + (pi / 180) * self.angle_e / 2)

        # Draw coupler grating.
        for j in range(gc_number):

            # number of points in the arcs:
            # calculate such that the vertex & edge placement error is < 0.5 nm.
            #   see "SiEPIC_EBeam_functions - points_per_circle" for more details
            radius = N * lambda_0 / (self.n_e *
                                     (1 - e)) + j * self.period + spacing
            seg_points = int(
                points_per_circle(radius / dbu) / 360. *
                self.angle_e)  # number of points grating arc
            theta_up = []
            for m in range(seg_points + 1):
                theta_up = theta_up + [start + m * (stop - start) / seg_points]
            theta_down = theta_up[::-1]

            ##small one
            r_up = []
            r_down = []
            for k in range(len(theta_up)):
                r_up = r_up + [
                    N * lambda_0 / (self.n_e *
                                    (1 - e * cos(float(theta_up[k])))) +
                    j * self.period + spacing
                ]
            r_down = r_up[::-1]

            xr = []
            yr = []
            for k in range(len(theta_up)):
                xr = xr + [r_up[k] * cos(theta_up[k])]
                yr = yr + [r_up[k] * sin(theta_up[k])]

            xl = []
            yl = []
            for k in range(len(theta_down)):
                xl = xl + [(r_down[k] + wl) * cos(theta_down[k])]
                yl = yl + [(r_down[k] + wl) * sin(theta_down[k])]

            x = xr + xl
            y = yr + yl

            pts = []
            for i in range(len(x)):
                pts.append(
                    Point.from_dpoint(pya.DPoint(x[i] / dbu, y[i] / dbu)))
            #small_one = core.Boundary(points)

            polygon = Polygon(pts)
            shapes(LayerSiN).insert(polygon)

            ##big one
            r_up = []
            r_down = []
            for k in range(len(theta_up)):
                r_up = r_up + [
                    N * lambda_0 / (self.n_e *
                                    (1 - e * cos(float(theta_up[k])))) +
                    j * self.period + 2 * spacing + wl
                ]
            r_down = r_up[::-1]

            xr = []
            yr = []
            for k in range(len(theta_up)):
                xr = xr + [r_up[k] * cos(theta_up[k])]
                yr = yr + [r_up[k] * sin(theta_up[k])]

            xl = []
            yl = []
            for k in range(len(theta_down)):
                xl = xl + [(r_down[k] + wh) * cos(theta_down[k])]
                yl = yl + [(r_down[k] + wh) * sin(theta_down[k])]

            x = xr + xl
            y = yr + yl

            pts = []
            for i in range(len(x)):
                pts.append(
                    Point.from_dpoint(pya.DPoint(x[i] / dbu, y[i] / dbu)))

            polygon = Polygon(pts)
            shapes(LayerSiN).insert(polygon)

        # Taper section
        r_up = []
        r_down = []
        for k in range(len(theta_up)):
            r_up = r_up + [
                N * lambda_0 / (self.n_e * (1 - e * cos(float(theta_up[k]))))
            ]
        r_down = r_up[::-1]

        xl = []
        yl = []
        for k in range(len(theta_down)):
            xl = xl + [(r_down[k]) * cos(theta_down[k])]
            yl = yl + [(r_down[k]) * sin(theta_down[k])]

        yr = [self.t / 2., self.t / 2., -self.t / 2., -self.t / 2.]

        yl_abs = []
        for k in range(len(yl)):
            yl_abs = yl_abs + [abs(yl[k])]

        y_max = max(yl_abs)
        iy_max = yl_abs.index(y_max)

        L_o = (y_max - self.t / 2) / tan((pi / 180) * self.angle_e / 2)

        xr = [L_o + xl[iy_max], 0, 0, L_o + xl[iy_max]]

        x = xr + xl
        y = yr + yl

        pts = []
        for i in range(len(x)):
            pts.append(Point.from_dpoint(pya.DPoint(x[i] / dbu, y[i] / dbu)))

        polygon = Polygon(pts)
        shapes(LayerSiN).insert(polygon)

        # Pin on the waveguide:
        pin_length = 200
        x = 0
        t = Trans(x, 0)
        pin = pya.Path([Point(-pin_length / 2, 0),
                        Point(pin_length / 2, 0)], self.t / dbu)
        pin_t = pin.transformed(t)
        shapes(LayerPinRecN).insert(pin_t)
        text = Text("pin1", t)
        shape = shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu

        # Device recognition layer
        yr = sin(start) * (N * lambda_0 / (self.n_e *
                                           (1 - e * cos(float(start)))) +
                           gc_number * self.period + spacing)
        box1 = Box(
            -(self.grating_length + self.taper_length) / dbu - pin_length * 2,
            yr / dbu, 0, -yr / dbu)
        shapes(LayerDevRecN).insert(box1)
Esempio n. 18
0
    def produce_impl(self):

        # fetch the parameters
        dbu = self.layout.dbu
        ly = self.layout
        bus_n = self.bus_number

        LayerSi = self.layer
        LayerSiN = ly.layer(self.layer)
        LayerPinRecN = ly.layer(self.pinrec)
        LayerDevRecN = ly.layer(self.devrec)
        LayerTextN = ly.layer(self.textl)

        a = self.a / dbu
        r = self.r / dbu
        wg_dis = self.wg_dis + 1
        n = int(math.ceil(self.n / 2))
        Sx = [self.S1x, self.S2x, self.S3x, self.S4x, self.S5x]
        Sy = [self.S1y, 0, self.S2y]
        if wg_dis % 2 == 0:
            length_slab_x = 2 * n * a
        else:
            length_slab_x = (2 * n + 1) * a

        length_slab_y = 2 * (n - 2) * a

        if bus_n == 2:
            k = -1
        else:
            k = 1

        #function to creat polygon pts for right half of a hole in a hexagon unit cell
        def hexagon_hole_half(a, r):
            npts = 10
            theta_div = math.pi / 3
            theta_div_hole = math.pi / npts
            triangle_length = a / math.sqrt(3)
            pts = []
            for i in range(0, 4):
                pts.append(
                    Point.from_dpoint(
                        pya.DPoint(
                            triangle_length *
                            math.cos(i * theta_div - math.pi / 2),
                            triangle_length *
                            math.sin(i * theta_div - math.pi / 2))))
            for i in range(0, npts + 1):
                pts.append(
                    Point.from_dpoint(
                        pya.DPoint(
                            r * math.cos(math.pi / 2 - i * theta_div_hole),
                            r * math.sin(math.pi / 2 - i * theta_div_hole))))
            return pts

        def hexagon_shifthole_half(a, r):
            npts = 10
            theta_div = math.pi / 3
            theta_div_hole = math.pi / npts
            triangle_length = a * 1.235 / math.sqrt(3)
            pts = []
            for i in range(0, 4):
                pts.append(
                    Point.from_dpoint(
                        pya.DPoint(
                            triangle_length *
                            math.cos(i * theta_div - math.pi / 2),
                            triangle_length *
                            math.sin(i * theta_div - math.pi / 2))))
            for i in range(0, npts + 1):
                pts.append(
                    Point.from_dpoint(
                        pya.DPoint(
                            r * math.cos(math.pi / 2 - i * theta_div_hole),
                            r * math.sin(math.pi / 2 - i * theta_div_hole))))
            return pts

        #function to creat polygon pts for right half of a hexagon unit cell
        def hexagon_half(a):
            theta_div = math.pi / 3
            triangle_length = a / math.sqrt(3)
            pts = []
            for i in range(0, 4):
                pts.append(
                    Point.from_dpoint(
                        pya.DPoint(
                            triangle_length *
                            math.cos(i * theta_div - math.pi / 2),
                            triangle_length *
                            math.sin(i * theta_div - math.pi / 2))))
            return pts

        #create the right and left half of the hole and hexagon cells
        #hole_cell = pya.Region()
        #hexagon_cell = pya.Region()
        hole = pya.Region()

        hole_cell_pts = hexagon_hole_half(a, r)
        hexagon_pts = hexagon_half(a)
        hole_shiftcell_pts = hexagon_shifthole_half(a, r)
        hole_cell_poly_0 = pya.Polygon(hole_cell_pts)
        hexagon_cell_poly_0 = pya.Polygon(hexagon_pts)
        hole_shiftcell_poly_0 = pya.Polygon(hole_shiftcell_pts)

        hole_trans = pya.Trans(pya.Trans.R180)
        hole_cell_poly_1 = hole_cell_poly_0.transformed(hole_trans)
        hexagon_cell_poly_1 = hexagon_cell_poly_0.transformed(hole_trans)
        hole_shiftcell_poly_1 = hole_shiftcell_poly_0.transformed(hole_trans)

        #create the photonic crystal with shifts and waveguides
        for j in range(-n + 1, n):
            if j % 2 == 0:
                for i in range(-n, n + 1):
                    #waveguide
                    if (j == k * wg_dis and i > 3) or (j == wg_dis and i != 0):
                        hole_x = abs(i) / i * (abs(i) - 0.5) * a
                        hole_y = j * a * math.sqrt(3) / 2
                        hole_trans = pya.Trans(Trans.R0, hole_x, hole_y)
                        hole_t_0 = hexagon_cell_poly_0.transformed(hole_trans)
                        hole_t_1 = hexagon_cell_poly_1.transformed(hole_trans)
                        hole.insert(hole_t_0)
                        hole.insert(hole_t_1)
                    #filling the edges with half cell
                    elif i in (-n, n) and wg_dis % 2 == 1:
                        hole_x = abs(i) / i * (abs(i) + 0.5) * a
                        hole_y = j * a * math.sqrt(3) / 2
                        hole_trans = pya.Trans(Trans.R0, hole_x, hole_y)
                        if i == -n:
                            hole_t = hole_cell_poly_0.transformed(hole_trans)
                        else:
                            hole_t = hole_cell_poly_1.transformed(hole_trans)
                        hole.insert(hole_t)
                        hole_x = abs(i) / i * (abs(i) - 0.5) * a
                        hole_y = j * a * math.sqrt(3) / 2
                        hole_trans = pya.Trans(Trans.R0, hole_x, hole_y)
                        hole_t_0 = hole_cell_poly_0.transformed(hole_trans)
                        hole_t_1 = hole_cell_poly_1.transformed(hole_trans)
                        hole.insert(hole_t_0)
                        hole.insert(hole_t_1)
                    #x shifts
                    elif j == 0 and i in (1, -1, 2, -2, 3, -3, 4, -4, 5, -5):
                        hole_x = abs(i) / i * (abs(i) - 0.5 +
                                               Sx[abs(i) - 1]) * a
                        hole_y = 0
                        hole_trans = pya.Trans(Trans.R0, hole_x, hole_y)
                        hole_t_0 = hole_shiftcell_poly_0.transformed(
                            hole_trans)
                        hole_t_1 = hole_shiftcell_poly_1.transformed(
                            hole_trans)
                        hole.insert(hole_t_0)
                        hole.insert(hole_t_1)
                    elif i != 0:
                        hole_x = abs(i) / i * (abs(i) - 0.5) * a
                        hole_y = j * a * math.sqrt(3) / 2
                        hole_trans = pya.Trans(Trans.R0, hole_x, hole_y)
                        hole_t_0 = hole_cell_poly_0.transformed(hole_trans)
                        hole_t_1 = hole_cell_poly_1.transformed(hole_trans)
                        hole.insert(hole_t_0)
                        hole.insert(hole_t_1)
            elif j % 2 == 1:
                for i in range(-n, n + 1):
                    #waveguide
                    if (j == k * wg_dis and i > 3) or j == wg_dis:
                        hole_x = i * a
                        hole_y = j * a * math.sqrt(3) / 2
                        hole_trans = pya.Trans(Trans.R0, hole_x, hole_y)
                        hole_t_0 = hexagon_cell_poly_0.transformed(hole_trans)
                        hole_t_1 = hexagon_cell_poly_1.transformed(hole_trans)
                        hole.insert(hole_t_0)
                        hole.insert(hole_t_1)
                    #filling the edges with half cell
                    elif wg_dis % 2 == 0 and i in (-n, n):
                        hole_x = i * a
                        hole_y = j * a * math.sqrt(3) / 2
                        hole_trans = pya.Trans(Trans.R0, hole_x, hole_y)
                        if i == -n:
                            hole_t = hole_cell_poly_0.transformed(hole_trans)
                        else:
                            hole_t = hole_cell_poly_1.transformed(hole_trans)
                        hole.insert(hole_t)
                    #y shifts
                    elif i == 0 and j in (1, -1, 3, -3):
                        hole_x = 0
                        hole_y = j * a * (math.sqrt(3) /
                                          2) + abs(j) / j * a * Sy[abs(j) - 1]
                        hole_trans = pya.Trans(Trans.R0, hole_x, hole_y)
                        hole_t_0 = hole_shiftcell_poly_0.transformed(
                            hole_trans)
                        hole_t_1 = hole_shiftcell_poly_1.transformed(
                            hole_trans)
                        hole.insert(hole_t_0)
                        hole.insert(hole_t_1)
                    else:
                        hole_x = i * a
                        hole_y = j * a * math.sqrt(3) / 2
                        hole_trans = pya.Trans(Trans.R0, hole_x, hole_y)
                        hole_t_0 = hole_cell_poly_0.transformed(hole_trans)
                        hole_t_1 = hole_cell_poly_1.transformed(hole_trans)
                        hole.insert(hole_t_0)
                        hole.insert(hole_t_1)

        #print(hole_t_0)
        box_l = a / 2
        hole.insert(pya.Box(-box_l, -box_l, box_l, box_l))
        cover_box = pya.Box(-length_slab_x / 2, -a / 2, length_slab_x / 2,
                            a / 2)
        box_y = n * a * math.sqrt(3) / 2
        cover_box_trans_0 = pya.Trans(Trans.R0, 0, box_y)
        cover_box_trans_1 = pya.Trans(Trans.R0, 0, -box_y)
        cover_box_t_0 = cover_box.transformed(cover_box_trans_0)
        cover_box_t_1 = cover_box.transformed(cover_box_trans_1)
        #hole.insert(pya.Box())
        self.cell.shapes(LayerSiN).insert(hole)
        self.cell.shapes(LayerSiN).insert(cover_box_t_0)
        self.cell.shapes(LayerSiN).insert(cover_box_t_1)
        # Pins on the waveguide:
        pin_length = 200
        pin_w = a
        wg_pos = a * math.sqrt(3) / 2 * wg_dis

        t = pya.Trans(Trans.R0, -length_slab_x / 2, wg_pos)
        pin = pya.Path(
            [pya.Point(-pin_length / 2, 0),
             pya.Point(pin_length / 2, 0)], pin_w)
        pin_t = pin.transformed(t)
        self.cell.shapes(LayerPinRecN).insert(pin_t)
        text = pya.Text("pin1", t)
        shape = self.cell.shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu

        t = pya.Trans(Trans.R0, length_slab_x / 2, wg_pos)
        pin_t = pin.transformed(t)
        self.cell.shapes(LayerPinRecN).insert(pin_t)
        text = pya.Text("pin2", t)
        shape = self.cell.shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu

        #pin for drop waveguide
        t = pya.Trans(Trans.R0, length_slab_x / 2, -wg_pos)
        pin_t = pin.transformed(t)
        self.cell.shapes(LayerPinRecN).insert(pin_t)
        text = pya.Text("pin3", t)
        shape = self.cell.shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu

        # Create the device recognition layer -- make it 1 * wg_width away from the waveguides.
        points = [[-length_slab_x / 2, 0], [length_slab_x / 2, 0]]
        points = [Point(each[0], each[1]) for each in points]
        path = Path(points, length_slab_y)
        self.cell.shapes(LayerDevRecN).insert(path.simple_polygon())
Esempio n. 19
0
grating_reps = 120

grid_nx = len(grating_period)
grid_ny = len(grating_dc)
grid_dx = 50 / dbu
grid_dy = 50 / dbu

gp = grating_period[0]
gd = grating_dc[0]
for i, gr in enumerate(grating_rt):
    for j, gd2 in enumerate(grating_dc2):
        x = grid_dx * i
        y = grid_dy * j
        boundary = pya.Region()
        outer_grating = pya.Region()
        inner_grating = pya.Region()
        boundary.insert(pya.Path([pya.Point(x, y + grating_length / 2)], gr * 2, gr, gr, True))
        for k in range(grating_reps):
            outer_grating.insert(pya.Box(x + gp * (k - grating_reps / 2), y,
                                         x + gp * (k - grating_reps / 2 + (1 - gd)), y + grating_length))
            inner_grating.insert(pya.Box(x + gp * (k - grating_reps / 2), y,
                                         x + gp * (k - grating_reps / 2 + (1 - gd - gd2)), y + grating_length))
        inner_grating.__iand__(boundary)
        outer_grating.__isub__( boundary)
        cell.shapes(li).insert(inner_grating)
        cell.shapes(li).insert(outer_grating)


lv.add_missing_layers()
lv.zoom_fit()
lv.commit()
Esempio n. 20
0
    def produce(self, layout, layers, parameters, cell):
        """
    coerce parameters (make consistent)
    """
        self._layers = layers
        self.cell = cell
        self._param_values = parameters
        self.layout = layout
        shapes = self.cell.shapes

        # cell: layout cell to place the layout
        # LayerSiN: which layer to use
        # w: waveguide width
        # length units in dbu

        # fetch the parameters
        dbu = self.layout.dbu
        ly = self.layout

        LayerSi = self.silayer
        LayerSiN = ly.layer(self.silayer)
        LayerPinRecN = ly.layer(self.pinrec)
        LayerDevRecN = ly.layer(self.devrec)
        LayerTextN = ly.layer(self.textl)

        base = int(round(self.tri_base / dbu))
        height = int(round(self.tri_height / dbu))
        l = int(round(self.taper_wg_length / dbu))
        w = int(round(self.wg_width / dbu))

        pts = [
            Point(-l, w / 2),
            Point(-base, w / 2),
            Point(0, w / 2 + height),
            Point(0, -(w / 2 + height)),
            Point(-base, -w / 2),
            Point(-l, -w / 2)
        ]
        shapes(LayerSiN).insert(Polygon(pts))

        # Pins on the bus waveguide side:
        pin_length = 200
        if l < pin_length + 1:
            pin_length = int(l / 3)
            pin_length = math.ceil(pin_length / 2.) * 2
        if pin_length == 0:
            pin_length = 2

        t = Trans(Trans.R0, -l, 0)
        pin = pya.Path([Point(-pin_length / 2, 0),
                        Point(pin_length / 2, 0)], w)
        pin_t = pin.transformed(t)
        shapes(LayerPinRecN).insert(pin_t)
        text = Text("pin1", t)
        shape = shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu

        t = Trans(Trans.R0, 0, 0)
        pin_t = pin.transformed(t)
        shapes(LayerPinRecN).insert(pin_t)
        text = Text("pin2", t)
        shape = shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu

        # Create the device recognition layer -- make it 1 * wg_width away from the waveguides.
        #box1 = Box(w/2+height, -(w/2+height), -l, -1)
        #shapes(LayerDevRecN).insert(box1)

        return "wg_triangle_taper"
Esempio n. 21
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
Esempio n. 22
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)
Esempio n. 23
0
  def make_pattern(self, l, w, xpos, ypos, num):

    a1 = [ 
      pya.Point(0, 0), 
      pya.Point(100, 0), 
      pya.Point(100, l + w), 
      pya.Point(200, l + w), 
      pya.Point(200, 0), 
      pya.Point(300, 0) 
    ]

    y1 = l + w / 2 - 20
    x1 = 150
    d1 = [ pya.Point(x1, y1), pya.Point(x1, -w / 2) ]

    y2 = w / 2 + 20
    x2 = 50
    e1 = [ pya.Point(x2, y2), pya.Point(x2, l + w + w / 2) ]


    unit_cell = self.layout.create_cell("1")
    unit_cell.shapes(self.layer_index).insert(pya.Path(a1, w))
    unit_cell.shapes(self.layer_index).insert(pya.Path(d1, w))
    unit_cell.shapes(self.layer_index).insert(pya.Path(e1, w))
    unit_cell.shapes(self.layer_index).insert(pya.Box(x1 - w / 2 - 2, y1 - 2, x1 - w / 2 + 2, y1 + 2))
    unit_cell.shapes(self.layer_index).insert(pya.Box(x1 + w / 2 + 2, y1 - 2, x1 + w / 2 + 2, y1 + 2))
    unit_cell.shapes(self.layer_index).insert(pya.Box(x2 - w / 2 - 2, y2 - 2, x2 - w / 2 + 2, y2 + 2))
    unit_cell.shapes(self.layer_index).insert(pya.Box(x2 + w / 2 + 2, y2 - 2, x2 + w / 2 + 2, y2 + 2))

    nx = 45
    dx = 200
    ny = 28
    dy = 320
    ox = xpos
    oy = ypos

    trans = pya.Trans(pya.Point(ox, oy))
    ax = pya.Point(dx, 0)
    ay = pya.Point(0, dy)
    self.top.insert(pya.CellInstArray(unit_cell.cell_index(), trans, ax, ay, nx, ny))

    # Note: this is the translation of named parameters to the PCell specific parameter vector
    # pv. Since the parameter vector is built the same way always, we could simply exchange the 
    # text parameter, given we have the index.

    param = { 
      "text": "%02d-%06d" % ( l, num ), 
      "layer": pya.LayerInfo(15,99), 
      "mag": 1 
    }

    pv = []
    for p in self.pcell_decl.get_parameters():
      if p.name in param:
        pv.append(param[p.name])
      else:
        pv.append(p.default)

    # "fake PCell code" - see other thread ("Creating letters")
    text_cell = self.layout.create_cell("1T")
    self.pcell_decl.produce(self.layout, [ self.layer_index ], pv, text_cell)

    t = pya.Trans(pya.Trans.R0, -1000 + xpos, -1000 + ypos)
    self.top.insert(pya.CellInstArray(text_cell.cell_index(), t))
Esempio n. 24
0
    def produce_impl(self):

        # fetch the parameters
        dbu = self.layout.dbu
        ly = self.layout
        shapes = self.cell.shapes

        LayerSi = self.layer
        LayerSiN = ly.layer(LayerSi)
        #LayerSiSPN = ly.layer(LayerSiSP)
        LayerPinRecN = ly.layer(self.pinrec)
        LayerDevRecN = ly.layer(self.devrec)

        # Determine the period such that the waveguide length is as desired.  Slight adjustment to period
        N_boxes = int(round(self.length / self.target_period - 0.5))
        grating_period = self.length / (N_boxes) / dbu
        print("N boxes: %s, grating_period: %s" % (N_boxes, grating_period))

        # Draw the Bragg grating:
        box_width = int(round(grating_period * self.duty))

        w = self.wg_width / dbu
        half_w = w / 2
        for i in range(0, N_boxes + 1):
            x = int(round((i * grating_period - box_width / 2)))
            box1 = Box(x, -half_w, x + box_width, half_w)
            shapes(LayerSiN).insert(box1)


#    i = i + 1
#    x = int(round((i * grating_period)))
#    box1 = Box(x, -half_w, x + box_width, half_w)
#    shapes(LayerSiN).insert(box1)
        length = self.length / dbu

        # Pins on the waveguide:
        from SiEPIC._globals import PIN_LENGTH as pin_length
        #    pin_length = box_width
        t = Trans(Trans.R0, 0, 0)
        pin = Path([Point(pin_length / 2, 0), Point(-pin_length / 2, 0)], w)
        pin_t = pin.transformed(t)
        shapes(LayerPinRecN).insert(pin_t)
        text = Text("pin1", t)
        shape = shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu

        t = Trans(Trans.R0, length, 0)
        pin = Path([Point(-pin_length / 2, 0), Point(pin_length / 2, 0)], w)
        pin_t = pin.transformed(t)
        shapes(LayerPinRecN).insert(pin_t)
        text = Text("pin2", t)
        shape = shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu
        shape.text_halign = 2

        # Compact model information
        t = Trans(Trans.R0, 0, 0)
        text = Text('Lumerical_INTERCONNECT_library=Design kits/ebeam_v1.2', t)
        shape = shapes(LayerDevRecN).insert(text)
        shape.text_size = 0.1 / dbu
        t = Trans(Trans.R0, length / 10, 0)
        text = Text('Component=NO_MODEL_AVAILABLE', t)
        shape = shapes(LayerDevRecN).insert(text)
        shape.text_size = 0.1 / dbu
        t = Trans(Trans.R0, length / 9, -box_width * 2)
        text = Text \
          ('Spice_param:length=%.3fu target_period=%.3fu grating_period=%.3fu wg_width=%.3fu duty=%.3f ' %\
          (self.length, self.target_period, round(grating_period)*dbu, self.wg_width, self.duty), t )
        shape = shapes(LayerDevRecN).insert(text)
        shape.text_size = 0.1 / dbu

        # Create the device recognition layer -- make it 1 * wg_width away from the waveguides.
        points = [pya.Point(0, 0), pya.Point(length, 0)]
        path = pya.Path(points, w)
        path = pya.Path(points, w * 3)
        shapes(LayerDevRecN).insert(path.simple_polygon())
Esempio n. 25
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
Esempio n. 26
0
def wireguide_to_path(cell=None):
    from . import _globals
    from .utils import get_layout_variables

    if cell is None:
        TECHNOLOGY, lv, ly, cell = get_layout_variables()
    else:
        TECHNOLOGY, lv, _, _ = get_layout_variables()
        ly = cell.layout()

    lv.transaction("wireguide to path")

    # record objects to delete:
    to_delete = []

    wireguides = select_wireguides(cell)
    selection = []
    for obj in wireguides:
        # path from wireguide guiding shape
        wireguide = obj.inst()
        layer_list = wireguide.cell.pcell_parameter(
            'layers'
        )  # get the list of layers in the wireguide pcell (should only be one)
        original_layer = ly.layer(
            TECHNOLOGY[layer_list[0]]
        )  # convert layer to understandable type for future functions

        from ._globals import KLAYOUT_VERSION

        if KLAYOUT_VERSION > 24:
            path = wireguide.cell.pcell_parameters_by_name()['path']
        else:
            # wireguide path and width from Wireguide PCell
            path1 = wireguide.cell.pcell_parameters_by_name()['path']
            path = pya.Path()
            path.width = wireguide.cell.pcell_parameters_by_name(
            )['width'] / TECHNOLOGY['dbu']
            pts = []
            for pt in [pt1 for pt1 in (path1).each_point()]:
                if type(pt) == pya.Point:
                    # for instantiated PCell
                    pts.append(pya.Point())
                else:
                    # for wireguide from path
                    pts.append(pya.Point().from_dpoint(
                        pt * (1 / TECHNOLOGY['dbu'])))
            path.points = pts

        selection.append(pya.ObjectInstPath())
        selection[-1].layer = original_layer
        # DPath.transformed requires DTrans. wireguide.trans is a Trans object
        if KLAYOUT_VERSION > 24:
            selection[-1].shape = cell.shapes(original_layer).insert(
                path.transformed(wireguide.trans.to_dtype(TECHNOLOGY['dbu'])))
        else:
            selection[-1].shape = cell.shapes(original_layer).insert(
                path.transformed(
                    pya.Trans(wireguide.trans.disp.x, wireguide.trans.disp.y)))

        selection[-1].top = obj.top
        selection[-1].cv_index = obj.cv_index

        # deleting the instance was ok, but would leave the cell which ends up as
        # an uninstantiated top cell
        to_delete.append(obj.inst())

    # deleting instance or cell should be done outside of the for loop,
    # otherwise each deletion changes the instance pointers in KLayout's
    # internal structure
    [t.delete() for t in to_delete]

    # Clear the layout view selection, since we deleted some objects (but
    # others may still be selected):
    lv.clear_object_selection()
    # Select the newly added objects
    lv.object_selection = selection
    # Record a transaction, to enable "undo"
    lv.commit()
Esempio n. 27
0
    def produce_impl(self):
        ly = self.layout
        LayerSiN = ly.layer(self.layer)
        LayerPinRecN = ly.layer(self.pinrec)
        LayerDevRecN = ly.layer(self.devrec)

        # fetch the parameters
        dbu = self.layout.dbu
        ly = self.layout
        shapes = self.cell.shapes

        LayerSi = self.layer
        LayerSiN = ly.layer(LayerSi)
        #LayerPinRecN = ly.layer(self.pinrec)
        LayerDevRecN = ly.layer(self.devrec)

        #    print("Waveguide_Straight:")
        w = self.wg_width
        length = self.wg_length
        points = [[-length / 2, 0], [length / 2, 0]]
        path = Path([Point(-length / 2, 0), Point(length / 2, 0)], w)
        #    print(path)

        shapes(LayerSiN).insert(path.simple_polygon())

        from SiEPIC._globals import PIN_LENGTH

        # Pins on the bus waveguide side:
        pin_length = PIN_LENGTH
        if length < pin_length + 1:
            pin_length = int(length / 3)
            pin_length = math.ceil(pin_length / 2.) * 2
        if pin_length == 0:
            pin_length = 2

        t = Trans(Trans.R0, -length / 2, 0)
        pin = pya.Path([Point(pin_length / 2, 0),
                        Point(-pin_length / 2, 0)], w)
        pin_t = pin.transformed(t)
        shapes(LayerPinRecN).insert(pin_t)
        text = Text("pin1", t)
        shape = shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu

        t = Trans(Trans.R0, length / 2, 0)
        pin = pya.Path([Point(-pin_length / 2, 0),
                        Point(pin_length / 2, 0)], w)
        pin_t = pin.transformed(t)
        shapes(LayerPinRecN).insert(pin_t)
        text = Text("pin2", t)
        shape = shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu
        shape.text_halign = 2

        # Compact model information
        t = Trans(Trans.R0, 0, 0)
        text = Text('Lumerical_INTERCONNECT_library=Design kits/EBeam', t)
        shape = shapes(LayerDevRecN).insert(text)
        shape.text_size = 0.1 / dbu
        t = Trans(Trans.R0, length / 10, 0)
        text = Text('Lumerical_INTERCONNECT_component=ebeam_wg_integral_1550',
                    t)
        shape = shapes(LayerDevRecN).insert(text)
        shape.text_size = 0.1 / dbu
        t = Trans(Trans.R0, length / 9, 0)
        text = Text(
            'Spice_param:wg_width=%.3fu wg_length=%.3fu' %
            (self.wg_width * dbu, self.wg_length * dbu), t)
        shape = shapes(LayerDevRecN).insert(text)
        shape.text_size = 0.1 / dbu

        # Create the device recognition layer -- make it 1 * wg_width away from the waveguides.
        path = Path([Point(-length / 2, 0), Point(length / 2, 0)], w * 3)
        shapes(LayerDevRecN).insert(path.simple_polygon())
Esempio n. 28
0
  def produce_impl(self):
    
    # fetch the parameters
    dbu = self.layout.dbu
    ly = self.layout
    
    LayerSi = self.layer
    LayerSiN = ly.layer(self.layer)
    LayerPinRecN = ly.layer(self.pinrec)
    LayerDevRecN = ly.layer(self.devrec)
    LayerTextN = ly.layer(self.textl)
    LayerInvert=ly.layer(self.invert)
    n_vertices = int(self.vertices)
    a = self.a/dbu
    r = self.r/dbu
    n_x = int(math.ceil(self.x/2))
    n_y = int(math.ceil(self.y/2))
    positive=bool(self.positive)
    minimum_feature=self.feature_size
    apodized=bool(self.apodized)
    length_slab_x = 2*n_x*a
    
    length_slab_y = 2*(n_y-2)*a

    k = 2
    
    #function to creat polygon pts for right half of a hole in a hexagon unit cell
    
    def circle(x,y,r):
      npts = n_vertices
      theta = 2 * math.pi / npts # increment, in radians
      pts = []
      for i in range(0, npts):
        pts.append(Point.from_dpoint(pya.DPoint((x+r*math.cos(i*theta))/1, (y+r*math.sin(i*theta))/1)))
      return pts
      
    def hexagon_hole_half(a,r): 
      npts = 10    
      theta_div = math.pi/3
      theta_div_hole = math.pi/npts
      triangle_length = a/math.sqrt(3)
      pts = []
      for i in range(0,4):
        pts.append(Point.from_dpoint(pya.DPoint(triangle_length*math.cos(i*theta_div-math.pi/2), triangle_length*math.sin(i*theta_div-math.pi/2))))
      for i in range(0, npts+1):
        pts.append(Point.from_dpoint(pya.DPoint(r*math.cos(math.pi/2-i*theta_div_hole), r*math.sin(math.pi/2-i*theta_div_hole))))
      return pts
    
    def hexagon_shifthole_half(a,r): 
      npts = 10    
      theta_div = math.pi/3
      theta_div_hole = math.pi/npts
      triangle_length = a*1.235/math.sqrt(3)
      pts = []
      for i in range(0,4):
        pts.append(Point.from_dpoint(pya.DPoint(triangle_length*math.cos(i*theta_div-math.pi/2), triangle_length*math.sin(i*theta_div-math.pi/2))))
      for i in range(0, npts+1):
        pts.append(Point.from_dpoint(pya.DPoint(r*math.cos(math.pi/2-i*theta_div_hole), r*math.sin(math.pi/2-i*theta_div_hole))))
      return pts
    
    #function to creat polygon pts for right half of a hexagon unit cell      
    def hexagon_half(a): 
      theta_div = math.pi/3
      triangle_length = a/math.sqrt(3)
      pts = []
      for i in range(0,4):
        pts.append(Point.from_dpoint(pya.DPoint(triangle_length*math.cos(i*theta_div-math.pi/2), triangle_length*math.sin(i*theta_div-math.pi/2))))
      return pts      
    
    #create the right and left half of the hole and hexagon cells
    #hole_cell = pya.Region()
    #hexagon_cell = pya.Region()
    
        # Define Si slab and hole region for future subtraction
    Si_slab = pya.Region()
    Si_slab.insert(pya.Box(-length_slab_x/2+a*2, -length_slab_y/2, length_slab_x/2-a, length_slab_y/2))
    hole = pya.Region()
    hole_r = r
    
        # function to generate points to create a circle
    def circle(x,y,r):
      npts = n_vertices
      theta = 2 * math.pi / npts # increment, in radians
      pts = []
      for i in range(0, npts):
        pts.append(Point.from_dpoint(pya.DPoint((x+r*math.cos(i*theta))/1, (y+r*math.sin(i*theta))/1)))
      return pts
    import numpy  as np 
    def gaussian(x, mu, sig):
      return 1./(np.sqrt(2.*np.pi)*sig)*np.exp(-np.power((x - mu)/sig, 2.)/2) 
      
    # raster through all holes with shifts and waveguide 

    for j in range(-n_y,n_y+1):
      if j%2 == 0:
        skip=0
        apodization=0
        for i in range(-n_x,n_x+1):
          if i==0:
            continue
          if skip==0:
            skip=1
            continue
          elif skip==1:
            skip=2
            continue
          elif skip==2:
            skip=3 
            apodization=apodization+1
            continue
          elif skip==3:
            skip=1
            
            
          #radius=r/gaussian(float(i)/(2*(n_x+1)),2*(n_x+1),10)
          location=float(i)
          location=abs(location)
          #radius=r/gaussian(location/(2*(n_x+1)),2*(n_x+1),0.02)
          #radius=(((2*n_x)-abs(i+n_x+3)*r)/(2*n_x))
          radius=(float(apodization)/((n_x*2/3)-1))*r
          if radius<minimum_feature*500:
            radius=minimum_feature*500
          if apodized==False:
            radius=r
         
            #radius=minimum_feature
          hole_cell = circle(0,0,radius)
          hole_poly = pya.Polygon(hole_cell)  
          print("x1 "+str(apodization))
          hole_x = abs(i)/i*(abs(i)-0.5)*a
          hole_y = j*a*math.sqrt(3)/2
          hole_trans = pya.Trans(Trans.R0, hole_x,hole_y)
          hole_t = hole_poly.transformed(hole_trans)
          hole.insert(hole_t) 
      elif j%2 == 1:
        skipodd=0
        apodization=0
        for i in range(-n_x,n_x+1):
          if i==-n_x:
            continue
          if i==n_x:
            continue
          if skipodd==0:
            skipodd=1
            continue
          elif skipodd==1:
            skipodd=2
            apodization=apodization+1
            continue
          elif skipodd==2:
            skipodd=3
          elif skipodd==3:
            skipodd=1
                        
          #radius=(((2*n_x)-abs(i+n_x+3)*r)/(2*n_x))
          radius=(float(apodization)/((n_x*2/3)-1))*r
          if radius<minimum_feature*500:
            radius=minimum_feature*500
          if apodized==False:
            radius=r
          
            #radius=minimum_feature
          #radius=r*(float(abs(i))/(2*(n_x+1)))
          hole_cell = circle(0,0,radius)
          hole_poly = pya.Polygon(hole_cell) 
          print("x2 "+str(apodization))
          print("p "+str(n_x))
          hole_x = i*a
          hole_y = j*a*math.sqrt(3)/2
          hole_trans = pya.Trans(Trans.R0, hole_x,hole_y)
          hole_t = hole_poly.transformed(hole_trans)
          hole.insert(hole_t) 
    if positive==True:        
        phc = hole
    else:
        phc = Si_slab - hole
    self.cell.shapes(LayerSiN).insert(phc)
    
    
     #print(hole_t_0)
    box_l = a/2
         
    # Pins on the waveguide:    
    pin_length = 200
    pin_w = a
    
    t = pya.Trans(Trans.R0, -length_slab_x/2+a*2,0)
    pin = pya.Path([pya.Point(-pin_length/2, 0), pya.Point(pin_length/2, 0)], pin_w)
    pin_t = pin.transformed(t)
    self.cell.shapes(LayerPinRecN).insert(pin_t)
    text = pya.Text ("pin1", t)
    shape = self.cell.shapes(LayerPinRecN).insert(text)
    shape.text_size = 0.4/dbu
    
    # Create the device recognition layer -- make it 1 * wg_width away from the waveguides.
    points = [[-length_slab_x/2+a*2,0], [length_slab_x/2-a, 0]]
    points = [Point(each[0], each[1]) for each in points]
    path = Path(points, length_slab_y)   
    self.cell.shapes(LayerDevRecN).insert(path.simple_polygon())
    
    if positive==True: 
        self.cell.shapes(LayerInvert).insert(path.simple_polygon())
    
    return
    
    hole = pya.Region()
    
    hole_cell_pts = hexagon_hole_half(a,r)
    hexagon_pts = hexagon_half(a)
    hole_shiftcell_pts = hexagon_shifthole_half(a,r)
    hole_cell_poly_0 = pya.Polygon(hole_cell_pts)
    hexagon_cell_poly_0 = pya.Polygon(hexagon_pts)
    hole_shiftcell_poly_0 = pya.Polygon(hole_shiftcell_pts)

    hole_trans = pya.Trans(pya.Trans.R180)
    hole_cell_poly_1 = hole_cell_poly_0.transformed(hole_trans)
    hexagon_cell_poly_1 = hexagon_cell_poly_0.transformed(hole_trans)    
    hole_shiftcell_poly_1 = hole_shiftcell_poly_0.transformed(hole_trans)
    skip=1
    skip2=0   
    #create the photonic crystal with shifts and waveguides
    for j in range(-y+1,y):
      if j%2 == 0:
        for i in range(-x,x+1):
          
          #waveguide     
          if (j == k and i > 3):
            hole_x = abs(i)/i*(abs(i)-0.5)*a
            hole_y = j*a*math.sqrt(3)/2
            hole_trans = pya.Trans(Trans.R0, hole_x,hole_y)
            hole_t_0 = hole_cell_poly_0.transformed(hole_trans)
            hole_t_1 = hole_cell_poly_1.transformed(hole_trans)            
            hole.insert(hole_t_0)
            hole.insert(hole_t_1)
          #filling the edges with half cell
                
                      
          elif i!=0:
            hole_x = abs(i)/i*(abs(i)-0.5)*a
            hole_y = j*a*math.sqrt(3)/2
            hole_trans = pya.Trans(Trans.R0, hole_x,hole_y)
            hole_t_0 = hole_cell_poly_0.transformed(hole_trans)
            hole_t_1 = hole_cell_poly_1.transformed(hole_trans)
            hole.insert(hole_t_0)  
            hole.insert(hole_t_1)
      elif j%2 == 1:
        for i in range(-x,x+1):
          if skip==0 and i%3==0:
            skip=1
            continue
          if skip==1:
            skip=2
            continue 
          if skip==2:
            skip=0
            
          if i== -x:
            hole_x = abs(i)/i*(abs(i)-0.5)*a
            hole_y = j*a*math.sqrt(3)/2
            hole_trans = pya.Trans(Trans.R0, hole_x,hole_y)
            hole_t_1 = hexagon_cell_poly_1.transformed(hole_trans)
            hole.insert(hole_t_1)
          if i== x:
            hole_x = abs(i)/i*(abs(i)-0.5)*a
            hole_y = j*a*math.sqrt(3)/2
            hole_trans = pya.Trans(Trans.R0, hole_x,hole_y)
            hole_t_0 = hexagon_cell_poly_0.transformed(hole_trans)
            hole.insert(hole_t_0)
          #waveguide
          if (j == k and i > 3):
            hole_x =i*a
            hole_y =j*a*math.sqrt(3)/2
            hole_trans = pya.Trans(Trans.R0, hole_x,hole_y)
            hole_t_0 = hexagon_cell_poly_0.transformed(hole_trans)
            hole_t_1 = hexagon_cell_poly_1.transformed(hole_trans)
            hole.insert(hole_t_0)
            hole.insert(hole_t_1)
          #filling the edges with half cell
          elif i in (-x,x):
            hole_x =i*a
            hole_y =j*a*math.sqrt(3)/2
            hole_trans = pya.Trans(Trans.R0, hole_x,hole_y) 
            if i == -x:           
              hole_t = hole_cell_poly_0.transformed(hole_trans)
            else:
              hole_t = hole_cell_poly_1.transformed(hole_trans)
            hole.insert(hole_t)               
          
          else:  
            hole_x = i*a
            hole_y = j*a*math.sqrt(3)/2
            hole_trans = pya.Trans(Trans.R0, hole_x,hole_y)
            hole_t_0 = hole_cell_poly_0.transformed(hole_trans)
            hole_t_1 = hole_cell_poly_1.transformed(hole_trans)
            hole.insert(hole_t_0)  
            hole.insert(hole_t_1)
    
    #print(hole_t_0)
    box_l = a/2
    
    cover_box = pya.Box(-length_slab_x/2, -a/2, length_slab_x/2, a/2) 
    box_y = y*a*math.sqrt(3)/2  
    cover_box_trans_0 = pya.Trans(Trans.R0, 0,box_y)
    cover_box_trans_1 = pya.Trans(Trans.R0, 0,-box_y)
    cover_box_t_0 = cover_box.transformed(cover_box_trans_0) 
    cover_box_t_1 = cover_box.transformed(cover_box_trans_1)     
    #hole.insert(pya.Box())    
    self.cell.shapes(LayerSiN).insert(hole)
    self.cell.shapes(LayerSiN).insert(cover_box_t_0)
    self.cell.shapes(LayerSiN).insert(cover_box_t_1)      
    # Pins on the waveguide:    
    pin_length = 200
    pin_w = a
    
    t = pya.Trans(Trans.R0, -length_slab_x/2,0)
    pin = pya.Path([pya.Point(-pin_length/2, 0), pya.Point(pin_length/2, 0)], pin_w)
    pin_t = pin.transformed(t)
    self.cell.shapes(LayerPinRecN).insert(pin_t)
    text = pya.Text ("pin1", t)
    shape = self.cell.shapes(LayerPinRecN).insert(text)
    shape.text_size = 0.4/dbu

    # Create the device recognition layer -- make it 1 * wg_width away from the waveguides.
    points = [[-length_slab_x/2,0], [length_slab_x/2, 0]]
    points = [Point(each[0], each[1]) for each in points]
    path = Path(points, length_slab_y)   
    self.cell.shapes(LayerDevRecN).insert(path.simple_polygon())
      
Esempio n. 29
0
    def produce_impl(self):

        # fetch the parameters
        dbu = self.layout.dbu
        ly = self.layout

        LayerSi = self.layer
        LayerSiN = ly.layer(self.layer)
        LayerPinRecN = ly.layer(self.pinrec)
        LayerDevRecN = ly.layer(self.devrec)
        LayerTextN = ly.layer(self.textl)

        # Fetch all the parameters:
        a = self.a / dbu
        r = self.r / dbu
        wg_dis = self.wg_dis + 1
        n_vertices = self.n_vertices
        n_bus = self.n_bus
        n = int(math.ceil(self.n / 2))
        Sx = [self.S1x, self.S2x, self.S3x, self.S4x, self.S5x]
        Sy = [self.S1y, 0, self.S2y]
        if n_bus == 1:
            Sx = [0, 0, 0, 0, 0]
            Sy = [0, 0, 0]

        if wg_dis % 2 == 0:
            length_slab_x = (2 * n - 1) * a
        else:
            length_slab_x = 2 * n * a

        length_slab_y = 2 * (wg_dis + 15) * a * math.sqrt(3) / 2

        n_x = n
        n_y = wg_dis + 10

        # Define Si slab and hole region for future subtraction
        Si_slab = pya.Region()
        Si_slab.insert(
            pya.Box(-length_slab_x / 2, -length_slab_y / 2, length_slab_x / 2,
                    length_slab_y / 2))
        hole = pya.Region()
        hole_r = r

        # function to generate points to create a circle
        def circle(x, y, r):
            npts = n_vertices
            theta = 2 * math.pi / npts  # increment, in radians
            pts = []
            for i in range(0, npts):
                pts.append(
                    Point.from_dpoint(
                        pya.DPoint((x + r * math.cos(i * theta)) / 1,
                                   (y + r * math.sin(i * theta)) / 1)))
            return pts

        # raster through all holes with shifts and waveguide

        hole_cell = circle(0, 0, hole_r)
        hole_poly = pya.Polygon(hole_cell)

        for j in range(-n_y, n_y + 1):
            if j % 2 == 0 and j != wg_dis:
                for i in range(-n_x, n_x + 1):
                    if j == -wg_dis and i > 3 and n_bus == 2:
                        None
                    elif j == 0 and i in (1, -1, 2, -2, 3, -3, 4, -4, 5, -5):
                        hole_x = abs(i) / i * (abs(i) - 0.5 +
                                               Sx[abs(i) - 1]) * a
                        hole_y = 0
                        hole_trans = pya.Trans(Trans.R0, hole_x, hole_y)
                        hole_t = hole_poly.transformed(hole_trans)
                        hole.insert(hole_t)
                    elif i != 0:
                        hole_x = abs(i) / i * (abs(i) - 0.5) * a
                        hole_y = j * a * math.sqrt(3) / 2
                        hole_trans = pya.Trans(Trans.R0, hole_x, hole_y)
                        hole_t = hole_poly.transformed(hole_trans)
                        hole.insert(hole_t)
            elif j % 2 == 1 and j != wg_dis:
                for i in range(-n_x, n_x + 1):
                    if j == -wg_dis and i > 3 and n_bus == 2:
                        None
                    elif i == 0 and j in (1, -1, 3, -3):
                        hole_x = 0
                        hole_y = j * a * (math.sqrt(3) /
                                          2) + abs(j) / j * a * Sy[abs(j) - 1]
                        hole_trans = pya.Trans(Trans.R0, hole_x, hole_y)
                        hole_t = hole_poly.transformed(hole_trans)
                        hole.insert(hole_t)
                    else:
                        hole_x = i * a
                        hole_y = j * a * math.sqrt(3) / 2
                        hole_trans = pya.Trans(Trans.R0, hole_x, hole_y)
                        hole_t = hole_poly.transformed(hole_trans)
                        hole.insert(hole_t)

        phc = Si_slab - hole
        self.cell.shapes(LayerSiN).insert(phc)

        # Pins on the waveguide:
        pin_length = 200
        pin_w = a
        wg_pos = a * math.sqrt(3) / 2 * wg_dis

        t = pya.Trans(Trans.R0, -length_slab_x / 2, wg_pos)
        pin = pya.Path(
            [pya.Point(pin_length / 2, 0),
             pya.Point(-pin_length / 2, 0)], pin_w)
        pin_t = pin.transformed(t)
        self.cell.shapes(LayerPinRecN).insert(pin_t)
        text = pya.Text("pin1", t)
        shape = self.cell.shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu

        t = pya.Trans(Trans.R0, length_slab_x / 2, wg_pos)
        pin = pya.Path(
            [pya.Point(-pin_length / 2, 0),
             pya.Point(pin_length / 2, 0)], pin_w)
        pin_t = pin.transformed(t)
        self.cell.shapes(LayerPinRecN).insert(pin_t)
        text = pya.Text("pin2", t)
        shape = self.cell.shapes(LayerPinRecN).insert(text)
        shape.text_size = 0.4 / dbu

        #pin for drop waveguide
        if n_bus == 2:
            t = pya.Trans(Trans.R0, length_slab_x / 2, -wg_pos)
            pin_t = pin.transformed(t)
            self.cell.shapes(LayerPinRecN).insert(pin_t)
            text = pya.Text("pin3", t)
            shape = self.cell.shapes(LayerPinRecN).insert(text)
            shape.text_size = 0.4 / dbu

        # Create the device recognition layer -- make it 1 * wg_width away from the waveguides.
        points = [[-length_slab_x / 2, 0], [length_slab_x / 2, 0]]
        points = [Point(each[0], each[1]) for each in points]
        path = Path(points, length_slab_y)
        self.cell.shapes(LayerDevRecN).insert(path.simple_polygon())
Esempio n. 30
0
  def test_3_DTrans(self):

    c = pya.DCplxTrans( 5.0, -7.0 )
    self.assertEqual( str(c), "r0 *1 5,-7" )

    c = pya.DCplxTrans( pya.DCplxTrans.M135 )
    self.assertEqual( str(c), "m135 *1 0,0" )
    self.assertEqual( c.is_unity(), False )
    self.assertEqual( c.is_ortho(), True )
    self.assertEqual( c.is_mag(), False )
    self.assertEqual( c.is_mirror(), True )
    self.assertEqual( c.rot(), pya.DCplxTrans.M135.rot() )
    self.assertEqual( str(c.s_trans()), "m135 0,0" )
    self.assertAlmostEqual( c.angle, 270 )

    self.assertEqual( str(c.trans( pya.Edge(0, 1, 2, 3) )), "(-1,0;-3,-2)" )
    self.assertEqual( str(( c * pya.Edge(0, 1, 2, 3) )), "(-1,0;-3,-2)" )
    self.assertEqual( str(c.trans( pya.Box(0, 1, 2, 3) )), "(-3,-2;-1,0)" )
    self.assertEqual( str(( c * pya.Box(0, 1, 2, 3) )), "(-3,-2;-1,0)" )
    self.assertEqual( str(c.trans( pya.Text("text", pya.Vector(0, 1)) )), "('text',m135 -1,0)" )
    self.assertEqual( str(( c * pya.Text("text", pya.Vector(0, 1)) )), "('text',m135 -1,0)" )
    self.assertEqual( str(c.trans( pya.Polygon( [ pya.Point(0, 1), pya.Point(2, -3), pya.Point(4, 5) ] ) )), "(-5,-4;-1,0;3,-2)" )
    self.assertEqual( str(( c * pya.Polygon( [ pya.Point(0, 1), pya.Point(2, -3), pya.Point(4, 5) ] ) )), "(-5,-4;-1,0;3,-2)" )
    self.assertEqual( str(c.trans( pya.Path( [ pya.Point(0, 1), pya.Point(2, 3) ], 10 ) )), "(-1,0;-3,-2) w=10 bx=0 ex=0 r=false" )
    self.assertEqual( str(( c * pya.Path( [ pya.Point(0, 1), pya.Point(2, 3) ], 10 ) )), "(-1,0;-3,-2) w=10 bx=0 ex=0 r=false" )

    c = pya.DCplxTrans.from_itrans( pya.CplxTrans.M135 )
    self.assertEqual( str(c), "m135 *1 0,0" )

    c = pya.DCplxTrans( 1.5 )
    self.assertEqual( str(c), "r0 *1.5 0,0" )
    self.assertEqual( c.is_unity(), False )
    self.assertEqual( c.is_ortho(), True )
    self.assertEqual( c.is_mag(), True )
    self.assertEqual( c.is_mirror(), False )
    self.assertEqual( c.rot(), pya.DCplxTrans.R0.rot() )
    self.assertEqual( str(c.s_trans()), "r0 0,0" )
    self.assertAlmostEqual( c.angle, 0 )

    c = pya.DCplxTrans( 0.75, 45, True, 2.5, -12.5 )
    self.assertEqual( str(c), "m22.5 *0.75 2.5,-12.5" )
    c = pya.DCplxTrans( 0.75, 45, True, pya.DPoint( 2.5, -12.5 ) )
    self.assertEqual( str(c), "m22.5 *0.75 2.5,-12.5" )
    self.assertEqual( c.is_unity(), False )
    self.assertEqual( c.is_ortho(), False )
    self.assertEqual( c.is_mag(), True )
    self.assertEqual( c.rot(), pya.DCplxTrans.M0.rot() )
    self.assertEqual( str(c.s_trans()), "m0 2.5,-12.5" )
    self.assertAlmostEqual( c.angle, 45 )

    self.assertEqual( str(c.ctrans( 5 )), "3.75" )
    self.assertEqual( str(c.trans( pya.DPoint( 12, 16 ) )), "17.3492424049,-14.6213203436" )

    self.assertEqual( str(pya.DCplxTrans()), "r0 *1 0,0" )
    self.assertEqual( pya.DCplxTrans().is_unity(), True )
    self.assertEqual( (c * c.inverted()).is_unity(), True )

    c.mirror = False
    self.assertEqual( str(c), "r45 *0.75 2.5,-12.5" )
    c.mag = 1.5
    self.assertEqual( str(c), "r45 *1.5 2.5,-12.5" )
    c.disp = pya.DPoint( -1.0, 5.5 )
    self.assertEqual( str(c), "r45 *1.5 -1,5.5" )
    self.assertEqual( c.mag, 1.5 )
    c.angle = 60
    self.assertEqual( str(c), "r60 *1.5 -1,5.5" )
    self.assertEqual( ("%g" % c.angle), "60" )

    # Constructor variations
    self.assertEqual( str(pya.ICplxTrans()), "r0 *1 0,0" )
    self.assertEqual( str(pya.ICplxTrans(1.5)), "r0 *1.5 0,0" )
    self.assertEqual( str(pya.ICplxTrans(pya.Trans(1, False, 10, 20), 1.5)), "r90 *1.5 10,20" )
    self.assertEqual( str(pya.ICplxTrans(pya.Trans(1, False, 10, 20))), "r90 *1 10,20" )
    self.assertEqual( str(pya.ICplxTrans(1.5, 80, True, pya.Vector(100, 200))), "m40 *1.5 100,200" )
    self.assertEqual( str(pya.ICplxTrans(1.5, 80, True, 100, 200)), "m40 *1.5 100,200" )
    self.assertEqual( str(pya.ICplxTrans(pya.Vector(100, 200))), "r0 *1 100,200" )
    self.assertEqual( str(pya.ICplxTrans(100, 200)), "r0 *1 100,200" )
    self.assertEqual( str(pya.ICplxTrans(pya.ICplxTrans(100, 200))), "r0 *1 100,200" )
    self.assertEqual( str(pya.ICplxTrans(pya.ICplxTrans(100, 200), 1.5)), "r0 *1.5 150,300" )
    self.assertEqual( str(pya.ICplxTrans(pya.ICplxTrans(100, 200), 1.5, pya.Vector(10, 20))), "r0 *1.5 160,320" )
    self.assertEqual( str(pya.ICplxTrans(pya.ICplxTrans(100, 200), 1.5, 10, 20)), "r0 *1.5 160,320" )

    self.assertEqual( str(pya.DCplxTrans()), "r0 *1 0,0" )
    self.assertEqual( str(pya.DCplxTrans(1.5)), "r0 *1.5 0,0" )
    self.assertEqual( str(pya.DCplxTrans(pya.DTrans(1, False, 0.01, 0.02), 1.5)), "r90 *1.5 0.01,0.02" )
    self.assertEqual( str(pya.DCplxTrans(pya.DTrans(1, False, 0.01, 0.02))), "r90 *1 0.01,0.02" )
    self.assertEqual( str(pya.DCplxTrans(1.5, 80, True, pya.DVector(0.1, 0.2))), "m40 *1.5 0.1,0.2" )
    self.assertEqual( str(pya.DCplxTrans(1.5, 80, True, 0.1, 0.2)), "m40 *1.5 0.1,0.2" )
    self.assertEqual( str(pya.DCplxTrans(pya.DVector(0.1, 0.2))), "r0 *1 0.1,0.2" )
    self.assertEqual( str(pya.DCplxTrans(0.1, 0.2)), "r0 *1 0.1,0.2" )
    self.assertEqual( str(pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2))), "r0 *1 0.1,0.2" )
    self.assertEqual( str(pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2), 1.5)), "r0 *1.5 0.15,0.3" )
    self.assertEqual( str(pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2), 1.5, pya.DVector(0.01, 0.02))), "r0 *1.5 0.16,0.32" )
    self.assertEqual( str(pya.DCplxTrans(pya.DCplxTrans(0.1, 0.2), 1.5, 0.01, 0.02)), "r0 *1.5 0.16,0.32" )