def init_regions( self ): self.P0 = DPoint( 0,0 ) self.P1 = self.P0 + DPoint( self.Z1.gap,0 ) self.P2 = self.P1 + DPoint( self.Z1.width,0 ) self.P3 = self.P2 + DPoint( 0,self.Z1.gap ) self.P4 = self.P2 + DPoint( self.Z1.gap, self.Z2.gap ) self.P5 = self.P4 + DPoint( 0,self.Z2.width ) self.P6 = DPoint( 0, self.Z1.gap + self.Z1.width ) self.P7 = DPoint( 0, self.Z1.gap ) self.P8 = self.P7 + DPoint( self.Z1.gap,0 ) self.P9 = self.P2 + DPoint( self.Z1.gap,0 ) self.P10 = self.P5 + DPoint( 0, self.Z2.gap ) self.P11 = self.P10 - DPoint( 2*self.Z1.gap + self.Z1.width, 0 ) self.P12 = self.P6 + DPoint( 0, self.Z1.gap ) self.connections = [(self.P6 + self.P7)*0.5,(self.P1 + self.P2)*0.5,(self.P5 + self.P4)*0.5] self.angle_connections = [0,3/2*pi,0] self.metal_polygon = DPolygon( [self.P1,self.P2,self.P3,self.P4,self.P5,self.P6,self.P7,self.P8] ) self.empty1_polygon = DPolygon( [self.P0,self.P1,self.P8,self.P7] ) self.empty2_polygon = DPolygon( [self.P2,self.P9,self.P4,self.P3] ) self.empty3_polygon = DPolygon( [self.P5,self.P10,self.P12,self.P6] ) self.gnd_polygon = DPolygon( [self.P10,self.P11,self.P12] ) self.metal_region = pya.Region( list(map(pya.Polygon().from_dpoly,[self.metal_polygon,self.gnd_polygon])) ) self.empty_region = pya.Region( list(map(pya.Polygon().from_dpoly ,[self.empty1_polygon,self.empty2_polygon,self.empty3_polygon])) )
def init_regions(self): Rout = self.r Rin = self.r - self.t dpts_arr_Rout = [DPoint(Rout * cos(2 * pi * i / self.n_pts), Rout * sin(2 * pi * i / self.n_pts)) for i in range(0, self.n_pts)] dpts_arr_Rin = [DPoint(Rin * cos(2 * pi * i / self.n_pts), Rin * sin(2 * pi * i / self.n_pts)) for i in range(0, self.n_pts)] ring_dpoly = DPolygon(dpts_arr_Rout) ring_dpoly.insert_hole(dpts_arr_Rin) ring_poly = Polygon().from_dpoly(ring_dpoly) if self.inverse: self.empty_region.insert(ring_poly) else: self.metal_region.insert(ring_poly)
def init_regions(self): pts_raw = [ -199499.00, -299939.00, -199499.00, -201544.00, -301346.00, -201544.00, -301346.00, 202661.00, -194835.00, 202661.00, -194835.00, 249057.00, -3110.00, 249057.00, -3110.00, 243800.00, -3006.00, 243800.00, -3006.00, 9362.00, -1507.00, 9362.00, -1507.00, 389.00, -10506.00, 389.00, -10506.00, 1862.00, -250230.00, 1862.00, -250230.00, -3138.00, -10506.00, -3138.00, -10506.00, -1639.00, -1507.00, -1639.00, -1507.00, -10638.00, -3006.00, -10638.00, -3006.00, -249398.00, 1994.00, -249398.00, 1994.00, -10638.00, 495.00, -10638.00, 495.00, -1639.00, 9494.00, -1639.00, 9494.00, -3138.00, 250101.00, -3138.00, 250101.00, 1862.00, 9494.00, 1862.00, 9494.00, 363.00, 521.00, 363.00, 521.00, 9362.00, 1994.00, 9362.00, 1994.00, 249057.00, -194835.00, 249057.00, -194835.00, 299939.00, 202792.00, 299939.00, 202792.00, 196681.00, 301345.00, 196681.00, 301345.00, 140894.00, 149560.00, 140894.00, 149560.00, 140729.00, 301345.00, 140729.00, 301345.00, -203457.00, 202313.00, -203457.00, 202313.00, -299939.00 ] pts = [ DPoint(pts_raw[2 * i], pts_raw[2 * i + 1]) for i in range(int(len(pts_raw) // 2)) ] poly = Polygon(DPolygon(pts)) if self.inverse: self.empty_region.insert(poly) else: self.metal_region.insert(poly)
def produce_impl(self): from SiEPIC._globals import PIN_LENGTH from SiEPIC.extend import to_itype import math from pya import DPolygon # This is the main part of the implementation: create the layout # 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) #variables pitch = self.pitch w = self.w r = self.r ff = self.ff angle = self.angle gap = self.gap W_ratio = self.W_ratio doublebus = self.doublebus print(doublebus) # set the deltaL of sT-shaped silicon pillar (deltaL = (Lin-Lout)/4) deltaL = (2 * pitch * ff) * (W_ratio - 1) / ((1 + W_ratio) * (4)) if (r - w / 2 <= 0): r = 5 print('invalid radius, set r to default: 5') #Calculate number of segments s1 = pitch * ff #silicon s2 = pitch - s1 #gap #calculate best radius pi = math.pi const = math.ceil(2 * pi * r / (s1 + s2)) #if doesn't divide evenly, replace r with best possible r if ((2 * pi * r) % (s1 + s2) != 0): r = const * (s1 + s2) / (2 * pi) print('r adjusted to ' + str(r) + 'um to fit periods perfectly.') #theta1 = (s1/r) #theta2 = (s2/r) theta1 = math.atan(s1 / r) # angle of silicon compared to the origin point theta2 = math.atan(s2 / r) # angle of the gap compared to the origin point nSeg = int( math.floor(angle / (math.degrees(theta1) + math.degrees(theta2)))) #how many segments to have si_first = True #for alternating between silicon and gap j = 0 #index of how many silicon thetas jj = 0 #index of how many gap thetas ORDER = True #ordering of the coordinates for polygon drawing #xo = [(r-w/2)*math.cos(0)] #yo = [(r-w/2)*math.sin(0)] #xo.append((r+w/2)*math.cos(0)) #yo.append((r+w/2)*math.sin(0)) xo = [(r - w / 2) * math.cos(0) + deltaL * math.sin(0)] yo = [(r - w / 2) * math.sin(0) - deltaL * math.cos(0)] xo.append((r + w / 2) * math.cos(0) - deltaL * math.sin(0)) yo.append((r + w / 2) * math.sin(0) + deltaL * math.cos(0)) for i in range(0, nSeg * 2): if si_first: j = j + 1 si_first = not (si_first) else: jj = jj + 1 si_first = not (si_first) if ORDER: xo.append((r + w / 2) * math.cos(j * theta1 + jj * theta2) + deltaL * math.sin(j * theta1 + jj * theta2)) yo.append((r + w / 2) * math.sin(j * theta1 + jj * theta2) - deltaL * math.cos(j * theta1 + jj * theta2)) xo.append((r - w / 2) * math.cos(j * theta1 + jj * theta2) - deltaL * math.sin(j * theta1 + jj * theta2)) yo.append((r - w / 2) * math.sin(j * theta1 + jj * theta2) + deltaL * math.cos(j * theta1 + jj * theta2)) ORDER = not (ORDER) else: xo.append((r - w / 2) * math.cos(j * theta1 + jj * theta2) + deltaL * math.sin(j * theta1 + jj * theta2)) yo.append((r - w / 2) * math.sin(j * theta1 + jj * theta2) - deltaL * math.cos(j * theta1 + jj * theta2)) xo.append((r + w / 2) * math.cos(j * theta1 + jj * theta2) - deltaL * math.sin(j * theta1 + jj * theta2)) yo.append((r + w / 2) * math.sin(j * theta1 + jj * theta2) + deltaL * math.cos(j * theta1 + jj * theta2)) ORDER = not (ORDER) if len(xo) == 4: dpts = [pya.DPoint(xo[i], yo[i]) for i in range(len(xo))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) xo = [] yo = [] #Draw Bus WG #calulate ideal length of bus bus_length = self.cell.bbox().height() * dbu + pitch * 2 constant = math.ceil(bus_length / (s1 + s2)) if bus_length % (s1 + s2) != 0: bus_length = constant * (s1 + s2) #draw first box at center xo = [(r + w / 2 + gap), (r + w / 2 + gap + w), (r + w / 2 + gap + w), (r + w / 2 + gap)] yo = [0, 0, s1, s1] dpts = [pya.DPoint(xo[i], yo[i]) for i in range(len(xo))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) for i in range(0, int(math.ceil((constant) / 2))): yu = [yo[j] + i * pitch for j in range(len(yo))] yd = [yo[j] - i * pitch for j in range(len(yo))] dpts = [pya.DPoint(xo[i], yu[i]) for i in range(len(xo))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) dpts = [pya.DPoint(xo[i], yd[i]) for i in range(len(xo))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) if doublebus: for i in range(0, int(math.ceil((constant) / 2))): x2 = [xo[j] * -1 for j in range(len(xo))] yu = [yo[j] + i * pitch for j in range(len(yo))] yd = [yo[j] - i * pitch for j in range(len(yo))] dpts = [pya.DPoint(x2[i], yu[i]) for i in range(len(xo))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) dpts = [pya.DPoint(x2[i], yd[i]) for i in range(len(xo))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) #DEV BOX if doublebus is False: half_l = (self.cell.bbox().width() - w / dbu - gap / dbu) / 2 half_r = self.cell.bbox().width() - half_l dev = Box(-half_l, yd[-4] / dbu, half_r, yu[-1] / dbu) shapes(LayerDevRecN).insert(dev) dev_width = self.cell.bbox().width() / 2 else: half_l = (self.cell.bbox().width()) / 2 half_r = self.cell.bbox().width() - half_l dev = Box(-half_l, yd[-4] / dbu, half_r, yu[-1] / dbu) shapes(LayerDevRecN).insert(dev) dev_width = self.cell.bbox().width() / 2 # Create the pins on the waveguides, as short paths: from SiEPIC._globals import PIN_LENGTH as pin_length w = to_itype(self.w, dbu) gap = to_itype(self.gap, dbu) bus_length = to_itype(bus_length / 2, dbu) #Pin1 t = Trans(Trans.R0, half_r - w / 2, yu[-1] / dbu) 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 #Pin2 t = Trans(Trans.R0, half_r - w / 2, yd[-4] / dbu) 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 doublebus is True: half_l = self.cell.bbox().width() / 2 half_r = self.cell.bbox().width() - half_l #pin 3 t = Trans(Trans.R0, -half_l + w / 2, yu[-1] / dbu) 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("pin3", t) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu #Pin4 t = Trans(Trans.R0, -half_l + w / 2, yd[-4] / dbu) 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("pin4", t) shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu
def produce_impl(self): from SiEPIC._globals import PIN_LENGTH from SiEPIC.extend import to_itype from pya import DPolygon import math # This is the main part of the implementation: create the layout # 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) #variables pitch = self.pitch w = self.w wc = self.wc ff = self.ff #angle = self.angle gap = self.gap #gap2 = self.gap2 row = self.row Length = self.Length taperL = self.taperL phaseshifted = self.phaseshifted #print(doublebus) if Length <= 3 * pitch: Length = 3 * pitch print( 'invalid length of MultiBox Bragg grating, set length at least 3 times larger than the period of multibox blocks' ) s1 = pitch * ff #silicon s2 = pitch - s1 #gap # Draw the first Multi-box Waveguides #calulate ideal length of bus Bragg_length = Length #bus_length = self.cell.bbox().height()*dbu +pitch*2 constant = math.ceil(Bragg_length / (s1 + s2)) if Bragg_length % (s1 + s2) != 0: Bragg_length = constant * (s1 + s2) for ii in range(0, int(row)): xo = [(ii * (w + gap)), (w + ii * (w + gap)), (w + ii * (w + gap)), (ii * (w + gap))] yo = [0, 0, s1, s1] dpts = [pya.DPoint(xo[i], yo[i]) for i in range(len(xo))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) # draw the SWG waveguide from the center one to +/- positions for i in range(0, int(math.ceil((constant) / 2))): yu = [yo[j] + i * pitch for j in range(len(yo))] yd = [yo[j] - i * pitch for j in range(len(yo))] dpts = [pya.DPoint(xo[i], yu[i]) for i in range(len(xo))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) dpts = [pya.DPoint(xo[i], yd[i]) for i in range(len(xo))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) # draw the tapers from waveguide to SWG if taperL != 0: xtu = [((ii * (w + gap)) + (w - 0.06) / 2), ((ii * (w + gap)) + (w - 0.06) / 2 + 0.06), ((ii * (w + gap)) + w + gap / 2), ((ii * (w + gap)) - gap / 2)] ytu = [(yu[3] - taperL), (yu[3] - taperL), (yu[3]), (yu[3])] dpts = [pya.DPoint(xtu[i], ytu[i]) for i in range(len(xtu))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) ytd = [(yd[1] + taperL), (yd[1] + taperL), (yd[1]), (yd[1])] dpts = [pya.DPoint(xtu[i], ytd[i]) for i in range(len(xtu))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) # taper connections from multi-tapers to std WG xTu = [(-gap / 2), (-gap / 2 + row * (gap + w)), ((row * (gap + w) - gap) / 2 + 0.25), ((row * (gap + w) - gap) / 2 - 0.25)] yTu = [(yu[3]), (yu[3]), (yu[3] + taperL), (yu[3] + taperL)] dpts = [pya.DPoint(xTu[i], yTu[i]) for i in range(len(xTu))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) yTd = [(yd[1]), (yd[1]), (yd[1] - taperL), (yd[1] - taperL)] dpts = [pya.DPoint(xTu[i], yTd[i]) for i in range(len(xTu))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) # f is the factor to define the Dev starting point f = 1 if taperL == 0: yTd = yd yTu = yu xTu = [0, 0, 0, 0] f = 0 # draw the corrugations of the Bragg gratings constant_c = math.ceil((Bragg_length - taperL) / (s1 + s2)) for iii in range(0, int(math.ceil(constant_c / 4))): yuc = [yo[j] + 2 * iii * pitch for j in range(len(yo))] ydc = [yo[j] - 2 * iii * pitch for j in range(len(yo))] xlc = [-wc - s2, -s2, -s2, -wc - s2] xrc = [ row * pitch, row * pitch + wc, row * pitch + wc, row * pitch ] dpts = [pya.DPoint(xlc[i], yuc[i]) for i in range(len(xo))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) dpts = [pya.DPoint(xrc[i], yuc[i]) for i in range(len(xo))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) if phaseshifted is False: for iii in range(0, int(math.ceil(constant_c / 4))): #yuc = [yo[j]+2*iii*pitch for j in range(len(yo))] ydc = [yo[j] - 2 * iii * pitch for j in range(len(yo))] #xlc = [-wc-s2, -s2, -s2,-wc-s2] #xrc = [row*pitch, row*pitch+wc, row*pitch+wc, row*pitch] dpts = [pya.DPoint(xlc[i], ydc[i]) for i in range(len(xo))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) dpts = [pya.DPoint(xrc[i], ydc[i]) for i in range(len(xo))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) if phaseshifted is True: for iii in range(0, int(math.ceil(constant_c / 4))): #yuc = [yo[j]+2*iii*pitch for j in range(len(yo))] yddc = [ yo[j] - pitch - 2 * iii * pitch for j in range(len(yo)) ] dpts = [pya.DPoint(xlc[i], yddc[i]) for i in range(len(xo))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) dpts = [pya.DPoint(xrc[i], yddc[i]) for i in range(len(xo))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) #DEV BOX dev = Box(f * (-gap - wc - (2) * pitch) / dbu, yTd[-1] / dbu, (wc + (row + 2) * pitch) / dbu, yTu[-1] / dbu) shapes(LayerDevRecN).insert(dev) dev_width = self.cell.bbox().width() / 2 dev_up = yu[-1] / dbu + taperL / dbu dev_down = yd[-4] / dbu - taperL / dbu # Create the pins on the waveguides, as short paths: from SiEPIC._globals import PIN_LENGTH as pin_length w = to_itype(self.w, dbu) gap = to_itype(self.gap, dbu) #Pin1 t = Trans(Trans.R0, xTu[-1] / dbu + 250, dev_up) pin = Path([Point(0, -pin_length / 2), Point(0, pin_length / 2)], 500) #500 is width of std WG pin_t = pin.transformed(t) shapes(LayerPinRecN).insert(pin_t) t = Trans(Trans.R270, xTu[-1] / dbu + 250, dev_up) text = Text("pin1", t) text.halign = 0 shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu #Pin2 t = Trans(Trans.R0, xTu[-1] / dbu + 250, dev_down) pin = Path([Point(0, pin_length / 2), Point(0, -pin_length / 2)], 500) pin_t = pin.transformed(t) shapes(LayerPinRecN).insert(pin_t) t = Trans(Trans.R90, xTu[-1] / dbu + 250, dev_down) text = Text("pin2", t) text.halign = 0 shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu # Ref t = Trans(Trans.R270, xTu[-1] / dbu + 250 + 0.5 / dbu, dev_up) text = Text("Ref: E. Luan, doi.org/10.1364/BOE.10.004825", t) text.halign = 0 shape = shapes(LayerPinRecN).insert(text) shape.text_size = 0.4 / dbu
def produce_impl(self): from SiEPIC._globals import PIN_LENGTH from SiEPIC.extend import to_itype import math from pya import DPolygon pi = math.pi # This is the main part of the implementation: create the layout # 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) #variables pitch = self.pitch w = self.w r = self.r ff = self.ff angle = self.angle gap = self.gap gap2 = self.gap2 row = self.row busL = self.busL taperL = self.taperL #doublebus = self.doublebus #print(doublebus) if (r - w / 2 <= 0): r = 5 print('invalid radius, set r to default: 5') if row <= 1: row = 1 print('invalid number of rows, set row to default: 1') if busL <= 10: busL = taperL * 2 + 10 print( 'invalid length of SWG bus waveguide, set length at least 2 times larger than taper length and pluse 10 um' ) #Calculate number of segments s1 = pitch * ff #silicon s2 = pitch - s1 #gap # Draw the Multi-box Ring for i in range(0, int(row)): # draw different radius SWG rings #calculate best radius #const = math.ceil(2*pi*r/(s1+s2)) const = math.floor(2 * pi * r / (s1 + s2)) #if doesn't divide evenly, replace r with best possible r if ((2 * pi * r) % (s1 + s2) != 0): r = const * (s1 + s2) / (2 * pi) print('r adjusted to ' + str(r) + 'um to fit periods perfectly.') theta1 = math.atan(s1 / r) theta2 = math.atan(s2 / r) nSeg = int( math.floor(angle / (math.degrees(theta1) + math.degrees(theta2)))) #how many segments to have si_first = True #for alternating between silicon and gap j = 0 #index of how many silicon thetas jj = 0 #index of how many gap thetas ORDER = True #ordering of the coordinates for polygon drawing xo = [(r - w / 2) * math.cos(0)] yo = [(r - w / 2) * math.sin(0)] xo.append((r + w / 2) * math.cos(0)) yo.append((r + w / 2) * math.sin(0)) for i in range(0, nSeg * 2): if si_first: j = j + 1 si_first = not (si_first) else: jj = jj + 1 si_first = not (si_first) if ORDER: xo.append((r + w / 2) * math.cos(j * theta1 + jj * theta2)) yo.append((r + w / 2) * math.sin(j * theta1 + jj * theta2)) xo.append((r - w / 2) * math.cos(j * theta1 + jj * theta2)) yo.append((r - w / 2) * math.sin(j * theta1 + jj * theta2)) ORDER = not (ORDER) else: xo.append((r - w / 2) * math.cos(j * theta1 + jj * theta2)) yo.append((r - w / 2) * math.sin(j * theta1 + jj * theta2)) xo.append((r + w / 2) * math.cos(j * theta1 + jj * theta2)) yo.append((r + w / 2) * math.sin(j * theta1 + jj * theta2)) ORDER = not (ORDER) if len(xo) == 4: dpts = [pya.DPoint(xo[i], yo[i]) for i in range(len(xo))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) xo = [] yo = [] r = r - (w + gap) # Draw the Bus Waveguides #Draw Bus WG # to go back to the initial point for Multi-box drawing, ger the first adjusted r value r = self.r const = math.floor(2 * pi * r / (s1 + s2)) #if doesn't divide evenly, replace r with best possible r if ((2 * pi * r) % (s1 + s2) != 0): r = const * (s1 + s2) / (2 * pi) #calulate ideal length of bus bus_length = busL #bus_length = self.cell.bbox().height()*dbu +pitch*2 constant = math.ceil(bus_length / (s1 + s2)) if bus_length % (s1 + s2) != 0: bus_length = constant * (s1 + s2) for ii in range(0, int(row)): xo = [(r + w / 2 + gap2 + ii * (w + gap)), (r + w / 2 + gap2 + w + ii * (w + gap)), (r + w / 2 + gap2 + w + ii * (w + gap)), (r + w / 2 + gap2 + ii * (w + gap))] yo = [0, 0, s1, s1] dpts = [pya.DPoint(xo[i], yo[i]) for i in range(len(xo))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) # draw the bus waveguide for i in range(0, int(math.ceil((constant) / 2))): yu = [yo[j] + i * pitch for j in range(len(yo))] yd = [yo[j] - i * pitch for j in range(len(yo))] dpts = [pya.DPoint(xo[i], yu[i]) for i in range(len(xo))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) dpts = [pya.DPoint(xo[i], yd[i]) for i in range(len(xo))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) # draw the tapers from waveguide to SWG xtu = [ ((r + w / 2 + gap2 + ii * (w + gap)) + (w - 0.06) / 2), ((r + w / 2 + gap2 + ii * (w + gap)) + (w - 0.06) / 2 + 0.06), ((r + w / 2 + gap2 + ii * (w + gap)) + w + gap / 2), ((r + w / 2 + gap2 + ii * (w + gap)) - gap / 2) ] ytu = [(yu[3] - taperL), (yu[3] - taperL), (yu[3]), (yu[3])] dpts = [pya.DPoint(xtu[i], ytu[i]) for i in range(len(xtu))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) ytd = [(yd[1] + taperL), (yd[1] + taperL), (yd[1]), (yd[1])] dpts = [pya.DPoint(xtu[i], ytd[i]) for i in range(len(xtu))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) # taper connections from multi-tapers to std WG xTu = [(r + w / 2 + gap2 - gap / 2), (r + w / 2 + gap2 - gap / 2 + row * (gap + w)), (r + w / 2 + gap2 + row * (gap + w) / 2 + 0.25), (r + w / 2 + gap2 + row * (gap + w) / 2 - 0.25)] yTu = [(yu[3]), (yu[3]), (yu[3] + taperL), (yu[3] + taperL)] dpts = [pya.DPoint(xTu[i], yTu[i]) for i in range(len(xTu))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) yTd = [(yd[1]), (yd[1]), (yd[1] - taperL), (yd[1] - taperL)] dpts = [pya.DPoint(xTu[i], yTd[i]) for i in range(len(xTu))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) # add std WG if 2 * r >= busL + 2 * taperL: xstdu = [(r + w / 2 + gap2 + row * (gap + w) / 2 - 0.25), (r + w / 2 + gap2 + row * (gap + w) / 2 + 0.25), (r + w / 2 + gap2 + row * (gap + w) / 2 + 0.25), (r + w / 2 + gap2 + row * (gap + w) / 2 - 0.25)] ystdu = [(yu[3] + taperL), (yu[3] + taperL), (yu[3] + r - busL / 2 + 1), (yu[3] + r - busL / 2 + 1)] dpts = [pya.DPoint(xstdu[i], ystdu[i]) for i in range(len(xstdu))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) ystdd = [(yd[1] - taperL), (yd[1] - taperL), (yd[1] - r + busL / 2 - 1), (yd[1] - r + busL / 2 - 1)] dpts = [pya.DPoint(xstdu[i], ystdd[i]) for i in range(len(xstdu))] dpolygon = DPolygon(dpts) element = Polygon.from_dpoly(dpolygon * (1.0 / dbu)) shapes(LayerSiN).insert(element) else: xstdu = xTu ystdu = yTu ystdd = yTd #DEV BOX half_l = (self.cell.bbox().width() - row * (gap + w) / dbu - gap2 / dbu + (gap / 2) / dbu) / 2 half_r = self.cell.bbox().width() - half_l dev = Box(-half_l, ystdd[-1] / dbu - 1, half_r, ystdu[-1] / dbu + 1) shapes(LayerDevRecN).insert(dev) dev_width = self.cell.bbox().width() / 2 if 2 * r >= busL + 2 * taperL: dev_up = yu[-1] / dbu + taperL / dbu + (yu[3] + r - busL / 2 + 1 - (yu[3] + taperL)) / dbu dev_down = yd[-4] / dbu - taperL / dbu - (yu[3] + r - busL / 2 + 1 - (yu[3] + taperL)) / dbu else: dev_up = yu[-1] / dbu + taperL / dbu dev_down = yd[-4] / dbu - taperL / dbu # Create the pins on the waveguides, as short paths: from SiEPIC._globals import PIN_LENGTH as pin_length w = to_itype(self.w, dbu) gap = to_itype(self.gap, dbu) bus_length = to_itype(bus_length / 2, dbu) #Pin1 #t = Trans(Trans.R0, dev_width-w/2,dev_up) t = Trans(Trans.R0, xstdu[-1] / dbu + 251, dev_up + 1) pin = Path([Point(0, -pin_length / 2), Point(0, pin_length / 2)], 500) #500 is width of std WG 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 print(dev_up) print(dev_up * dbu) #Pin2 t = Trans(Trans.R0, xstdu[-1] / dbu + 251, dev_down - 1) pin = Path([Point(0, pin_length / 2), Point(0, -pin_length / 2)], 500) 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