def init_primitives(self): R_index = 0 L_index = 0 origin = DPoint(0,0) prev_primitive_end = origin prev_primitive_end_angle = 0 for i, symbol in enumerate(self._shape_string): if( symbol == 'R' ): if( self._turn_angles[R_index] > 0 ): turn_radius = self._turn_radiuses[R_index] else: turn_radius =-self._turn_radiuses[R_index] cpw_arc = CPW_arc(self._cpw_parameters[i], prev_primitive_end, turn_radius, self._turn_angles[R_index], trans_in = DCplxTrans(1, prev_primitive_end_angle*180/pi, False, 0, 0)) self.primitives["arc_"+str(R_index)] = cpw_arc R_index += 1 elif symbol == 'L': # Turns are reducing segments' lengths so as if there were no roundings at all # next 'R' segment if exists if( i+1 < self._N_elements and self._shape_string[i+1] == 'R' and abs(self._turn_angles[R_index]) < pi ): coeff = abs(tan(self._turn_angles[R_index]/2)) self._segment_lengths[L_index] -= self._turn_radiuses[R_index]*coeff # previous 'R' segment if exists if( i-1 > 0 and self._shape_string[i-1] == 'R' and abs(self._turn_angles[R_index-1]) < pi ): coeff = abs(tan(self._turn_angles[R_index-1]/2)) self._segment_lengths[L_index] -= self._turn_radiuses[R_index-1]*coeff #if( self._segment_lengths[L_index] < 0 ): # print(self._segment_lengths[L_index]) # print("CPW_RL_Path warning: segment length is less than zero") # print("L_index = {}".format(L_index)) cpw = CPW(self._cpw_parameters[i].width, self._cpw_parameters[i].gap, prev_primitive_end, prev_primitive_end + DPoint(self._segment_lengths[L_index], 0), trans_in=DCplxTrans(1, prev_primitive_end_angle*180/pi, False, 0, 0)) self.primitives["cpw_"+str(L_index)] = cpw L_index += 1 primitive = list(self.primitives.values())[i] prev_primitive_end = primitive.end prev_primitive_end_angle = primitive.alpha_end self.connections = [origin, list(self.primitives.values())[-1].end] self.angle_connections = [0, list(self.primitives.values())[-1].alpha_end]
def init_primitives( self ): self.arc1 = CPW_arc( self.Z0, DPoint(0,0), self.R1, pi/4 ) self.cop1 = CPW( self.Z0.width, self.Z0.gap, self.arc1.end, self.arc1.end + DPoint( sin(pi/4), sin(pi/4) )*self.L1 ) self.arc2 = CPW_arc( self.Z0, self.cop1.end, self.R2, pi/4, trans_in=DCplxTrans( 1,45,False,0,0 ) ) self.cop2 = CPW( self.Z0.width, self.Z0.gap, self.arc2.end, self.arc2.end + DPoint( 0,self.L2 ) ) self.connections = [self.arc1.start,self.cop2.end] self.angle_connections = [self.arc1.alpha_start, self.cop2.alpha_end] self.primitives = {"arc1":self.arc1, "cop1":self.cop1, "arc2":self.arc2, "cop2":self.cop2}
def _init_regions_trans(self): self.init_regions() # must be implemented in every subclass dr_origin = DSimplePolygon([DPoint(0, 0)]) if (self.DCplxTrans_init is not None): # constructor trans displacement dCplxTrans_temp = DCplxTrans(1, 0, False, self.DCplxTrans_init.disp) self.make_trans(dCplxTrans_temp) dr_origin.transform(dCplxTrans_temp) # rest of the constructor trans functions dCplxTrans_temp = self.DCplxTrans_init.dup() dCplxTrans_temp.disp = DPoint(0, 0) self.make_trans(dCplxTrans_temp) dr_origin.transform(dCplxTrans_temp) # translation to the old origin (self.connections are already contain proper values) self.make_trans(DCplxTrans(1, 0, False, self.origin)) # move to the origin self.origin += dr_origin.point(0)
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.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 = CPW_arc(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 = CPW_arc(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 = CPW_arc(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 _init_primitives_trans(self): self.init_primitives() # must be implemented in every subclass dr_origin = DSimplePolygon([DPoint(0, 0)]) if (self.DCplxTrans_init is not None): # constructor trans displacement dCplxTrans_temp = DCplxTrans(1, 0, False, self.DCplxTrans_init.disp) self.make_trans(dCplxTrans_temp) dr_origin.transform(dCplxTrans_temp) # rest of the constructor trans functions dCplxTrans_temp = self.DCplxTrans_init.dup() dCplxTrans_temp.disp = DPoint(0, 0) self.make_trans(dCplxTrans_temp) dr_origin.transform(dCplxTrans_temp) dCplxTrans_temp = DCplxTrans(1, 0, False, self.origin) self.make_trans(dCplxTrans_temp) #move to the origin self.origin += dr_origin.point(0) # FOLLOWING CYCLE GIVES WRONG INFO ABOUT FILLED AND ERASED AREAS for element in self.primitives.values(): self.metal_region += element.metal_region self.empty_region += element.empty_region
def init_regions( self ): self.connections = [DPoint(0,0),self.dr] self.start = DPoint(0,0) self.end = self.start + self.dr alpha = atan2( self.dr.y, self.dr.x ) self.angle_connections = [alpha,alpha] alpha_trans = ICplxTrans().from_dtrans( DCplxTrans( 1,alpha*180/pi,False, self.start ) ) metal_poly = DSimplePolygon( [DPoint(0,-self.width/2), DPoint(self.dr.abs(),-self.width/2), DPoint(self.dr.abs(),self.width/2), DPoint(0,self.width/2)] ) self.connection_edges = [3,1] self.metal_region.insert( klayout.db.SimplePolygon().from_dpoly( metal_poly ) ) if( self.gap != 0 ): self.empty_region.insert( klayout.db.Box( Point().from_dpoint(DPoint(0,self.width/2)), Point().from_dpoint(DPoint( self.dr.abs(), self.width/2 + self.gap )) ) ) self.empty_region.insert( klayout.db.Box( Point().from_dpoint(DPoint(0,-self.width/2-self.gap)), Point().from_dpoint(DPoint( self.dr.abs(), -self.width/2 )) ) ) self.metal_region.transform( alpha_trans ) self.empty_region.transform( alpha_trans )
def init_regions( self ): self.connections = [DPoint(0,0),self.dr] self.start = DPoint(0,0) self.end = self.start + self.dr self.L0 = self.start.distance(self.end) / (self.N_air_bridges +1) alpha = atan2( self.dr.y, self.dr.x ) self.angle_connections = [alpha,alpha] alpha_trans = ICplxTrans().from_dtrans( DCplxTrans( 1,alpha*180/pi,False, self.start ) ) for i in range(self.N_air_bridges): self.air_bridge = klayout.db.DBox( DPoint((i+1)*self.L0, -self.b/2 - 2e3), DPoint((i+1)*self.L0+2e3, self.b/2 + 2e3) ) self.metal_region.insert( klayout.db.Box().from_dbox( self.air_bridge ) ) self.air_bridge_2 = klayout.db.DBox( DPoint((i+1)*self.L0-self.b/4+1e3, -self.b/2 - 2e3), DPoint((i+1)*self.L0+1e3+self.b/4, -self.b/2 - 4e3) ) self.metal_region.insert( klayout.db.Box().from_dbox( self.air_bridge_2 ) ) self.air_bridge_3 = klayout.db.DBox( DPoint((i+1)*self.L0-self.b/4+1e3, self.b/2 + 2e3), DPoint((i+1)*self.L0+1e3+self.b/4, self.b/2 + 4e3) ) self.metal_region.insert( klayout.db.Box().from_dbox( self.air_bridge_3 ) ) self.metal_region.transform( alpha_trans )
def init_regions(self): self.connections = [DPoint(0, 0), DPoint(self.dr.abs(), 0)] self.angle_connections = [0, 0] alpha = atan2(self.dr.y, self.dr.x) self.angle_connections = [alpha,alpha] alpha_trans = DCplxTrans(1, alpha*180/pi, False, 0, 0) m_poly = DSimplePolygon([DPoint(0,-self.Z0.width/2), DPoint(self.dr.abs(), -self.Z1.width/2), DPoint(self.dr.abs(),self.Z1.width/2), DPoint(0,self.Z0.width/2)] ) e_poly1 = DSimplePolygon([DPoint(0,-self.Z0.b/2), DPoint(self.dr.abs(), -self.Z1.b/2), DPoint(self.dr.abs(),-self.Z1.width/2), DPoint(0,-self.Z0.width/2)] ) e_poly2 = DSimplePolygon([DPoint(0,self.Z0.b/2), DPoint(self.dr.abs(),self.Z1.b/2), DPoint(self.dr.abs(),self.Z1.width/2), DPoint(0,self.Z0.width/2)] ) m_poly.transform(alpha_trans) e_poly1.transform(alpha_trans) e_poly2.transform(alpha_trans) self.metal_region.insert(SimplePolygon.from_dpoly(m_poly)) self.empty_region.insert(SimplePolygon.from_dpoly(e_poly1)) self.empty_region.insert(SimplePolygon.from_dpoly(e_poly2))
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 = {} self.empty_regions = {} 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._init_regions_trans()
def init_primitives(self): origin = DPoint(0, 0) self.c_wave = CWave(origin, self.r_out, self.dr, self.n_semiwaves, self.s, self.alpha, self.r_curve, n_pts=self.n_pts_cwave) self.primitives["c_wave"] = self.c_wave Z1_start = origin + DPoint(0, self.r_in + self.gap1 + self.width1 / 2) Z1_end = Z1_start + DPoint(0, -self.gap1 - self.width1 / 2 + self.dr) self.cpw1 = CPW(self.Z1.width, self.Z1.gap, Z1_start, Z1_end) self.primitives["cpw1"] = self.cpw1 Z2_start = origin - DPoint(0, self.r_in + self.gap2 + self.width2 / 2) Z2_end = Z2_start - DPoint(0, -self.gap2 - self.width2 / 2 + self.dr) self.cpw2 = CPW(self.Z2.width, self.Z2.gap, Z2_start, Z2_end) self.primitives["cpw2"] = self.cpw2 if isinstance(self.params, dict): self.c_wave_2_cpw_adapter = CWave2CPW(self.c_wave, self.params, n_pts=self.n_pts_arcs) else: # not recommended self.c_wave_2_cpw_adapter = CWave2CPW(self.c_wave, self.params[7:15], n_pts=self.n_pts_arcs) self.primitives["c_wave_2_cpw_adapter"] = self.c_wave_2_cpw_adapter p_squid = None squid_trans_in = None if not self.squid_pos: if (self.c_wave.n_segments % 2 == 1): squid_trans_in = DCplxTrans(1, -self.c_wave.alpha * 180 / pi, False, 0, 0) p_squid = origin else: squid_trans_in = None second_parity = self.c_wave.n_segments / 2 y_shift = self.c_wave.L0 * sin( self.c_wave.alpha) - self.c_wave.r_curve * ( 1 / cos(self.c_wave.alpha) - 1) if (second_parity % 2 == 0): p_squid = origin + DPoint(0, y_shift) else: p_squid = origin + DPoint(0, -y_shift) else: squid_trans_in = None p_squid = origin - DPoint( self.squid_pos * (self.r_out - 1.8 * self.dr), 0) self.squid = Squid(p_squid, self.squid_params, trans_in=squid_trans_in) self.primitives["qubit"] = self.squid self.connections = [Z1_end, Z2_end] self.angle_connections = [pi / 2, 3 / 2 * pi]
class Element_Base(): ''' @brief: base class for simple single-layer or multi-layer elements and objects that are consisting of several polygons. metal_region polygons will be added to the design empty_region polygons will be erased from the background with metal region polygons already added. ''' 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 = {} self.empty_regions = {} 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._init_regions_trans() def init_regions(self): raise NotImplementedError # first it makes trans_init displacement # then the rest of the trans_init # then displacement of the current state to the origin # after all, origin should be updated def _init_regions_trans(self): self.init_regions() # must be implemented in every subclass dr_origin = DSimplePolygon([DPoint(0, 0)]) if (self.DCplxTrans_init is not None): # constructor trans displacement dCplxTrans_temp = DCplxTrans(1, 0, False, self.DCplxTrans_init.disp) self.make_trans(dCplxTrans_temp) dr_origin.transform(dCplxTrans_temp) # rest of the constructor trans functions dCplxTrans_temp = self.DCplxTrans_init.dup() dCplxTrans_temp.disp = DPoint(0, 0) self.make_trans(dCplxTrans_temp) dr_origin.transform(dCplxTrans_temp) # translation to the old origin (self.connections are already contain proper values) self.make_trans(DCplxTrans(1, 0, False, self.origin)) # move to the origin self.origin += dr_origin.point(0) def make_trans(self, dCplxTrans): if (dCplxTrans is not None): iCplxTrans = ICplxTrans().from_dtrans(dCplxTrans) self.metal_region.transform(iCplxTrans) self.empty_region.transform(iCplxTrans) self._update_connections(dCplxTrans) self._update_alpha(dCplxTrans) def _update_connections(self, dCplxTrans): if (dCplxTrans is not None): # the problem is, if i construct polygon with multiple points # their order in poly_temp.each_point() doesn't coinside with the # order of the list that was passed to the polygon constructor # so, when i perform transformation and try to read new values through poly_temp.each_point() # they values are rearranged # solution is: i need to create polygon for each point personally, and the initial order presists for i, pt in enumerate(self.connections): poly_temp = DSimplePolygon([pt]) poly_temp.transform(dCplxTrans) self.connections[i] = poly_temp.point(0) def _update_alpha(self, dCplxTrans): if (dCplxTrans is not None): dCplxTrans_temp = dCplxTrans.dup() dCplxTrans_temp.disp = DPoint(0, 0) for i, alpha in enumerate(self.angle_connections): poly_temp = DSimplePolygon([DPoint(cos(alpha), sin(alpha))]) poly_temp.transform(dCplxTrans_temp) pt = poly_temp.point(0) self.angle_connections[i] = atan2(pt.y, pt.x) def _update_origin(self, dCplxTrans): if (dCplxTrans is not None): poly_temp = DSimplePolygon([self.origin]) poly_temp.transform(dCplxTrans) self.origin = poly_temp.point(0) def place(self, dest, layer_i=-1, region_name=None, merge=False): r_cell = None metal_region = None empty_region = None if (region_name == None): metal_region = self.metal_region empty_region = self.empty_region else: if (region_name in self.metal_regions): metal_region = self.metal_regions[region_name] else: metal_region = Region() if (region_name in self.empty_regions): empty_region = self.empty_regions[region_name] else: empty_region = Region() if (layer_i != -1): r_cell = Region(dest.begin_shapes_rec(layer_i)) temp_i = dest.layout().layer( klayout.db.LayerInfo(PROGRAM.LAYER1_NUM, 0)) r_cell += metal_region r_cell -= empty_region if (merge is True): r_cell.merge() dest.shapes(temp_i).insert(r_cell) dest.layout().clear_layer(layer_i) dest.layout().move_layer(temp_i, layer_i) dest.layout().delete_layer(temp_i) if (layer_i == -1 ): # dest is interpreted as instance of Region() class dest += metal_region dest -= empty_region if (merge is True): dest.merge() def add_sonnet_port(self, connection_idx): ''' @brief: sets internal marker that during export to Sonnet the port should be placed at the connection edge with an index 'connection_idx' ''' print(self.connections) self.sonnet_port_connections.append(self.connections[connection_idx])
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 }