def init_primitives( self ): Z0 = CPW( self.bl_vert.width, self.bl_vert.gap, DPoint(0,0), DPoint(0,0) ) Z1 = CPW( self.bl_hor.width, self.bl_hor.gap, DPoint(0,0), DPoint(0,0) ) self.tj_BL = TJunction_112( Z0,Z1, DPoint(0,0) + DPoint(0,Z0.b), Trans( Trans.M0 ) ) self.bl_buttom = self.bl_hor.__class__( Z1, self.tj_BL.connections[2], self.bl_hor.params, trans_in=Trans(Trans.M0) ) self.tj_BR = TJunction_112( Z0,Z1, self.bl_buttom.end + DPoint( Z0.b, Z1.b/2 ), Trans( Trans.R180 ) ) self.bl_left = self.bl_vert.__class__( Z0, self.tj_BL.connections[1], self.bl_vert.params, trans_in=Trans(Trans.R90) ) self.tj_TL = TJunction_112( Z0,Z1, self.bl_left.end + DPoint( -Z0.b/2,0 ) ) self.bl_top = self.bl_hor.__class__( Z1, self.tj_TL.connections[2], self.bl_hor.params ) self.tj_TR = TJunction_112( Z0,Z1, self.bl_top.end + DPoint( Z0.b,-Z1.b/2), Trans( Trans.R180*Trans.M0 ) ) self.bl_right = self.bl_vert.__class__( Z0, self.tj_TR.connections[1], self.bl_vert.params, trans_in=Trans(Trans.R270) ) self.primitives = {"tj_BL":self.tj_BL,"bl_buttom":self.bl_buttom,"tj_BR":self.tj_BR,"bl_left":self.bl_left, "tj_TL":self.tj_TL,"bl_top":self.bl_top,"tj_TR":self.tj_TR,"bl_right":self.bl_right}
def __init__(self, origin, trans_in=None): ## MUST BE IMPLEMENTED ## self.connections = [] # DPoint list with possible connection points self.angle_connections = [] #list with angle of connecting elements self.connection_ptrs = [] # pointers to connected structures represented by their class instances ## MUST BE IMLPEMENTED END ## self.origin = origin self.metal_region = Region() self.empty_region = Region() self.metal_regions = {} self.empty_regions = {} self.metal_regions["default"] = self.metal_region self.empty_regions["default"] = self.empty_region self.metal_region.merged_semantics = False self.empty_region.merged_semantics = False self.DCplxTrans_init = None self.ICplxTrans_init = None if( trans_in is not None ): # if( isinstance( trans_in, ICplxTrans ) ): <==== FORBIDDEN if( isinstance( trans_in, DCplxTrans ) ): self.DCplxTrans_init = trans_in self.ICplxTrans_init = ICplxTrans().from_dtrans( trans_in ) elif( isinstance( trans_in, CplxTrans ) ): self.DCplxTrans_init = DCplxTrans().from_itrans( trans_in ) self.ICplxTrans_init = ICplxTrans().from_trans( trans_in ) elif( isinstance( trans_in, DTrans ) ): self.DCplxTrans_init = DCplxTrans( trans_in, 1 ) self.ICplxTrans_init = ICplxTrans( Trans().from_dtrans( trans_in ), 1 ) elif( isinstance( trans_in, Trans ) ): self.DCplxTrans_init = DCplxTrans( DTrans().from_itrans( trans_in ), 1 ) self.ICplxTrans_init = ICplxTrans( trans_in, 1 ) self._init_regions_trans()
def __init__(self, origin, trans_in=None, inverse=False): ## MUST BE IMPLEMENTED ## self.connections = [] # DPoint list with possible connection points self.connection_edges = [ ] # indexes of edges that are intended to connect to other polygons # indexes in "self.connection_edges" where Sonnet ports # should be placed self.sonnet_port_connections = [] self.angle_connections = [] # list with angle of connecting elements ## MUST BE IMLPEMENTED END ## self.connection_ptrs = [ ] # pointers to connected structures represented by their class instances self.origin = origin self.inverse = inverse # TODO: after Region.insert() and/or? metal_region + other_region # there is width problem that initial region has dimensions # Region().bbox() = ((-1,-1,1,1)) or something like that # Hence, if you wish to take Region.bbox() of the resulting region # You will get incorrect value due to initial region having # something "blank" at the creation moment. This may be solved # by either shrinking resulting region to shapes it contains, # or by refusing of usage of empty `Region()`s self.metal_region = Region() self.empty_region = Region() self.metal_regions = OrderedDict() self.empty_regions = OrderedDict() self.metal_regions["default"] = self.metal_region self.empty_regions["default"] = self.empty_region self.metal_region.merged_semantics = True self.empty_region.merged_semantics = True self.DCplxTrans_init = None self.ICplxTrans_init = None if (trans_in is not None): # TODO: update with Klayouts new rules. # if( isinstance( trans_in, ICplxTrans ) ): <==== FORBIDDEN if (isinstance(trans_in, DCplxTrans)): self.DCplxTrans_init = trans_in self.ICplxTrans_init = ICplxTrans().from_dtrans(trans_in) elif (isinstance(trans_in, CplxTrans)): self.DCplxTrans_init = DCplxTrans().from_itrans(trans_in) self.ICplxTrans_init = ICplxTrans().from_trans(trans_in) elif (isinstance(trans_in, DTrans)): self.DCplxTrans_init = DCplxTrans(trans_in, 1) self.ICplxTrans_init = ICplxTrans( Trans().from_dtrans(trans_in), 1) elif (isinstance(trans_in, Trans)): self.DCplxTrans_init = DCplxTrans( DTrans().from_itrans(trans_in), 1) self.ICplxTrans_init = ICplxTrans(trans_in, 1) elif (isinstance(trans_in, ICplxTrans)): # not tested 14.08.2021 self.DCplxTrans_init = DCplxTrans(trans_in) self.ICplxTrans_init = trans_in self._geometry_parameters = OrderedDict() self._init_regions_trans()
def __init__(self, origin, trans_in=None, inverse=False): ## MUST BE IMPLEMENTED ## self.connections = [] # DPoint list with possible connection points self.connection_edges = [ ] # indexes of edges that are intended to connect to other polygons # indexes in "self.connection_edges" where Sonnet ports # should be placed self.sonnet_port_connections = [] self.angle_connections = [] # list with angle of connecting elements ## MUST BE IMLPEMENTED END ## self.connection_ptrs = [ ] # pointers to connected structures represented by their class instances self.origin = origin self.inverse = inverse self.metal_region = Region() self.empty_region = Region() self.metal_regions = OrderedDict() self.empty_regions = OrderedDict() self.metal_regions["default"] = self.metal_region self.empty_regions["default"] = self.empty_region self.metal_region.merged_semantics = True self.empty_region.merged_semantics = True self.DCplxTrans_init = None self.ICplxTrans_init = None if (trans_in is not None): # if( isinstance( trans_in, ICplxTrans ) ): <==== FORBIDDEN if (isinstance(trans_in, DCplxTrans)): self.DCplxTrans_init = trans_in self.ICplxTrans_init = ICplxTrans().from_dtrans(trans_in) elif (isinstance(trans_in, CplxTrans)): self.DCplxTrans_init = DCplxTrans().from_itrans(trans_in) self.ICplxTrans_init = ICplxTrans().from_trans(trans_in) elif (isinstance(trans_in, DTrans)): self.DCplxTrans_init = DCplxTrans(trans_in, 1) self.ICplxTrans_init = ICplxTrans( Trans().from_dtrans(trans_in), 1) elif (isinstance(trans_in, Trans)): self.DCplxTrans_init = DCplxTrans( DTrans().from_itrans(trans_in), 1) self.ICplxTrans_init = ICplxTrans(trans_in, 1) self._geometry_parameters = OrderedDict() self._init_regions_trans()
def init_primitives(self): self.connections = [DPoint(0, 0), self.dr] self.angle_connections = [0, 0] self.coplanar1 = CPW(self.width, self.gap, DPoint(0, 0), DPoint(0, 0) + DPoint(self.L1, 0), self.gndWidth) self.arc1 = CPWArc(self.coplanar1, self.coplanar1.end, self.R1, self.gamma, self.gndWidth, Trans(Trans.M0)) self.coplanar2 = CPW( self.width, self.gap, self.arc1.end, self.arc1.end + DPoint(cos(self.gamma), -sin(self.gamma)) * self.L2, self.gndWidth) self.arc2 = CPWArc(self.coplanar1, self.coplanar2.end, self.R2, self.gamma, self.gndWidth, DCplxTrans(1, -self.gamma * 180 / pi, False, 0, 0)) self.coplanar3 = CPW(self.width, self.gap, self.arc2.end, self.arc2.end + DPoint(L3, 0), self.gndWidth) self.arc3 = CPWArc(self.coplanar1, self.coplanar3.end, self.R2, self.gamma, self.gndWidth) self.coplanar4 = CPW( self.width, self.gap, self.arc3.end, self.arc3.end + DPoint(cos(self.gamma), sin(self.gamma)) * self.L2, self.gndWidth) self.arc4 = CPWArc(self.coplanar1, self.coplanar4.end, self.R1, self.gamma, self.gndWidth, DCplxTrans(1, self.gamma * 180 / pi, True, 0, 0)) self.coplanar5 = CPW(self.width, self.gap, self.arc4.end, self.arc4.end + DPoint(self.L1, 0), self.gndWidth) self.primitives = { "coplanar1": self.coplanar1, "arc1": self.arc1, "coplanar2": self.coplanar2, "arc2": self.arc2, "coplanar3": self.coplanar3, "arc3": self.arc3, "coplanar4": self.coplanar4, "arc4": self.arc4, "coplanar5": self.coplanar5 }
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
empties.append( empty ) qbit.place( cell, layer_photo, layer_el ) qbits.append(qbit) # place top array of resonators with qBits N_top = N_bottom - 1 delta = 1e6 step_top = step_bot resonators = [] qbits = [] empties = [] for i in range( N_top ): point = DPoint( contact_L + delta + step_bot/2 + i*step_top, CHIP.dy/2 + (Z0.width + Z_res.width)/2 + toLine ) worm = EMResonator_TL2Qbit_worm( Z_res, point, L_coupling[i + N_bottom], L1[i + N_bottom], r, L2, N, Trans( Trans.M0 ) ) worm.place( cell, layer_photo ) resonators.append( worm ) qbit_params = [a[i+N_bottom],b[i+N_bottom], jos1_b,jos1_a,f1,d1, jos2_b,jos2_a,f2,d2, w, dCap,gap, square_a, dSquares, alum_over, B1_width] dy_qbit = -(worm.cop_tail.dr.abs() - square_a)/2 - square_a qbit_start = worm.end + DPoint( B1_width/2,0 ) qbit = QBit_Flux_Сshunted_3JJ( worm.end + DPoint( qbit_coupling_gap + Z_res.width/2, dy_qbit ) , qbit_params, DCplxTrans( 1,90,False,0,0 ) ) qbit_bbox = pya.DBox().from_ibox( qbit.metal_regions["photo"].bbox() ) p1 = qbit.origin + DPoint(-qbit_coupling_gap,qbit.square_a/2) p2 = p1 + DPoint( qbit_bbox.width() + qbit_coupling_gap + qbit_gnd_gap, 0 ) empty = CPW( 0, (square_a + 2*qbit_gnd_gap)/2, p1, p2 ) empty.place( cell, layer_photo )
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
qbits = [] empties = [] for i in range(N_top): point = DPoint(contact_L + delta + step_bot / 2 + i * step_top, CHIP.dy / 2 + Z0.b / 3) L_coupling = 100e3 L1 = 280e3 r = 50e3 L2 = 270e3 N = 4 width_res = 4.8e3 gap_res = 2.6e3 Z_res = CPW(width_res, gap_res, origin, origin) worm = EMResonator_TL2Qbit_worm(Z_res, point, L_coupling, L1_list[i + N_bottom], r, L2, N, gnd_width, Trans(Trans.M0)) worm.place(cell, layer_photo) resonators.append(worm) qbit_params = [ a_list[N_bottom + i], a_list[N_bottom + i], jos1_b, jos1_a, f1, d1, jos2_b, jos2_a, f2, d2, w, B1_width, B1_height, B2_width, B5_width, B6_width, B6_height, B7_width, B7_height, dCap, gap ] qbit_start = worm.end + DPoint(B1_width / 2, 0) qbit = QBit_Flux_2(qbit_start, qbit_params, DCplxTrans(1, 180, False, 0, 0)) qbit.place(cell, layer_el) qbits.append(qbit) qbit_bbox = pya.DBox().from_ibox(qbit.metal_region.bbox())
def init_regions(self): self.metal_regions["photo"] = Region() self.empty_regions["photo"] = Region() self.metal_regions["ebeam"] = Region() self.empty_regions["ebeam"] = Region() self.metal_regions["patch"] = Region() self.empty_regions["patch"] = Region() self.metal_regions["litho"] = Region() self.empty_regions["litho"] = Region() w_frame, g_frame = self._frame_cpw_params.width, self._frame_cpw_params.gap l_frame = self._frame_length metal_points1 = [ DPoint(g_frame, g_frame), DPoint(g_frame + w_frame, g_frame), DPoint(g_frame + w_frame, g_frame + l_frame), DPoint(g_frame + w_frame / 2 + 3e3, g_frame + l_frame), DPoint(g_frame + w_frame / 2 + 3e3, g_frame + l_frame - 7e3), DPoint(g_frame + w_frame / 2 - 3e3, g_frame + l_frame - 7e3), DPoint(g_frame + w_frame / 2 - 3e3, g_frame + l_frame), DPoint(g_frame, g_frame + l_frame) ] metal_poly1 = DSimplePolygon(metal_points1) self.metal_regions["photo"].insert(metal_poly1) metal_points2 = [ DPoint(g_frame, 2 * g_frame + l_frame), DPoint(g_frame + w_frame / 2 - 3e3, 2 * g_frame + l_frame), DPoint(g_frame + w_frame / 2 - 3e3, 2 * g_frame + l_frame + 7e3), DPoint(g_frame + w_frame / 2 + 3e3, 2 * g_frame + l_frame + 7e3), DPoint(g_frame + w_frame / 2 + 3e3, 2 * g_frame + l_frame), DPoint(g_frame + w_frame, 2 * g_frame + l_frame), DPoint(g_frame + w_frame, 2 * g_frame + 2 * l_frame), DPoint(g_frame, 2 * g_frame + 2 * l_frame) ] metal_poly2 = DSimplePolygon(metal_points2) self.metal_regions["photo"].insert(metal_poly2) protect_points = [ DPoint(0, 0), DPoint(2 * g_frame + w_frame, 0), DPoint(2 * g_frame + w_frame, 3 * g_frame + 2 * l_frame), DPoint(0, 3 * g_frame + 2 * l_frame) ] protect_poly = DSimplePolygon(protect_points) protect_region = Region(protect_poly) empty_region = protect_region - self.metal_regions["photo"] self.empty_regions["photo"].insert(empty_region) self.connections = [ DPoint(0, 0), DPoint(g_frame + 0.5 * w_frame, 1.5 * g_frame + l_frame) ] if not self._use_cell: squid = SQUIDManhattan(self.connections[1], self._w_JJ, self._h_JJ, \ self._asymmetry, 180, self._JJ_site_span * 1.5, \ squid_width_top=6.2e3, squid_width_bottom=4e3) if self._first_jj and self._second_jj: squid_metal = squid.metal_region self.metal_regions["ebeam"].insert(squid_metal) elif self._first_jj: rec = [ self.connections[1] + DPoint(0, -self._JJ_site_span / 2), self.connections[1] + DPoint(self._JJ_site_span / 2, -self._JJ_site_span / 2), self.connections[1] + DPoint(self._JJ_site_span / 2, self._JJ_site_span / 2), self.connections[1] + DPoint(0, self._JJ_site_span / 2), ] self.metal_regions["ebeam"].insert(squid.metal_region) self.empty_regions["ebeam"].insert(Region(DSimplePolygon(rec))) elif self._second_jj: rec = [ self.connections[1] + DPoint(0, -self._JJ_site_span / 2), self.connections[1] + DPoint(-self._JJ_site_span / 2, -self._JJ_site_span / 2), self.connections[1] + DPoint(-self._JJ_site_span / 2, self._JJ_site_span / 2), self.connections[1] + DPoint(0, self._JJ_site_span / 2), ] self.metal_regions["ebeam"].insert(squid.metal_region) self.empty_regions["ebeam"].insert(Region(DSimplePolygon(rec))) else: squid = SQUIDManhattan(DPoint(0, 0), self._w_JJ, self._h_JJ, \ self._asymmetry, 180, self._JJ_site_span * 1.5, \ squid_width_top=6.2e3, squid_width_bottom=4e3) # instance = Instance() # print(squid._cell.cell_index()) trans = Trans(int(self._origin.x + g_frame + 0.5 * w_frame), int(self._origin.y + 1.5 * g_frame + l_frame)) arr = CellInstArray(squid._cell.cell_index(), trans) # print(arr.size()) # instance.cell_inst = arr app = pya.Application.instance() cur_cell = app.main_window().current_view().active_cellview().cell cur_cell.insert(arr) rec1_points = [ DPoint(g_frame + w_frame / 2 - 4e3, 2 * g_frame + l_frame - 1e3), DPoint(g_frame + w_frame / 2 - 4e3, 2 * g_frame + l_frame + 12e3), DPoint(g_frame + w_frame / 2 + 4e3, 2 * g_frame + l_frame + 12e3), DPoint(g_frame + w_frame / 2 + 4e3, 2 * g_frame + l_frame - 1e3) ] rec1_poly = DSimplePolygon(rec1_points) rec2_points = [ DPoint(g_frame + w_frame / 2 - 4e3, g_frame + l_frame - 12e3), DPoint(g_frame + w_frame / 2 - 4e3, g_frame + l_frame + 1e3), DPoint(g_frame + w_frame / 2 + 4e3, g_frame + l_frame + 1e3), DPoint(g_frame + w_frame / 2 + 4e3, g_frame + l_frame - 12e3) ] rec2_poly = DSimplePolygon(rec2_points) self.metal_regions["ebeam"].insert(squid.metal_region) self.metal_regions["ebeam"].insert(rec1_poly) self.metal_regions["ebeam"].insert(rec2_poly) rec1_points = [ DPoint(g_frame + w_frame / 2 - 6e3, 2 * g_frame + l_frame + 3.5e3), DPoint(g_frame + w_frame / 2 - 6e3, 2 * g_frame + l_frame + 18.5e3), DPoint(g_frame + w_frame / 2 + 6e3, 2 * g_frame + l_frame + 18.5e3), DPoint(g_frame + w_frame / 2 + 6e3, 2 * g_frame + l_frame + 3.5e3) ] rec2_points = [ DPoint(g_frame + w_frame / 2 - 6e3, g_frame + l_frame - 18.5e3), DPoint(g_frame + w_frame / 2 - 6e3, g_frame + l_frame - 3.5e3), DPoint(g_frame + w_frame / 2 + 6e3, g_frame + l_frame - 3.5e3), DPoint(g_frame + w_frame / 2 + 6e3, g_frame + l_frame - 18.5e3) ] rec1_poly = DSimplePolygon(rec1_points) rec2_poly = DSimplePolygon(rec2_points) self.metal_regions["patch"].insert(rec1_poly) self.metal_regions["patch"].insert(rec2_poly) rec1_points = [ DPoint(g_frame + w_frame / 2 - 150e3, g_frame + l_frame - 150e3), DPoint(g_frame + w_frame / 2 - 150e3, g_frame + l_frame + 150e3), DPoint(g_frame + w_frame / 2 + 150e3, g_frame + l_frame + 150e3), DPoint(g_frame + w_frame / 2 + 150e3, g_frame + l_frame - 150e3) ] rec1_poly = DSimplePolygon(rec1_points) self.metal_regions["litho"].insert(rec1_poly)
def init_primitives( self ): self.connections = [DPoint(0,0),self.dr] self.angle_connections = [0,0] self.coplanar1 = CPW( self.width, self.gap, DPoint(0,0), DPoint(0,0) + DPoint(self.L1,0), self.gndWidth ) self.arc1 = CPW_arc( self.coplanar1, self.coplanar1.end, self.R1, self.gamma1, self.gndWidth, Trans( Trans.M0 ) ) self.coplanar2 = CPW( self.width, self.gap, self.arc1.end, self.arc1.end + DPoint( cos(self.gamma1),-sin(self.gamma1) )*self.L2, self.gndWidth ) self.arc2 = CPW_arc( self.coplanar1, self.coplanar2.end, self.R2, self.gamma1, self.gndWidth, DCplxTrans( 1,-self.gamma1*180/pi,False,0,0 ) ) self.coplanar3 = CPW( self.width, self.gap, self.arc2.end, self.arc2.end + DPoint( self.L3, 0 ), self.gndWidth ) self.arc3 = CPW_arc( self.coplanar1, self.coplanar3.end, self.R3, self.gamma2, self.gndWidth ) self.coplanar4 = CPW( self.width, self.gap, self.arc3.end, self.arc3.end + DPoint( cos(self.gamma2),sin(self.gamma2) )*self.L4, self.gndWidth ) self.arc4 = CPW_arc( self.coplanar1, self.coplanar4.end, self.R4, self.gamma2, self.gndWidth, DCplxTrans( 1,self.gamma2*180/pi,True,0,0 ) ) self.coplanar5 = CPW( self.width, self.gap, self.arc4.end, self.arc4.end + DPoint(self.L5,0), self.gndWidth ) self.arc5 = CPW_arc( self.coplanar1, self.coplanar5.end, self.R4, self.gamma2, self.gndWidth, Trans( Trans.M0 ) ) self.coplanar6 = CPW( self.width, self.gap, self.arc5.end, self.arc5.end + DPoint( cos(self.gamma2),-sin(self.gamma2) )*self.L4, self.gndWidth ) self.arc6 = CPW_arc( self.coplanar1, self.coplanar6.end, self.R3, self.gamma2, self.gndWidth, DCplxTrans( 1,-self.gamma2*180/pi, False,0,0 ) ) self.coplanar7 = CPW( self.width, self.gap, self.arc6.end, self.arc6.end + DPoint( self.L3,0 ), self.gndWidth ) self.arc7 = CPW_arc( self.coplanar1, self.coplanar7.end, self.R2, self.gamma1, self.gndWidth ) self.coplanar8 = CPW( self.width, self.gap, self.arc7.end, self.arc7.end + DPoint( cos(self.gamma1),sin(self.gamma1) )*self.L2, self.gndWidth ) self.arc8 = CPW_arc( self.coplanar1, self.coplanar8.end, self.R1, self.gamma1, self.gndWidth, DCplxTrans( 1,self.gamma1*180/pi,True,0,0 ) ) self.coplanar9 = CPW( self.width, self.gap, self.arc8.end, self.arc8.end + DPoint( self.L1,0 ), self.gndWidth ) self.primitives = {"coplanar1":self.coplanar1,"coplanar2":self.coplanar2,"coplanar3":self.coplanar3, "coplanar4":self.coplanar4,"coplanar5":self.coplanar5,"coplanar6":self.coplanar6, "coplanar7":self.coplanar7,"coplanar8":self.coplanar8,"coplanar9":self.coplanar9, "arc1":self.arc1,"arc2":self.arc2,"arc3":self.arc3,"arc4":self.arc4, "arc5":self.arc5,"arc6":self.arc6,"arc7":self.arc7,"arc8":self.arc8}
def init_regions(self): self.metal_regions["photo"] = Region() self.empty_regions["photo"] = Region() self.metal_regions["ebeam"] = Region() self.empty_regions["ebeam"] = Region() w_frame, g_frame = self._frame_cpw_params.width, self._frame_cpw_params.gap l_frame = self._frame_length metal_points1 = [ DPoint(g_frame, g_frame), DPoint(g_frame + w_frame, g_frame), DPoint(g_frame + w_frame, g_frame + l_frame), DPoint(g_frame, g_frame + l_frame) ] metal_poly1 = DSimplePolygon(metal_points1) self.metal_regions["photo"].insert(metal_poly1) metal_points2 = [ DPoint(g_frame, 2 * g_frame + l_frame), DPoint(g_frame + w_frame, 2 * g_frame + l_frame), DPoint(g_frame + w_frame, 2 * g_frame + 2 * l_frame), DPoint(g_frame, 2 * g_frame + 2 * l_frame) ] metal_poly2 = DSimplePolygon(metal_points2) self.metal_regions["photo"].insert(metal_poly2) protect_points = [ DPoint(0, 0), DPoint(2 * g_frame + w_frame, 0), DPoint(2 * g_frame + w_frame, 3 * g_frame + 2 * l_frame), DPoint(0, 3 * g_frame + 2 * l_frame) ] protect_poly = DSimplePolygon(protect_points) protect_region = Region(protect_poly) empty_region = protect_region - self.metal_regions["photo"] self.empty_regions["photo"].insert(empty_region) self.connections = [ DPoint(0, 0), DPoint(g_frame + 0.5 * w_frame, 1.5 * g_frame + l_frame) ] if not self._use_cell: squid = SQUIDManhattan(self.connections[1], self._w_JJ, self._h_JJ, \ self._asymmetry, 150, self._JJ_site_span * 1.5, \ squid_width_top=6.2e3, squid_width_bottom=4e3) self.metal_regions["ebeam"].insert(squid.metal_region) else: squid = SQUIDManhattan(DPoint(0, 0), self._w_JJ, self._h_JJ, \ self._asymmetry, 150, self._JJ_site_span * 1.5, \ squid_width_top=6.2e3, squid_width_bottom=4e3) # instance = Instance() # print(squid._cell.cell_index()) trans = Trans(int(self._origin.x + g_frame + 0.5 * w_frame), int(self._origin.y + 1.5 * g_frame + l_frame)) arr = CellInstArray(squid._cell.cell_index(), trans) # print(arr.size()) # instance.cell_inst = arr app = pya.Application.instance() cur_cell = app.main_window().current_view().active_cellview().cell cur_cell.insert(arr)
def init_regions(self): self.metal_regions["photo"] = Region() self.empty_regions["photo"] = Region() self.metal_regions["ebeam"] = Region() self.empty_regions["ebeam"] = Region() w_tmon, g_tmon = self.tmon_cpw_params.width, self.tmon_cpw_params.gap arms_len = self._arms_len JJ_arm_len = self._JJ_arm_len JJ_site_span = self._JJ_site_span coupling_pads_len = self._coupling_pads_len h_JJ, w_JJ = self._h_JJ, self._w_JJ asymmetry = self._asymmetry protect_points = [DPoint(0, 0), DPoint(-arms_len+g_tmon, 0), DPoint(-arms_len+g_tmon, -coupling_pads_len/2+w_tmon/2), DPoint(-arms_len-g_tmon-w_tmon, -coupling_pads_len/2+w_tmon/2), DPoint(-arms_len-g_tmon-w_tmon, coupling_pads_len/2+w_tmon/2+2*g_tmon), DPoint(-arms_len+g_tmon, coupling_pads_len/2+w_tmon/2+2*g_tmon), DPoint(-arms_len+g_tmon, 2*g_tmon+w_tmon), DPoint(-w_tmon/2-g_tmon, 2*g_tmon+w_tmon), DPoint(-w_tmon/2-g_tmon, g_tmon+w_tmon+JJ_arm_len+JJ_site_span), \ DPoint(w_tmon/2+g_tmon, g_tmon+w_tmon+JJ_arm_len+JJ_site_span), DPoint(w_tmon/2+g_tmon, 2*g_tmon+w_tmon), DPoint(arms_len-g_tmon, 2*g_tmon+w_tmon), DPoint(arms_len-g_tmon, coupling_pads_len/2+w_tmon/2+2*g_tmon), DPoint(arms_len+g_tmon+w_tmon, coupling_pads_len/2+w_tmon/2+2*g_tmon), DPoint(arms_len+g_tmon+w_tmon, -coupling_pads_len/2+w_tmon/2), DPoint(arms_len-g_tmon, -coupling_pads_len/2+w_tmon/2), DPoint(arms_len-g_tmon, 0)] protect_region = Region(DSimplePolygon(protect_points)) metal_points = [DPoint(0, g_tmon), DPoint(-arms_len, g_tmon), DPoint(-arms_len, g_tmon-coupling_pads_len/2+w_tmon/2), DPoint(-arms_len-w_tmon, g_tmon-coupling_pads_len/2+w_tmon/2), DPoint(-arms_len-w_tmon, g_tmon+coupling_pads_len/2+w_tmon/2), DPoint(-arms_len, g_tmon+coupling_pads_len/2+w_tmon/2), DPoint(-arms_len, g_tmon+w_tmon), DPoint(-w_tmon/2, g_tmon+w_tmon), DPoint(-w_tmon/2, g_tmon+w_tmon+JJ_arm_len), \ DPoint(w_tmon/2, g_tmon+w_tmon+JJ_arm_len), DPoint(w_tmon/2, g_tmon+w_tmon), DPoint(arms_len, g_tmon+w_tmon), DPoint(arms_len, g_tmon+coupling_pads_len/2+w_tmon/2), DPoint(arms_len+w_tmon, g_tmon+coupling_pads_len/2+w_tmon/2), DPoint(arms_len+w_tmon, g_tmon-coupling_pads_len/2+w_tmon/2), DPoint(arms_len, g_tmon-coupling_pads_len/2+w_tmon/2), DPoint(arms_len, g_tmon)] metal_poly = DSimplePolygon(metal_points) self.metal_regions["photo"].insert(metal_poly) empty_region = protect_region - self.metal_regions["photo"] self.empty_regions["photo"].insert(empty_region) if not self._use_cell: squid = SQUIDManhattan(DPoint(0, g_tmon + w_tmon + JJ_arm_len + JJ_site_span / 2), self._w_JJ, self._h_JJ, \ self._asymmetry, 150, JJ_site_span * 1.5, \ squid_width_top=6.2e3, squid_width_bottom=4e3) self.metal_regions["ebeam"].insert(squid.metal_region) else: squid = SQUIDManhattan(DPoint(0, 0), self._w_JJ, self._h_JJ, \ self._asymmetry, 150, JJ_site_span * 1.5, \ squid_width_top=6.2e3, squid_width_bottom=4e3) # instance = Instance() # print(squid._cell.cell_index()) trans = Trans( int(self._origin.x), int(self._origin.y + g_tmon + w_tmon + JJ_arm_len + JJ_site_span / 2)) arr = CellInstArray(squid._cell.cell_index(), trans) # print(arr.size()) # instance.cell_inst = arr app = pya.Application.instance() cur_cell = app.main_window().current_view().active_cellview().cell cur_cell.insert(arr) self.connections = [ DPoint(0, 0), DPoint(0, g_tmon + w_tmon + JJ_arm_len + JJ_site_span) ]
def layout_waveguide4(cell, dpath, waveguide_type, debug=True): if debug: print('SiEPIC.utils.layout.layout_waveguide4: ') print(' - waveguide_type: %s' % (waveguide_type)) # get the path and clean it up layout = cell.layout() dbu = layout.dbu dpath = dpath.to_itype(dbu) dpath.unique_points() pts = dpath.get_points() dpts = dpath.get_dpoints() # Load the technology and all waveguide types from SiEPIC.utils import load_Waveguides_by_Tech technology_name = layout.technology_name waveguide_types = load_Waveguides_by_Tech(technology_name) if debug: print(' - technology_name: %s' % (technology_name)) print(' - waveguide_types: %s' % (waveguide_types)) # Load parameters for the chosen waveguide type params = [t for t in waveguide_types if t['name'] == waveguide_type] if type(params) == type([]) and len(params) > 0: params = params[0] else: print('error: waveguide type not found in PDK waveguides') raise Exception( 'error: waveguide type (%s) not found in PDK waveguides' % waveguide_type) # compound waveguide types: if 'compound_waveguide' in params: # find the singlemode and multimode waveguides: if 'singlemode' in params['compound_waveguide']: singlemode = params['compound_waveguide']['singlemode'] else: raise Exception( 'error: waveguide type (%s) does not have singlemode defined' % waveguide_type) if 'multimode' in params['compound_waveguide']: multimode = params['compound_waveguide']['multimode'] else: raise Exception( 'error: waveguide type (%s) does not have multimode defined' % waveguide_type) params_singlemode = [ t for t in waveguide_types if t['name'] == singlemode ] params_multimode = [ t for t in waveguide_types if t['name'] == multimode ] if type(params_singlemode) == type([]) and len(params_singlemode) > 0: params_singlemode = params_singlemode[0] else: raise Exception( 'error: waveguide type (%s) not found in PDK waveguides' % singlemode) if type(params_multimode) == type([]) and len(params_multimode) > 0: params_multimode = params_multimode[0] else: raise Exception( 'error: waveguide type (%s) not found in PDK waveguides' % multimode) # find the taper if 'taper_library' in params[ 'compound_waveguide'] and 'taper_cell' in params[ 'compound_waveguide']: taper = layout.create_cell( params['compound_waveguide']['taper_cell'], params['compound_waveguide']['taper_library']) if not taper: raise Exception( 'Cannot import cell %s : %s' % (params['compound_waveguide']['taper_cell'], params['compound_waveguide']['taper_library'])) else: raise Exception( 'error: waveguide type (%s) does not have taper cell and library defined' % waveguide_type) from pya import Trans, CellInstArray ''' find sections of waveguides that are larger than (2 x radius + 2 x taper_length) - insert two tapers - insert multimode straight section - insert singlemode waveguides (including bends) before ''' import math from SiEPIC.extend import to_itype from pya import Point radius = to_itype(params_singlemode['radius'], dbu) taper_length = taper.find_pins()[0].center.distance( taper.find_pins()[1].center) min_length = 2 * radius + 2 * taper_length offset = radius wg_sm_segment_pts = [] wg_last = 0 waveguide_length = 0 for ii in range(1, len(dpts)): start_point = dpts[ii - 1] end_point = dpts[ii] distance_points = end_point.distance(start_point) if distance_points < min_length: # single mode segment, keep track if ii == 1: wg_sm_segment_pts.append(pts[ii - 1]) wg_sm_segment_pts.append(pts[ii]) if ii == len(pts) - 1: subcell = layout.create_cell("Waveguide_sm_%s" % ii) cell.insert(CellInstArray(subcell.cell_index(), Trans())) waveguide_length += layout_waveguide3(subcell, wg_sm_segment_pts, params_singlemode, debug=True) else: # insert two tapers and multimode waveguide angle = math.atan2( (end_point.y - start_point.y), (end_point.x - start_point.x)) / math.pi * 180 if ii == 1: wg_first = offset else: wg_first = 0 if ii == len(pts) - 1: wg_last = offset if round(angle) % 360 == 270.0: t = Trans(Trans.R270, start_point.x, start_point.y - offset + wg_first) t2 = Trans(Trans.R90, end_point.x, end_point.y + offset - wg_last) wg_start_pt = Point( start_point.x, start_point.y - offset - taper_length + wg_first) wg_end_pt = Point( end_point.x, end_point.y + offset + taper_length - wg_last) if round(angle) % 360 == 90.0: t = Trans(Trans.R90, start_point.x, start_point.y + offset - wg_first) t2 = Trans(Trans.R270, end_point.x, end_point.y - offset + wg_last) wg_start_pt = Point( start_point.x, start_point.y + offset + taper_length - wg_first) wg_end_pt = Point( end_point.x, end_point.y - offset - taper_length + wg_last) if round(angle) % 360 == 180.0: t = Trans(Trans.R180, start_point.x - offset + wg_first, start_point.y) t2 = Trans(Trans.R0, end_point.x + offset - wg_last, end_point.y) wg_start_pt = Point( start_point.x - offset - taper_length + wg_first, start_point.y) wg_end_pt = Point( end_point.x + offset + taper_length - wg_last, end_point.y) if round(angle) % 360 == 0.0: t = Trans(Trans.R0, start_point.x + offset - wg_first, start_point.y) t2 = Trans(Trans.R180, end_point.x - offset + wg_last, end_point.y) wg_start_pt = Point( start_point.x + offset + taper_length - wg_first, start_point.y) wg_end_pt = Point( end_point.x - offset - taper_length + wg_last, end_point.y) inst_taper = cell.insert(CellInstArray(taper.cell_index(), t)) inst_taper = cell.insert(CellInstArray(taper.cell_index(), t2)) waveguide_length += taper_length * 2 subcell = layout.create_cell("Waveguide_mm_%s" % ii) cell.insert(CellInstArray(subcell.cell_index(), Trans())) waveguide_length += layout_waveguide3(subcell, [wg_start_pt, wg_end_pt], params_multimode, debug=True) # compound segment if ii > 1: wg_sm_segment_pts.append(t.disp.to_p()) subcell = layout.create_cell("Waveguide_sm_%s" % ii) cell.insert(CellInstArray(subcell.cell_index(), Trans())) waveguide_length += layout_waveguide3(subcell, wg_sm_segment_pts, params_singlemode, debug=True) wg_sm_segment_pts = [t2.disp.to_p(), pts[ii]] else: wg_sm_segment_pts = [t2.disp.to_p(), pts[ii]] else: # primitive waveguide type waveguide_length = layout_waveguide3(cell, pts, params, debug=True) return waveguide_length
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
def layout_waveguide3(cell, pts, params, debug=True): if debug: print('SiEPIC.utils.layout.layout_waveguide3: ') layout = cell.layout() dbu = layout.dbu technology_name = layout.technology_name from SiEPIC.utils import get_technology_by_name TECHNOLOGY = get_technology_by_name(technology_name) from SiEPIC.extend import to_itype wg_width = to_itype(params['width'], dbu) radius = float(params['radius']) model = params['model'] cellName = 'Waveguide2' CML = params['CML'] if debug: print(' - waveguide params: %s' % (params)) if 'compound_waveguide' in params: print('error: this function cannot handle compound waveguides') raise Exception( 'error: this function cannot handle compound waveguides (%s)' % waveguide_type) # draw the waveguide waveguide_length = layout_waveguide2( TECHNOLOGY, layout, cell, [wg['layer'] for wg in params['component']], [wg['width'] for wg in params['component']], [wg['offset'] for wg in params['component']], pts, radius, params['adiabatic'], params['bezier']) # Draw the marking layers from SiEPIC.utils import angle_vector LayerPinRecN = layout.layer(TECHNOLOGY['PinRec']) make_pin(cell, 'opt1', pts[0], wg_width, LayerPinRecN, angle_vector(pts[0] - pts[1]) % 360) make_pin(cell, 'opt2', pts[-1], wg_width, LayerPinRecN, angle_vector(pts[-1] - pts[-2]) % 360) from pya import Trans, Text, Path, Point ''' t1 = Trans(angle_vector(pts[0]-pts[1])/90, False, pts[0]) cell.shapes(LayerPinRecN).insert(Path([Point(-10, 0), Point(10, 0)], wg_width).transformed(t1)) cell.shapes(LayerPinRecN).insert(Text("opt1", t1, 0.3/dbu, -1)) t = Trans(angle_vector(pts[-1]-pts[-2])/90, False, pts[-1]) cell.shapes(LayerPinRecN).insert(Path([Point(-10, 0), Point(10, 0)], wg_width).transformed(t)) cell.shapes(LayerPinRecN).insert(Text("opt2", t, 0.3/dbu, -1)) ''' LayerDevRecN = layout.layer(TECHNOLOGY['DevRec']) # Compact model information angle_vec = angle_vector(pts[0] - pts[1]) / 90 halign = 0 # left angle = 0 dpt = Point(0, 0) if angle_vec == 0: # horizontal halign = 2 # right angle = 0 dpt = Point(0, 0.2 * wg_width) if angle_vec == 2: # horizontal halign = 0 # left angle = 0 dpt = Point(0, 0.2 * wg_width) if angle_vec == 1: # vertical halign = 2 # right angle = 1 dpt = Point(0.2 * wg_width, 0) if angle_vec == -1: # vertical halign = 0 # left angle = 1 dpt = Point(0.2 * wg_width, 0) pt2 = pts[0] + dpt pt3 = pts[0] - dpt pt4 = pts[0] - 6 * dpt pt5 = pts[0] + 2 * dpt t = Trans(angle, False, pt3) text = Text('Lumerical_INTERCONNECT_library=Design kits/%s' % CML, t, 0.1 * wg_width, -1) text.halign = halign shape = cell.shapes(LayerDevRecN).insert(text) t = Trans(angle, False, pt2) text = Text('Component=%s' % model, t, 0.1 * wg_width, -1) text.halign = halign shape = cell.shapes(LayerDevRecN).insert(text) t = Trans(angle, False, pt5) text = Text('cellName=%s' % cellName, t, 0.1 * wg_width, -1) text.halign = halign shape = cell.shapes(LayerDevRecN).insert(text) t = Trans(angle, False, pts[0]) pts_txt = str([[round(p.to_dtype(dbu).x, 3), round(p.to_dtype(dbu).y, 3)] for p in pts]).replace(', ', ',') text = Text( 'Spice_param:wg_length=%.9f wg_width=%.3g points="%s" radius=%.3g' % (waveguide_length * 1e-6, wg_width * 1e-9, pts_txt, radius * 1e-6), t, 0.1 * wg_width, -1) text.halign = halign shape = cell.shapes(LayerDevRecN).insert(text) t = Trans(angle, False, pt4) text = Text('Length=%.3f (microns)' % (waveguide_length), t, 0.5 * wg_width, -1) text.halign = halign shape = cell.shapes(LayerDevRecN).insert(text) return waveguide_length
qbits.append(qbit) # place top array of resonators with qBits N_top = N_bottom - 1 delta = 1e6 step_top = step_bot resonators = [] qbits = [] empties = [] for i in range(N_top): point = DPoint(contact_L + delta + step_bot / 2 + i * step_top, CHIP.dy / 2 + (Z0.width + Z_res.width) / 2 + toLine) worm = EMResonator_TL2Qbit_worm(Z_res, point, L_coupling[i + N_bottom], L1[i + N_bottom], r, L2, N, Trans(Trans.M0)) worm.place(cell, layer_photo) resonators.append(worm) qbit_params = [ a[i + N_bottom], b[i + N_bottom], jos1_b, jos1_a, f1, d1, jos2_b, jos2_a, f2, d2, w, dCap, gap, square_a, dSquares, alum_over, B1_width ] dy_qbit = -(worm.cop_tail.dr.abs() - square_a) / 2 - square_a qbit_start = worm.end + DPoint(B1_width / 2, 0) qbit = QBit_Flux_Сshunted_3JJ( worm.end + DPoint(qbit_coupling_gap + Z_res.width / 2, dy_qbit), qbit_params, DCplxTrans(1, 90, False, 0, 0)) qbit_bbox = pya.DBox().from_ibox(qbit.metal_regions["photo"].bbox()) p1 = qbit.origin + DPoint(-qbit_coupling_gap, qbit.square_a / 2)
ly.prune_subcells(cell_top.cell_index(), 1000) #%%Define Layer mapping and floor plan LayerSiN = ly.layer(lib[layer_Si220]) fpLayerN = cell_top.layout().layer(lib[layer_floorplan]) TextLayerN = cell_top.layout().layer(lib[layer_text]) # Draw the floor plan ly_height = 350 ly_width = 600 cell_top.shapes(fpLayerN).insert(Box(0, 0, ly_width / dbu, ly_height / dbu)) #%%Import Grating couplers GC_imported = ly.create_cell("Grating_Coupler_13deg_TE_1550_Oxide", pdk).cell_index() GC_pitch = 127 t = Trans(Trans.R0, 0.5 * ly_width / dbu, (0.5 * ly_height - GC_pitch / 2) / dbu) cell_top.insert( CellInstArray(GC_imported, t, DPoint(0, GC_pitch).to_itype(dbu), Point(0, 0), 2, 1)) #%%draw waveguide connecting grating couplers path = [[0.5 * ly_width, 0.5 * ly_height - GC_pitch / 2]] # start point path.append([0.5 * ly_width + 50, 0.5 * ly_height - GC_pitch / 2]) path.append([0.5 * ly_width + 50, 0.5 * ly_height + GC_pitch / 2]) path.append([0.5 * ly_width, 0.5 * ly_height + GC_pitch / 2]) # end point path = DPath([DPoint(each[0], each[1]) for each in path], 0.5) path = path.to_itype(dbu) pts = path.get_points() widths = [0.5] layers = ['Waveguide']