def produce_impl(self): # This is the main part of the implementation: create the layout from math import pi, cos, sin from SiEPIC.utils import arc_wg, arc_wg_xy from SiEPIC._globals import PIN_LENGTH # fetch the parameters dbu = self.layout.dbu ly = self.layout shapes = self.cell.shapes LayerSiN = ly.layer(self.silayer) LayerPinRecN = ly.layer(self.pinrec) LayerDevRecN = ly.layer(self.devrec) TextLayerN = ly.layer(self.textl) w = int(round(self.w/dbu)) r = int(round(self.r/dbu)) g = int(round(self.g/dbu)) Lc = int(round(self.Lc/dbu)) # draw the half-circle x = 0 y = r+w+g self.cell.shapes(LayerSiN).insert(arc_wg_xy(x-Lc/2, y, r, w, 180, 270)) self.cell.shapes(LayerSiN).insert(arc_wg_xy(x+Lc/2, y, r, w, 270, 360)) # Pins on the top side: pin = Path([Point(-r-Lc/2, y-PIN_LENGTH/2), Point(-r-Lc/2, y+PIN_LENGTH/2)], w) shapes(LayerPinRecN).insert(pin) t = Trans(Trans.R0, -r-Lc/2, y) text = Text ("pin2", t) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4/dbu pin = Path([Point(r+Lc/2, y-PIN_LENGTH/2), Point(r+Lc/2, y+PIN_LENGTH/2)], w) shapes(LayerPinRecN).insert(pin) t = Trans(Trans.R0, r+Lc/2, y) text = Text ("pin4", t) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4/dbu if Lc > 0: wg1 = Box(-Lc/2, -w/2+w+g, Lc/2, w/2+w+g) shapes(LayerSiN).insert(wg1) # Create the waveguide wg1 = Box(-r-w/2-w-Lc/2, -w/2, r+w/2+w+Lc/2, w/2) shapes(LayerSiN).insert(wg1) # Pins on the bus waveguide side: pin = Path([Point(-r-w/2-w+PIN_LENGTH/2-Lc/2, 0), Point(-r-w/2-w-PIN_LENGTH/2-Lc/2, 0)], w) shapes(LayerPinRecN).insert(pin) t = Trans(Trans.R0, -r-w/2-w-Lc/2, 0) text = Text ("pin1", t) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4/dbu pin = Path([Point(r+w/2+w-PIN_LENGTH/2+Lc/2, 0), Point(r+w/2+w+PIN_LENGTH/2+Lc/2, 0)], w) shapes(LayerPinRecN).insert(pin) t = Trans(Trans.R0, r+w/2+w+Lc/2, 0) text = Text ("pin3", t) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4/dbu # Merge all the waveguide shapes, to avoid any small gaps layer_temp = self.layout.layer(LayerInfo(913, 0)) shapes_temp = self.cell.shapes(layer_temp) ShapeProcessor().merge(self.layout,self.cell,LayerSiN,shapes_temp,True,0,True,True) self.cell.shapes(LayerSiN).clear() shapes_SiN = self.cell.shapes(LayerSiN) ShapeProcessor().merge(self.layout,self.cell,layer_temp, shapes_SiN,True,0,True,True) self.cell.shapes(layer_temp).clear() # Create the device recognition layer -- make it 1 * wg_width away from the waveguides. dev = Box(-r-w/2-w-Lc/2, -w/2-w, r+w/2+w+Lc/2, y ) shapes(LayerDevRecN).insert(dev) # Compact model information t = Trans(Trans.R0, -r, 0) text = Text ("Lumerical_INTERCONNECT_library=Design kits/ebeam", t) shape = shapes(LayerDevRecN).insert(text) shape.text_size = self.r*0.03/dbu t = Trans(Trans.R0, -r, r/4) text = Text ('Component=ebeam_dc_halfring_straight', t) shape = shapes(LayerDevRecN).insert(text) shape.text_size = self.r*0.03/dbu t = Trans(Trans.R0, -r, r/2) text = Text ('Spice_param:wg_width=%.3g gap=%.3g radius=%.3g Lc=%.3g orthogonal_identifier=%s'% (self.w*1e-6,self.g*1e-6,self.r*1e-6,self.Lc*1e-6, self.orthogonal_identifier), t) shape = shapes(LayerDevRecN).insert(text) shape.text_size = self.r*0.03/dbu print("Done drawing the layout for - ebeam_dc_halfring_straight: %.3f-%g" % ( self.r, self.g) )
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) # draw spiral from math import pi, cos, sin, log, sqrt # Archimedes spiral # r = b + a * theta b = self.min_radius spacing = self.wg_spacing + self.wg_width a = 2 * spacing / (2 * pi) # area, length, turn tracking for spiral area = 0 spiral_length = 0 turn = -1 from SiEPIC.utils import points_per_circle, arc_wg_xy while spiral_length < self.length: turn += 1 # Spiral #1 pts = [] # local radius: r = 2 * b + a * turn * 2 * pi - self.wg_width / 2 # number of points per circle: npoints = int(points_per_circle(r)) # increment, in radians, for each point: da = 2 * pi / npoints # draw the inside edge of spiral for i in range(0, npoints + 1): t = i * da xa = (a * t + r) * cos(t) ya = (a * t + r) * sin(t) pts.append(Point.from_dpoint(DPoint(xa / dbu, ya / dbu))) # draw the outside edge of spiral r = 2 * b + a * turn * 2 * pi + self.wg_width / 2 npoints = int(points_per_circle(r)) da = 2 * pi / npoints for i in range(npoints, -1, -1): t = i * da xa = (a * t + r) * cos(t) ya = (a * t + r) * sin(t) pts.append(Point.from_dpoint(DPoint(xa / dbu, ya / dbu))) polygon = Polygon(pts) area += polygon.area() shapes(LayerSiN).insert(polygon) # Spiral #2 pts = [] # local radius: r = 2 * b + a * turn * 2 * pi - self.wg_width / 2 - spacing # number of points per circle: npoints = int(points_per_circle(r)) # increment, in radians, for each point: da = 2 * pi / npoints # draw the inside edge of spiral for i in range(0, npoints + 1): t = i * da + pi xa = (a * t + r) * cos(t) ya = (a * t + r) * sin(t) pts.append(Point.from_dpoint(DPoint(xa / dbu, ya / dbu))) # draw the outside edge of spiral r = 2 * b + a * turn * 2 * pi + self.wg_width / 2 - spacing npoints = int(points_per_circle(r)) da = 2 * pi / npoints for i in range(npoints, -1, -1): t = i * da + pi xa = (a * t + r) * cos(t) ya = (a * t + r) * sin(t) pts.append(Point.from_dpoint(DPoint(xa / dbu, ya / dbu))) polygon = Polygon(pts) area += polygon.area() shapes(LayerSiN).insert(polygon) # waveguide length: spiral_length = area / self.wg_width * dbu * dbu + 2 * pi * self.min_radius if self.spiral_ports: # Spiral #1 extra 1/2 arm turn = turn + 1 pts = [] # local radius: r = 2 * b + a * turn * 2 * pi - self.wg_width / 2 # number of points per circle: npoints = int(points_per_circle(r)) # increment, in radians, for each point: da = pi / npoints # draw the inside edge of spiral for i in range(0, npoints + 1): t = i * da xa = (a * t + r) * cos(t) ya = (a * t + r) * sin(t) pts.append(Point.from_dpoint(DPoint(xa / dbu, ya / dbu))) # draw the outside edge of spiral r = 2 * b + a * turn * 2 * pi + self.wg_width / 2 npoints = int(points_per_circle(r)) da = pi / npoints for i in range(npoints, -1, -1): t = i * da xa = (a * t + r) * cos(t) ya = (a * t + r) * sin(t) pts.append(Point.from_dpoint(DPoint(xa / dbu, ya / dbu))) polygon = Polygon(pts) area += polygon.area() shapes(LayerSiN).insert(polygon) turn = turn - 1 # waveguide length: spiral_length = area / self.wg_width * dbu * dbu + 2 * pi * self.min_radius # Centre S-shape connecting waveguide #layout_arc_wg_dbu(self.cell, LayerSiN, -b/dbu, 0, b/dbu, self.wg_width/dbu, 0, 180) self.cell.shapes(LayerSiN).insert( arc_wg_xy(-b / dbu, 0, b / dbu, self.wg_width / dbu, 0, 180)) #layout_arc_wg_dbu(self.cell, LayerSiN, b/dbu, 0, b/dbu, self.wg_width/dbu, 180, 0) self.cell.shapes(LayerSiN).insert( arc_wg_xy(b / dbu, 0, b / dbu, self.wg_width / dbu, 180, 0)) print("spiral length: %s microns" % spiral_length) # Pins on the waveguide: from SiEPIC._globals import PIN_LENGTH as pin_length x = -(2 * b + a * (turn + 1) * 2 * pi) / dbu w = self.wg_width / dbu t = Trans(Trans.R0, x, 0) pin = Path([Point(0, pin_length / 2), Point(0, -pin_length / 2)], 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 if self.spiral_ports: x = -(2 * b + a * (turn + 1.5) * 2 * pi) / dbu else: x = (2 * b + a * (turn + 1) * 2 * pi) / dbu t = Trans(Trans.R0, x, 0) pin = Path([Point(0, pin_length / 2), Point(0, -pin_length / 2)], 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 # Compact model information t = Trans(Trans.R0, -abs(x), 0) text = Text('Length=%.3fu' % spiral_length, t) shape = shapes(LayerDevRecN).insert(text) shape.text_size = abs(x) / 8 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, 0, w * 2) text = Text('Component=ebeam_wg_strip_1550', t) shape = shapes(LayerDevRecN).insert(text) shape.text_size = 0.1 / dbu t = Trans(Trans.R0, 0, -w * 2) text = Text \ ('Spice_param:wg_length=%.3fu wg_width=%.3fu min_radius=%.3fu wg_spacing=%.3fu' %\ (spiral_length, self.wg_width, (self.min_radius), self.wg_spacing), 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. x = abs(x) npoints = int(points_per_circle(x) / 10) da = 2 * pi / npoints # increment, in radians r = x + 2 * self.wg_width / dbu pts = [] for i in range(0, npoints + 1): pts.append( Point.from_dpoint(DPoint(r * cos(i * da), r * sin(i * da)))) shapes(LayerDevRecN).insert(Polygon(pts)) print("spiral done.")
def produce_impl(self): # This is the main part of the implementation: create the layout from math import pi, cos, sin from SiEPIC._globals import PIN_LENGTH as pin_length from SiEPIC.utils import arc_wg_xy # fetch the parameters dbu = self.layout.dbu ly = self.layout shapes = self.cell.shapes LayerSi = self.silayer LayerSiN = ly.layer(LayerSi) LayerPinRecN = ly.layer(self.pinrec) LayerDevRecN = ly.layer(self.devrec) TextLayerN = ly.layer(self.textl) w = int(round( self.w/dbu)) r1 = int(round( self.r1/dbu)) r2 = int(round( self.r2/dbu)) g = int(round( self.g/dbu)) Lc = int(round( self.Lc/dbu)) # draw the half-circle x = 0 y = r1+r2+g+w self.cell.shapes(LayerSiN).insert(arc_wg_xy(x-Lc/2, y, r2, w, 180, 270)) self.cell.shapes(LayerSiN).insert(arc_wg_xy(x+Lc/2, y, r2, w, 270, 360)) # Create the pins, as short paths: # Pins on the top side: pin = Path([Point(-r2-Lc/2, y-pin_length/2), Point(-r2-Lc/2, y+pin_length/2)], w) shapes(LayerPinRecN).insert(pin) t = Trans(Trans.R0, -r2-Lc/2, y) text = Text ("pin2", t) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4/dbu pin = Path([Point(r2+Lc/2, y-pin_length/2), Point(r2+Lc/2, y+pin_length/2)], w) shapes(LayerPinRecN).insert(pin) t = Trans(Trans.R0, r2+Lc/2, y) text = Text ("pin4", t) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4/dbu if Lc > 0: wg1 = Box(-Lc/2,w + w/2+ g+ r1 , Lc/2, w/2 + g+ r1) shapes(LayerSiN).insert(wg1) y = 0 self.cell.shapes(LayerSiN).insert(arc_wg_xy(x-Lc/2, y, r1, w, 90, 180)) self.cell.shapes(LayerSiN).insert(arc_wg_xy(x+Lc/2, y, r1, w, 0, 90)) # Pins on the lower side: pin = Path([Point(-r1-Lc/2, y+pin_length/2), Point(-r1-Lc/2, y-pin_length/2)], w) shapes(LayerPinRecN).insert(pin) t = Trans(Trans.R0, -r1-Lc/2, y) text = Text ("pin1", t) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4/dbu pin = Path([Point(r1+Lc/2, y+pin_length/2), Point(r1+Lc/2, y-pin_length/2)], w) shapes(LayerPinRecN).insert(pin) t = Trans(Trans.R0, r1+Lc/2, y) text = Text ("pin3", t) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4/dbu if Lc > 0: wg1 = Box(-Lc/2, r1 -w/2, Lc/2, w/2 + r1) shapes(LayerSiN).insert(wg1) if(r1>r2): r = r1 else: r = r2 # Create the device recognition layer -- make it 1 * wg_width away from the waveguides. dev = Box(-r-w/2-w-Lc/2,r1+r2+g+w, r+w/2+w+Lc/2, y ) shapes(LayerDevRecN).insert(dev) # Compact model information t = Trans(Trans.R0, ((r1+r2)/2)/4, 0) text = Text ("Lumerical_INTERCONNECT_library=Design kits/ebeam_v1.2", t) shape = shapes(LayerDevRecN).insert(text) shape.text_size = r*0.017 t = Trans(Trans.R0, ((r1+r2)/2)/4, ((r1+r2)/2)/4) text = Text ('Component=ebeam_dc_seriesrings', t) shape = shapes(LayerDevRecN).insert(text) shape.text_size = r*0.017 t = Trans(Trans.R0, ((r1+r2)/2)/4, ((r1+r2)/2)/2) # text = Text ('Spice_param:wg_width=%.3fu gap="%s" radius="%s"'% ( w, g,int( r)), t) text = Text ('Spice_param:wg_width=%.3fu gap=%.3fu radius1=%.3fu radius2=%.3fu'% ( self.w, self.g,int( self.r1), int(self.r2)), t) shape = shapes(LayerDevRecN).insert(text) shape.text_size = r*0.017 print("Done drawing the layout for - DirectionalCoupler_SeriesRings: %.3f-%.3f-%g" % ( self.r1, self.r2, self.g) )
def produce_impl(self): # This is the main part of the implementation: create the layout from math import pi, cos, sin from SiEPIC.utils import arc_wg, arc_wg_xy from SiEPIC._globals import PIN_LENGTH # fetch the parameters dbu = self.layout.dbu ly = self.layout shapes = self.cell.shapes LayerSiN = ly.layer(self.silayer) LayerPinRecN = ly.layer(self.pinrec) LayerDevRecN = ly.layer(self.devrec) TextLayerN = ly.layer(self.textl) w = int(round(self.w / dbu)) r = int(round(self.r / dbu)) g = int(round(self.g / dbu)) Lc = int(round(self.Lc / dbu)) # draw the half-circle x = 0 y = r + w + g self.cell.shapes(LayerSiN).insert( arc_wg_xy(x - Lc / 2, y, r, w, 180, 270)) self.cell.shapes(LayerSiN).insert( arc_wg_xy(x + Lc / 2, y, r, w, 270, 360)) # Pins on the top side: pin = Path([ Point(-r - Lc / 2, y - PIN_LENGTH / 2), Point(-r - Lc / 2, y + PIN_LENGTH / 2) ], w) shapes(LayerPinRecN).insert(pin) t = Trans(Trans.R0, -r - Lc / 2, y) text = Text("pin2", t) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu pin = Path([ Point(r + Lc / 2, y - PIN_LENGTH / 2), Point(r + Lc / 2, y + PIN_LENGTH / 2) ], w) shapes(LayerPinRecN).insert(pin) t = Trans(Trans.R0, r + Lc / 2, y) text = Text("pin4", t) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu if Lc > 0: wg1 = Box(-Lc / 2, -w / 2 + w + g, Lc / 2, w / 2 + w + g) shapes(LayerSiN).insert(wg1) # Create the waveguide if Lc > 0: wg1 = Box(-Lc / 2, -w / 2, Lc / 2, w / 2) shapes(LayerSiN).insert(wg1) dc_angle = 30.0 self.cell.shapes(LayerSiN).insert( arc_wg_xy(Lc / 2, -r, r, w, 90 - dc_angle, 90)) self.cell.shapes(LayerSiN).insert( arc_wg_xy(-Lc / 2, -r, r, w, 90, 90 + dc_angle)) y_bottom = round(-2 * (1 - cos(dc_angle / 180.0 * pi)) * r) x_bottom = round(2 * sin(dc_angle / 180.0 * pi) * r) t = Trans(Trans.R0, -x_bottom - Lc / 2, y_bottom + r) self.cell.shapes(LayerSiN).insert( arc_wg(r, w, -90, -90 + dc_angle).transformed(t)) t = Trans(Trans.R0, x_bottom + Lc / 2, y_bottom + r) self.cell.shapes(LayerSiN).insert( arc_wg(r, w, -90 - dc_angle, -90).transformed(t)) wg1 = Box(-r - w / 2 - w - Lc / 2, y_bottom - w / 2, -x_bottom - Lc / 2, y_bottom + w / 2) shapes(LayerSiN).insert(wg1) wg1 = Box(x_bottom + Lc / 2, y_bottom - w / 2, r + w / 2 + w + Lc / 2, y_bottom + w / 2) shapes(LayerSiN).insert(wg1) # Pins on the bus waveguide side: pin = Path([ Point(-r - w / 2 - w + PIN_LENGTH / 2 - Lc / 2, y_bottom), Point(-r - w / 2 - w - PIN_LENGTH / 2 - Lc / 2, y_bottom) ], w) shapes(LayerPinRecN).insert(pin) text = Text("pin1", Trans(Trans.R0, -r - w / 2 - w - Lc / 2, y_bottom)) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu pin = Path([ Point(r + w / 2 + w - PIN_LENGTH / 2 + Lc / 2, y_bottom), Point(r + w / 2 + w + PIN_LENGTH / 2 + Lc / 2, y_bottom) ], w) shapes(LayerPinRecN).insert(pin) text = Text("pin3", Trans(Trans.R0, r + w / 2 + w + Lc / 2, y_bottom)) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu # Merge all the waveguide shapes, to avoid any small gaps layer_temp = self.layout.layer(LayerInfo(913, 0)) shapes_temp = self.cell.shapes(layer_temp) ShapeProcessor().merge(self.layout, self.cell, LayerSiN, shapes_temp, True, 0, True, True) self.cell.shapes(LayerSiN).clear() shapes_SiN = self.cell.shapes(LayerSiN) ShapeProcessor().merge(self.layout, self.cell, layer_temp, shapes_SiN, True, 0, True, True) self.cell.shapes(layer_temp).clear() # Create the device recognition layer -- make it 1 * wg_width away from the waveguides. dev = Box(-r - w / 2 - w - Lc / 2, y_bottom - w / 2 - w, r + w / 2 + w + Lc / 2, y) shapes(LayerDevRecN).insert(dev) # Compact model information t = Trans(Trans.R0, r / 4, 0) text = Text("Lumerical_INTERCONNECT_library=Design kits/ebeam_v1.2", t) shape = shapes(LayerDevRecN).insert(text) shape.text_size = self.r * 0.017 / dbu t = Trans(Trans.R0, r / 4, r / 4) text = Text('Component=ebeam_dc_halfring_arc_te1550', t) shape = shapes(LayerDevRecN).insert(text) shape.text_size = self.r * 0.017 / dbu t = Trans(Trans.R0, r / 4, r / 2) text = Text( 'Spice_param:wg_width=%.3fu gap=%.3fu radius=%.3fu Lc=%.3fu' % (self.w, self.g, self.r, self.Lc), t) shape = shapes(LayerDevRecN).insert(text) shape.text_size = self.r * 0.017 / dbu print("Done drawing the layout for - ebeam_dc_halfring_arc: %.3f-%g" % (self.r, self.g))
def produce_impl(self): # This is the main part of the implementation: create the layout # Fixed PCell parameters port_spacing = 2000 # spacing of the two ports, determines the angle required by the s-bend. from math import pi, cos, sin, acos from SiEPIC.utils import arc_wg, arc_wg_xy from SiEPIC._globals import PIN_LENGTH # fetch the parameters dbu = self.layout.dbu ly = self.layout shapes = self.cell.shapes LayerSiN = ly.layer(self.silayer) LayerPinRecN = ly.layer(self.pinrec) LayerDevRecN = ly.layer(self.devrec) TextLayerN = ly.layer(self.textl) Lc = int(round(self.Lc / dbu)) w = int(round(self.w / dbu)) r = int(round(self.r / dbu)) g = int(round(self.g / dbu)) # Create the parallel waveguides if Lc > 0: wg1 = Box(-Lc / 2, -w / 2 + (w + g) / 2, Lc / 2, w / 2 + (w + g) / 2) shapes(LayerSiN).insert(wg1) wg1 = Box(-Lc / 2, -w / 2 - (w + g) / 2, Lc / 2, w / 2 - (w + g) / 2) shapes(LayerSiN).insert(wg1) dc_angle = acos((r - abs(port_spacing / 2)) / r) * 180 / pi # bottom S-bends self.cell.shapes(LayerSiN).insert( arc_wg_xy(Lc / 2, -r - (w + g) / 2, r, w, 90 - dc_angle, 90)) self.cell.shapes(LayerSiN).insert( arc_wg_xy(-Lc / 2, -r - (w + g) / 2, r, w, 90, 90 + dc_angle)) y_bottom = round(-2 * (1 - cos(dc_angle / 180.0 * pi)) * r) - (w + g) / 2 x_bottom = round(2 * sin(dc_angle / 180.0 * pi) * r) t = Trans(Trans.R0, -x_bottom - Lc / 2, y_bottom + r) self.cell.shapes(LayerSiN).insert( arc_wg(r, w, -90, -90 + dc_angle).transformed(t)) t = Trans(Trans.R0, x_bottom + Lc / 2, y_bottom + r) self.cell.shapes(LayerSiN).insert( arc_wg(r, w, -90 - dc_angle, -90).transformed(t)) # top S-bends self.cell.shapes(LayerSiN).insert( arc_wg_xy(Lc / 2, r + (w + g) / 2, r, w, 270, 270 + dc_angle)) self.cell.shapes(LayerSiN).insert( arc_wg_xy(-Lc / 2, r + (w + g) / 2, r, w, 270 - dc_angle, 270)) y_top = round(2 * (1 - cos(dc_angle / 180.0 * pi)) * r) + (w + g) / 2 x_top = round(2 * sin(dc_angle / 180.0 * pi) * r) t = Trans(Trans.R0, -x_top - Lc / 2, y_top - r) self.cell.shapes(LayerSiN).insert( arc_wg(r, w, 90 - dc_angle, 90).transformed(t)) t = Trans(Trans.R0, x_top + Lc / 2, y_top - r) self.cell.shapes(LayerSiN).insert( arc_wg(r, w, 90, 90 + dc_angle).transformed(t)) # Pins on the bottom waveguide side: pin = Path([ Point(-x_bottom + PIN_LENGTH / 2 - Lc / 2, y_bottom), Point(-x_bottom - PIN_LENGTH / 2 - Lc / 2, y_bottom) ], w) shapes(LayerPinRecN).insert(pin) text = Text("pin1", Trans(Trans.R0, -x_bottom - Lc / 2, y_bottom)) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu pin = Path([ Point(x_bottom - PIN_LENGTH / 2 + Lc / 2, y_bottom), Point(x_bottom + PIN_LENGTH / 2 + Lc / 2, y_bottom) ], w) shapes(LayerPinRecN).insert(pin) text = Text("pin3", Trans(Trans.R0, x_bottom + Lc / 2, y_bottom)) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu # Pins on the top waveguide side: pin = Path([ Point(-x_bottom + PIN_LENGTH / 2 - Lc / 2, y_top), Point(-x_bottom - PIN_LENGTH / 2 - Lc / 2, y_top) ], w) shapes(LayerPinRecN).insert(pin) text = Text("pin2", Trans(Trans.R0, -x_bottom - Lc / 2, y_top)) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu pin = Path([ Point(x_bottom - PIN_LENGTH / 2 + Lc / 2, y_top), Point(x_bottom + PIN_LENGTH / 2 + Lc / 2, y_top) ], w) shapes(LayerPinRecN).insert(pin) text = Text("pin4", Trans(Trans.R0, x_bottom + Lc / 2, y_top)) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu # Merge all the waveguide shapes, to avoid any small gaps layer_temp = self.layout.layer(LayerInfo(913, 0)) shapes_temp = self.cell.shapes(layer_temp) ShapeProcessor().merge(self.layout, self.cell, LayerSiN, shapes_temp, True, 0, True, True) self.cell.shapes(LayerSiN).clear() shapes_SiN = self.cell.shapes(LayerSiN) ShapeProcessor().merge(self.layout, self.cell, layer_temp, shapes_SiN, True, 0, True, True) self.cell.shapes(layer_temp).clear() # Create the device recognition layer -- make it 1 * wg_width away from the waveguides. dev = Box(-x_bottom - Lc / 2, y_bottom - w / 2 - w, x_bottom + Lc / 2, y_top + w / 2 + w) shapes(LayerDevRecN).insert(dev) # Compact model information t = Trans(Trans.R0, 0, -w) text = Text("Lumerical_INTERCONNECT_library=Design kits/ebeam_v1.2", t) shape = shapes(LayerDevRecN).insert(text) shape.text_size = r * 0.017 t = Trans(Trans.R0, 0, 0) text = Text('Component=NO_MODEL', t) shape = shapes(LayerDevRecN).insert(text) shape.text_size = r * 0.017 t = Trans(Trans.R0, 0, w) text = Text( 'Spice_param:wg_width=%.3fu gap=%.3fu radius=%.3fu Lc=%.3fu' % (w * dbu, g * dbu, r * dbu, self.Lc), t) shape = shapes(LayerDevRecN).insert(text) shape.text_size = r * 0.017 print("Done drawing the layout for - ebeam_dc: %.3f" % (self.Lc))
def produce(self, layout, layers, parameters, cell): """ coerce parameters (make consistent) """ self._layers = layers self.cell = cell self._param_values = parameters self.layout = layout # cell: layout cell to place the layout # LayerSiN: which layer to use # r: radius # w: waveguide width # length units in dbu import math from math import pi, cos, sin from SiEPIC.utils import arc_wg_xy from SiEPIC._globals import PIN_LENGTH as pin_length from SiEPIC.extend import to_itype # fetch the parameters dbu = self.layout.dbu ly = self.layout LayerSi = self.silayer LayerSiN = self.silayer_layer # LayerSiN = ly.layer(LayerSi) LayerPinRecN = ly.layer(self.pinrec) LayerDevRecN = ly.layer(self.devrec) w_bus = to_itype(self.bus_width, dbu) w_ring = to_itype(self.ring_width, dbu) r = to_itype(self.radius, dbu) r_bus = to_itype(self.bus_radius, dbu) bend_angle = int(round(self.bend_angle)) gap = to_itype(self.gap, dbu) #********************** # Draw the ring waveguide #********************** x = 0 y = 0 self.cell.shapes(LayerSiN).insert(arc_wg_xy(x, y, r, w_ring, 0, 180)) # Create the pins, as short paths: # Pin on the bottom left side: p3 = [ Point(x - r, pin_length / 2 + y), Point(x - r, -pin_length / 2 + y) ] p3c = Point(x - r, y) self.set_p3 = p3c self.p3 = p3c pin = Path(p3, w_ring) self.cell.shapes(LayerPinRecN).insert(pin) t = Trans(Trans.R0, x - r, y) text = Text("pin3", t) shape = self.cell.shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu # Pin on the bottom right side: p4 = [ Point(x + r, y + pin_length / 2), Point(x + r, y - pin_length / 2) ] p4c = Point(x + r, y) self.set_p4 = p4c self.p4 = p4c pin = Path(p4, w_ring) self.cell.shapes(LayerPinRecN).insert(pin) t = Trans(Trans.R0, x + r, y) text = Text("pin4", 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. self.cell.shapes(LayerDevRecN).insert( arc_wg_xy(x, y, r, w_ring * 3, 0, 180)) #********************** # Draw the bus waveguide (figure out how to call the existing class maybe??) #********************** r_original = to_itype(self.radius, dbu) r = r + gap + w_ring / 2 + w_bus / 2 # number of points per circle: # npoints = int(points_per_circle(r)) # increment, in radians, for each point: #da = 2 * pi / npoints # draw the first arc x = round(-r * math.sin(bend_angle * math.pi / 180) - r_bus * math.sin(bend_angle * math.pi / 180)) y = round(r * math.cos(bend_angle * math.pi / 180) + r_bus * math.cos(bend_angle * math.pi / 180)) self.cell.shapes(LayerSiN).insert( arc_wg_xy(x, y, r_bus, w_bus, 270, 270 + bend_angle)) # Create the device recognition layer -- make it 1 * wg_width away from the waveguides. self.cell.shapes(LayerDevRecN).insert( arc_wg_xy(x, y, r_bus, w_bus * 3, 270, 270 + bend_angle)) # draw the second arc r = to_itype(self.radius, dbu) x = 0 y = 0 r = r + gap + w_ring / 2 + w_bus / 2 self.cell.shapes(LayerSiN).insert( arc_wg_xy(x, y, r, w_bus, 90 - bend_angle, 90 + bend_angle)) # Create the device recognition layer -- make it 1 * wg_width away from the waveguides. self.cell.shapes(LayerDevRecN).insert( arc_wg_xy(x, y, r, w_bus * 3, 90 - bend_angle, 90 + bend_angle)) # draw the third arc x = round(r * math.sin(bend_angle * math.pi / 180) + r_bus * math.sin(bend_angle * math.pi / 180)) y = round(r * math.cos(bend_angle * math.pi / 180) + r_bus * math.cos(bend_angle * math.pi / 180)) self.cell.shapes(LayerSiN).insert( arc_wg_xy(x, y, r_bus, w_bus, 270 - bend_angle, 270)) # Create the device recognition layer -- make it 1 * wg_width away from the waveguides. self.cell.shapes(LayerDevRecN).insert( arc_wg_xy(x, y, r_bus, w_bus * 3, 270 - bend_angle, 270)) r = to_itype(self.radius, dbu) r = r + gap + w_ring / 2 + w_bus / 2 # Pin on the left side: x = round(-r * math.sin(bend_angle * math.pi / 180) - r_bus * math.sin(bend_angle * math.pi / 180)) y = round(r * math.cos(bend_angle * math.pi / 180) + r_bus * math.cos(bend_angle * math.pi / 180) - r_bus) p2 = [Point(x + pin_length / 2, y), Point(x - pin_length / 2, y)] p2c = Point(x, y) self.set_p2 = p2c self.p2 = p2c pin = Path(p2, w_bus) self.cell.shapes(LayerPinRecN).insert(pin) t = Trans(Trans.R0, x, y) text = Text("pin2", t) shape = self.cell.shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu # Pin on the right side: p1 = [Point(-x - pin_length / 2, y), Point(-x + pin_length / 2, y)] p1c = Point(x, -r) self.set_p1 = p1c self.p1 = p1c pin = Path(p1, w_bus) self.cell.shapes(LayerPinRecN).insert(pin) t = Trans(Trans.R0, -x, y) text = Text("pin1", t) shape = self.cell.shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu
def produce(self, layout, layers, parameters, cell): """ coerce parameters (make consistent) """ self._layers = layers self.cell = cell self._param_values = parameters self.layout = layout # cell: layout cell to place the layout # LayerSiN: which layer to use # r: radius # w: waveguide width # length units in dbu from math import pi, cos, sin from SiEPIC.utils import arc_wg, arc_wg_xy from SiEPIC._globals import PIN_LENGTH # fetch the parameters dbu = self.layout.dbu ly = self.layout LayerSi = self.silayer LayerSiN_gratings = self.silayer_gratings_layer LayerSiN = self.silayer_layer LayerPinRecN = ly.layer(self.pinrec) LayerDevRecN = ly.layer(self.devrec) from SiEPIC.extend import to_itype w_bus = to_itype(self.bus_width, dbu) w_ring = to_itype(self.ring_width, dbu) w = w_ring r = int(round(self.radius / dbu)) gap = int(round(self.gap / dbu)) period = self.period deltaWR = int(round(self.deltaWR / dbu)) N = int(self.gamma) deltaWB = int(round(self.deltaWB / dbu)) busBendR = int(round(self.busBend / dbu)) # Center of everything x = 0 y = 0 # Angle of CDC portion, also bend angle! periodAngle = (180 / pi) * (period / 2) / (r + w_ring / 2 + gap / 2) # Bend angle bendAngle = (180 / pi) * (N * period / 2) / (r + w_ring / 2 + gap / 2) # Bend radius of bus rBus = r + gap + w_bus / 2 + w_ring / 2 N_input = N # Normalized number of corrugations to periodAngle N = N * periodAngle * 2 # Convention: Set A is the CDC portion that is not offsetted, set B is offsetted by corrugation width # Ring CDCs (set A) ii = periodAngle * 2 while ii < N + periodAngle * 1.5: self.cell.shapes(LayerSiN_gratings).insert( arc_wg_xy(x, y, r - deltaWR / 2, w_ring, 90 + bendAngle - ii, 90 + bendAngle - ii - periodAngle)) ii = ii + periodAngle ii = ii + periodAngle # Ring CDCs (set B) ii = periodAngle while ii < N: self.cell.shapes(LayerSiN_gratings).insert( arc_wg_xy(x, y, r + deltaWR / 2, w_ring, 90 + bendAngle - ii, 90 + bendAngle - ii - periodAngle)) ii = ii + periodAngle ii = ii + periodAngle # Bus CDCs (set A) ii = periodAngle while ii < N: self.cell.shapes(LayerSiN_gratings).insert( arc_wg_xy(x, y, rBus - deltaWB / 2, w_bus, 90 + bendAngle - ii, 90 + bendAngle - ii - periodAngle)) ii = ii + periodAngle ii = ii + periodAngle # Bus CDCs (set B) ii = periodAngle * 2 while ii < N + periodAngle * 1.5: self.cell.shapes(LayerSiN_gratings).insert( arc_wg_xy(x, y, rBus + deltaWB / 2, w_bus, 90 + bendAngle - ii, 90 + bendAngle - ii - periodAngle)) ii = ii + periodAngle ii = ii + periodAngle # Ring non-CDC left self.cell.shapes(LayerSiN).insert( arc_wg_xy(x, y, r, w_ring, 180 - (90 - bendAngle), 180)) # Ring non-CDC right self.cell.shapes(LayerSiN).insert( arc_wg_xy(x, y, r, w_ring, 0, 90 - bendAngle)) bendAngleRad = (pi / 180) * bendAngle # Draw Bus non-CDC Waveguide y_center = rBus * cos(bendAngleRad) + busBendR * cos(bendAngleRad) x_center = rBus * sin(bendAngleRad) + busBendR * sin(bendAngleRad) self.cell.shapes(LayerSiN).insert( arc_wg_xy(x_center, y_center, busBendR, w_bus, 270 - bendAngle, 270)) self.cell.shapes(LayerSiN).insert( arc_wg_xy(-x_center, y_center, busBendR, w_bus, 270, 270 - bendAngle)) # Create the pins, as short paths: from SiEPIC._globals import PIN_LENGTH as pin_length # Pin on the right side: y_center = rBus * cos(bendAngleRad) + busBendR * cos( bendAngleRad) - busBendR p2 = [ Point(-pin_length / 2 + x_center, y_center), Point(pin_length / 2 + x_center, y_center) ] p2c = Point(x_center, y_center) self.set_p2 = p2c self.p2 = p2c pin = Path(p2, w_bus) self.cell.shapes(LayerPinRecN).insert(pin) t = Trans(Trans.R0, x_center, y_center) text = Text("pin2", t) shape = self.cell.shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu # Pin on the left side: x_center = -x_center p1 = [ Point(pin_length / 2 + x_center, y_center), Point(-pin_length / 2 + x_center, y_center) ] p1c = Point(x_center, y_center) self.set_p1 = p1c self.p1 = p1c pin = Path(p1, w_bus) self.cell.shapes(LayerPinRecN).insert(pin) t = Trans(Trans.R0, x_center, y_center) text = Text("pin1", t) shape = self.cell.shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu # Pin on the bottom left side: p3 = [ Point(x - r, pin_length / 2 + y), Point(x - r, -pin_length / 2 + y) ] p3c = Point(x - r, y) self.set_p3 = p3c self.p3 = p3c pin = Path(p3, w_ring) self.cell.shapes(LayerPinRecN).insert(pin) t = Trans(Trans.R0, x - r, y) text = Text("pin3", t) shape = self.cell.shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu # Pin on the bottom right side: p4 = [ Point(x + r, y + pin_length / 2), Point(x + r, y - pin_length / 2) ] p4c = Point(x + r, y) self.set_p4 = p4c self.p4 = p4c pin = Path(p4, w_ring) self.cell.shapes(LayerPinRecN).insert(pin) t = Trans(Trans.R0, x + r, y) text = Text("pin4", 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. self.cell.shapes(LayerDevRecN).insert( arc_wg_xy(x, y, r + gap, w * 5, 0, 180))
def produce_impl(self): # This is the main part of the implementation: create the layout from math import pi, cos, sin from SiEPIC.utils import arc_wg, arc_wg_xy, arc_xy from SiEPIC._globals import PIN_LENGTH from SiEPIC.extend import to_itype, to_dtype # fetch the parameters dbu = self.layout.dbu ly = self.layout shapes = self.cell.shapes LayerSiN = ly.layer(self.silayer) LayerSiRibN = ly.layer(self.siriblayer) LayerNN = ly.layer(self.nlayer) LayerNPPN = ly.layer(self.npplayer) LayerVCN = ly.layer(self.vclayer) LayerMN = ly.layer(self.mlayer) LayerPinRecN = ly.layer(self.pinrec) LayerDevRecN = ly.layer(self.devrec) TextLayerN = ly.layer(self.textl) w = to_itype(self.w, dbu) r = to_itype(self.r, dbu) g = to_itype(self.g, dbu) n_w = to_itype(self.n_w, dbu) npp_si = to_itype(self.npp_si, dbu) npp_w = to_itype(self.npp_w, dbu) theta_start = self.n_theta_start theta_stop = self.n_theta_stop vc_cw = to_itype(self.vc_cw, dbu) vc_aw = to_itype(self.vc_aw, dbu) overlay_ebl = to_itype(self.overlay_ebl, dbu) m_cw = to_itype(self.m_cw, dbu) m_aw = to_itype(self.m_aw, dbu) x = 0 y = 0 #draw ring self.cell.shapes(LayerSiN).insert(arc_wg_xy(x, y, r, w, 0, 360)) #draw bus waveguides #bottom waveguide xtop = -2 / 3 * r ytop = -1 * (r + g + w / 2) xbottom = 4 / 3 * r ybottom = ytop - w wg1 = Box(xtop, ytop, xbottom, ybottom) shapes(LayerSiN).insert(wg1) #left waveguide wg1 = Box(ytop, xtop, ybottom, xbottom) shapes(LayerSiN).insert(wg1) # Pins on the bottom waveguide side: pin = Path([ Point(xtop + PIN_LENGTH, ytop - w / 2), Point(xtop - PIN_LENGTH, ytop - w / 2) ], w) shapes(LayerPinRecN).insert(pin) text = Text("pin1", Trans(Trans.R0, xtop, ytop - w / 2)) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu pin = Path([ Point(xbottom - PIN_LENGTH, ytop - w / 2), Point(xbottom + PIN_LENGTH, ytop - w / 2) ], w) shapes(LayerPinRecN).insert(pin) text = Text("pin2", Trans(Trans.R0, xbottom, ytop - w / 2)) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu # Pins on the left waveguide side: pin = Path([ Point(ytop - w / 2, xtop + PIN_LENGTH), Point(ytop - w / 2, xtop - PIN_LENGTH) ], w) shapes(LayerPinRecN).insert(pin) text = Text("pin3", Trans(Trans.R0, ytop - w / 2, xtop)) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu pin = Path([ Point(ybottom + w / 2, xbottom - PIN_LENGTH), Point(ybottom + w / 2, xbottom + PIN_LENGTH) ], w) shapes(LayerPinRecN).insert(pin) text = Text("pin4", Trans(Trans.R0, ybottom + w / 2, xbottom)) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu #draw N arc_pts = arc_xy(x, y, n_w, theta_start, theta_stop) arc_pts.append(pya.Point.from_dpoint(pya.DPoint( 0, 0))) #adding center point for polygon shapes(LayerNN).insert(pya.Polygon(arc_pts)) #draw NPP #center arc_pts = arc_xy(x, y, r - npp_si - w / 2, 0, 360) arc_pts.append(pya.Point.from_dpoint(pya.DPoint( 0, 0))) #adding center point for polygon shapes(LayerNPPN).insert(pya.Polygon(arc_pts)) #outer donut shapes(LayerNPPN).insert( arc_wg_xy(x, y, r + w / 2 + npp_si + npp_w / 2, npp_w, theta_start, theta_stop)) #draw via #center arc_pts = arc_xy(x, y, vc_cw, 0, 360) arc_pts.append(pya.Point.from_dpoint(pya.DPoint( 0, 0))) #adding center point for polygon shapes(LayerVCN).insert(pya.Polygon(arc_pts)) #outer donut shapes(LayerVCN).insert( arc_wg_xy(x, y, 4 / dbu + r + npp_w / 2, vc_aw, theta_start + 10, theta_stop - 10)) #draw metal #center arc_pts = arc_xy(x, y, m_cw, 0, 360) arc_pts.append(pya.Point.from_dpoint(pya.DPoint( 0, 0))) #adding center point for polygon shapes(LayerMN).insert(pya.Polygon(arc_pts)) #outer donut shapes(LayerMN).insert( arc_wg_xy(x, y, 4 / dbu + r + npp_w / 2, m_aw, theta_start, theta_stop)) #devrec layer xtop = -2 / 3 * r ytop = -1 * (r + g + w) xbottom = 4 / 3 * r ybottom = ytop dev_array = [ Point(ytop + 3.5 * w, xbottom + npp_w), Point(ytop + 3.5 * w, xbottom), Point(ytop - 3.5 * w, xbottom), Point(ytop - 3.5 * w, xtop), Point(ytop + 3.5 * w, xtop), Point(xtop, ybottom + 3.5 * w), Point(xtop, ybottom - 3 * w), Point(xbottom, ybottom - 3.5 * w), Point(xbottom, ybottom + 3.5 * w), Point(xbottom + npp_w, ybottom + 3.5 * w), Point(xbottom + npp_w, xbottom + npp_w) ] shapes(LayerDevRecN).insert(pya.Polygon(dev_array)) if self.io_wg_type == 0: # strip converter taper_long = to_itype(10, dbu) taper_short = to_itype(3, dbu) dev_array = [ Point(ytop + 3.5 * w, xbottom + npp_w), Point(ytop + 3.5 * w, xbottom - taper_long), Point(ytop + 2.5 * w, xbottom - taper_long), Point(ytop + w / 2 - overlay_ebl * 2, xbottom), Point(ytop - w / 2 + overlay_ebl * 2, xbottom), Point(ytop - 2.5 * w, xbottom - taper_long), Point(ytop - 3.5 * w, xbottom - taper_long), Point(ytop - 3.5 * w, xtop + taper_short), Point(ytop - 1.5 * w, xtop + taper_short), Point(ytop - w / 2 + overlay_ebl * 2, xtop), Point(ytop + w / 2 - overlay_ebl * 2, xtop), Point(ytop + 1.5 * w, xtop + taper_short), Point(ytop + 3.5 * w, xtop + taper_short), Point((ytop + 3.5 * w + xtop) / 2, (xtop + ybottom + 3.5 * w) / 2), Point(xtop + taper_short, ybottom + 3.5 * w), Point(xtop + taper_short, ybottom + 1.5 * w), Point(xtop, ybottom + w / 2 - overlay_ebl * 2), Point(xtop, ybottom - w / 2 + overlay_ebl * 2), Point(xtop + taper_short, ybottom - 1.5 * w), Point(xtop + taper_short, ybottom - 3.5 * w), Point(xbottom - taper_long, ybottom - 3.5 * w), Point(xbottom - taper_long, ybottom - 2.5 * w), Point(xbottom, ybottom - w / 2 + overlay_ebl * 2), Point(xbottom, ybottom + w / 2 - overlay_ebl * 2), Point(xbottom - taper_long, ybottom + 2.5 * w), Point(xbottom - taper_long, ybottom + 3.5 * w), Point(xbottom + npp_w, ybottom + 3.5 * w), Point(xbottom + npp_w, xbottom + npp_w) ] # Si rib layer shapes(LayerSiRibN).insert(pya.Polygon(dev_array)) t = Trans(Trans.R0, 0, 0) text = Text('Component=ebeam_irph_mrr', t) shape = shapes(LayerDevRecN).insert(text) shape.text_size = self.r * 0.07 / dbu print("Done drawing the layout for - ebeam_IRPH_MRR: %.3f-%g" % (self.r, self.g))