def init_half(self, origin, side=-1): # side = -1 is left, 1 is right pars = self.params j_width = pars.j_width_1 if side < 0 else pars.j_width_2 j_length = pars.j_length if side < 0 else pars.j_length_2 suff = "_left" if side < 0 else "_right" up_st_gap = pars.sq_area / (2 * pars.sq_len) # exact correction in first row # additional extension to isolate jj's from intermediate bottom polygons # without correction horizontal faces of jj's will be adjacent # to thick intemediate polygons low_st_gap = up_st_gap + ((pars.j_length + pars.j_length_2) / 2 + pars.intermediate_width) + \ 2 * pars.intermediate_width ### upper and lower vertical intermediate and jj leads ### ## top leads ## upper_leads_extension = j_width / 4 # upper intemediate lead up_st_start = self.primitives["p_ext_up"].connections[1] + \ DVector(side * up_st_gap / 2, 0) up_st_stop = origin + \ DVector(side * up_st_gap / 2, pars.bridge / 2 + upper_leads_extension) # top jj lead self.primitives["upp_st" + suff] = Kolbaska(up_st_start, up_st_stop, j_width, upper_leads_extension) # top intermediate lead upper_thin_part_len = 4 * pars.bridge + pars.intermediate_width / 2 self.primitives["upp_st_thick" + suff] = Kolbaska( up_st_start, up_st_stop + DPoint(0, upper_thin_part_len), pars.intermediate_width, pars.intermediate_width / 2) ## bottom leads ## low_st_start = self.primitives["p_ext_down"].connections[1] + \ DVector(side * low_st_gap / 2, 0) low_st_stop = origin + \ DVector(side * (low_st_gap / 2 + 2 * pars.intermediate_width), -pars.bridge / 2 - pars.intermediate_width / 2) len_ly = (low_st_stop - low_st_start).y # bottom intermediate lead self.primitives["low_st" + suff] = CPW_RL_Path( low_st_start, 'LR', CPWParameters(pars.intermediate_width, 0), pars.intermediate_width / 2, [len_ly], [side * pi / 2], trans_in=DTrans.R90) # bottom jj lead (horizontal) low_st_end = self.primitives["low_st" + suff].connections[1] low_st_jj_start = low_st_end + DPoint( 0, -j_length / 2 + pars.intermediate_width / 2) low_st_jj_stop = low_st_jj_start + DPoint(-side * pars.b_ext, 0) self.primitives["low_st_jj" + suff] = Kolbaska(low_st_jj_start, low_st_jj_stop, j_length, j_length / 2)
def init_primitives(self): self.arc1 = CPW_arc(self.Z0, DPoint(0, 0), -self.r, pi / 2) self.primitives["arc1"] = self.arc1 p1 = self.arc1.end p2 = self.arc1.end + DPoint(0, -self.L0) self.cop_vertical = CPW(start=p1, end=p2, cpw_params=self.Z0) # open end tail face is separated from ground by `b = width + 2*gap` self.primitives["cop_vertical"] = self.cop_vertical # draw the open-circuited "tail" self.cpw_end_open_RLPath = CPW_RL_Path( self.cop_vertical.end, self.tail_shape, cpw_parameters=self.Z0, turn_radiuses=self.tail_turn_radiuses, segment_lengths=self.tail_segment_lengths, turn_angles=self.tail_turn_angles, trans_in=self.tail_trans_in ) self.primitives["cpw_end_open_RLPath"] = self.cpw_end_open_RLPath self.cpw_end_open_gap = CPW( 0, self.Z0.b / 2, self.cpw_end_open_RLPath.end, self.cpw_end_open_RLPath.end - DPoint(0, self.Z0.b) ) self.primitives["cpw_end_open_gap"] = self.cpw_end_open_gap # making coil name = "coil0" setattr(self, name, Coil_type_1(self.Z0, DPoint(0, 0), self.L_coupling, self.r, self.L1)) self.primitives[name] = getattr(self, name) # coils filling for i in range(self.N): name = "coil" + str(i + 1) setattr(self, name, Coil_type_1(self.Z0, DPoint(-self.L1 + self.L_coupling, -(i + 1) * (4 * self.r)), self.L1, self.r, self.L1)) self.primitives[name] = getattr(self, name) self.connections = [DPoint(0, 0), self.cpw_end_open_RLPath.end] self.angle_connections = [0, self.cpw_end_open_RLPath.alpha_end]
origin = DPoint(CHIP.dx / 2, CHIP.dy / 2) bridge = Bridge1(origin) bridge.place(cell, layer_photo1_bridges, "bridges_1") bridge.place(cell, layer_photo2_bridges, "bridges_2") p1 = DPoint(1 / 4 * CHIP.dx, CHIP.dy / 5) p2 = DPoint(3 / 4 * CHIP.dx, CHIP.dy / 4) width = 20e3 gap = 10e3 cpw = CPW(width, gap, p1, p2) cpw.place(cell, layer_photo) bridges_step = 50e3 Bridge1.bridgify_CPW(cpw, bridges_step, cell=cell, bridge_layer1=layer_photo1_bridges, bridge_layer2=layer_photo2_bridges) z2 = CPWParameters(width, gap) cpw2 = CPW_RL_Path(DPoint(400e3, 400e3), "LRLRL", z2, 60e3, 100e3, [pi / 4, pi / 3]) cpw2.place(cell, layer_photo) Bridge1.bridgify_CPW(cpw2, bridges_step, cell=cell, bridge_layer1=layer_photo1_bridges, bridge_layer2=layer_photo2_bridges) lv.zoom_fit() ### DRAWING SECTION END ###
def draw_md_and_flux_lines(self): """ Drawing of md (microwave drive) and flux tuning lines for 5 qubits Returns ------- """ contact_pads = self.contact_pads ctr_line_turn_radius = 100e3 xmon_center = self.xmons[-1].center xmon_x_distance = self.xmon_x_distance cross_width_y = self.cross_width_y cross_width_x = self.cross_width_x cross_len_x = self.cross_len_x cross_len_y = self.cross_len_y cross_gnd_gap_y = self.cross_gnd_gap_y cross_gnd_gap_x = self.cross_gnd_gap_x width_res = self.Z_res.width tmp_reg = self.region_ph z_md_fl_corrected = CPWParameters( self.z_md_fl.width + 2 * FABRICATION.OVERETCHING, self.z_md_fl.gap - 2 * FABRICATION.OVERETCHING ) shift_fl_y = self.shift_fl_y shift_md_x = self.shift_md_x shift_md_y = self.shift_md_y md0_md5_gnd = 5e3 flux_end_width = self.cross_width_x + 2 * self.cross_gnd_gap_x - 2 * FABRICATION.OVERETCHING md_transition = 25e3 md_z1_params = z_md_fl_corrected md_z1_length = 245e3 shift_md_x_side = md_z1_length + md_transition + md_z1_params.b / 2 + cross_len_x + cross_width_x / 2 + cross_gnd_gap_x # place caplanar line 1md self.cpwrl_md1 = CPW_RL_Path( contact_pads[0].end, shape="LRLRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius] * 2, segment_lengths=[ 2 * (-contact_pads[0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16, ( (contact_pads[0].end.y - xmon_center.y) ** 2 + (9 * (-contact_pads[0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16) ** 2 ) ** 0.5, 5 * (-contact_pads[ 0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16 - md0_md5_gnd], turn_angles=[-atan2(contact_pads[0].end.y - xmon_center.y, 9 * (-contact_pads[ 0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16), atan2(contact_pads[0].end.y - xmon_center.y, 9 * (-contact_pads[ 0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16)], trans_in=Trans.R0 ) self.cpwrl_md1.place(tmp_reg) self.cpwrl_md1_end = MDriveLineEnd(list(self.cpwrl_md1.primitives.values())[-1], md_z1_params, md_transition, md_z1_length) self.cpwrl_md1_end.place(tmp_reg) # place caplanar line 1 fl self.cpwrl_fl1 = CPW_RL_Path( contact_pads[1].end, shape="LRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius], segment_lengths=[ -contact_pads[1].end.x + xmon_center.x - 4 * xmon_x_distance - cross_len_x, xmon_center.y - contact_pads[1].end.y - cross_width_x / 2 - cross_gnd_gap_x - z_md_fl_corrected.width + FABRICATION.OVERETCHING ], turn_angles=[pi / 2], trans_in=Trans.R0 ) self.cpwrl_fl1.place(tmp_reg) self.cpwrl_fl1_end = FluxLineEnd(self.cpwrl_fl1.end, z_md_fl_corrected, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl1_end.place(tmp_reg) # place caplanar line 2md self.cpwrl_md2 = CPW_RL_Path( contact_pads[3].end, shape="LRLRLRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius] * 3, segment_lengths=[ (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 4, (-contact_pads[3].end.x + xmon_center.x + shift_md_x - 3 * xmon_x_distance) / 2, ( ( (-contact_pads[3].end.x + xmon_center.x + shift_md_x - 3 * xmon_x_distance) / 2 ) ** 2 + ( 5 * (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 8 ) ** 2 ) ** 0.5, (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 8 ], turn_angles=[-pi / 2, atan2(5 * (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 8, ( -contact_pads[3].end.x + xmon_center.x + shift_md_x - 3 * xmon_x_distance) / 2), pi / 2 - atan2(5 * (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 8, ( -contact_pads[3].end.x + xmon_center.x + shift_md_x - 3 * xmon_x_distance) / 2)], trans_in=Trans.R90 ) self.cpwrl_md2.place(tmp_reg) self.cpwrl_md2_end = MDriveLineEnd( list(self.cpwrl_md2.primitives.values())[-1], md_z1_params, md_transition, md_z1_length ) self.cpwrl_md2_end.place(tmp_reg) # place caplanar line 2 fl self.cpwrl_fl2 = CPW_RL_Path( contact_pads[2].end, shape="LRLRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius] * 2, segment_lengths=[(-contact_pads[2].end.x + xmon_center.x - 3 * xmon_x_distance) / 4, ( (3 * (-contact_pads[2].end.x + xmon_center.x - 3 * xmon_x_distance) / 4) ** 2 + ( 7 * (-contact_pads[2].end.y + xmon_center.y - shift_fl_y) / 8) ** 2) ** 0.5, (-contact_pads[2].end.y + xmon_center.y - shift_fl_y) / 8], turn_angles=[atan2(7 * (-contact_pads[2].end.y + xmon_center.y - shift_fl_y) / 8, 3 * (-contact_pads[2].end.x + xmon_center.x - 3 * xmon_x_distance) / 4), pi / 2 - atan2(7 * (-contact_pads[2].end.y + xmon_center.y - shift_fl_y) / 8, 3 * (-contact_pads[2].end.x + xmon_center.x - 3 * xmon_x_distance) / 4)], trans_in=Trans.R0 ) self.cpwrl_fl2.place(tmp_reg) self.cpwrl_fl2_end = FluxLineEnd(self.cpwrl_fl2.end, z_md_fl_corrected, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl2_end.place(tmp_reg) # place caplanar line 3md self.cpwrl_md3_1 = CPW_RL_Path( contact_pads[5].end, shape="LRLRLRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius] * 3, segment_lengths=[ (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 4, (contact_pads[5].end.x - xmon_center.x - shift_md_x + 2 * xmon_x_distance) / 2, ( ( (contact_pads[5].end.x - xmon_center.x - shift_md_x + 2 * xmon_x_distance) / 2 ) ** 2 + ( 5 * (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 8 ) ** 2 ) ** 0.5 - 400e3, (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 8], turn_angles=[pi / 2, -atan2(5 * (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 8, (contact_pads[5].end.x - xmon_center.x - shift_md_x + 2 * xmon_x_distance) / 2), -pi / 2 + atan2(5 * (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 8, ( contact_pads[5].end.x - xmon_center.x - shift_md_x + 2 * xmon_x_distance) / 2)], trans_in=Trans.R90 ) self.cpwrl_md3_1.place(tmp_reg) dy = self.cpwrl_md2.end.y - self.cpwrl_md3_1.end.y dx = self.cpwrl_md3_1.end.x - (self.xmons[2].center.x + shift_md_x) md3_2_radius = ctr_line_turn_radius - 50e3 self.cpwrl_md3_2 = CPW_RL_Path( self.cpwrl_md3_1.end, shape="LRLR", cpw_parameters=z_md_fl_corrected, turn_radiuses=[md3_2_radius] * 2, segment_lengths=[dy - md3_2_radius, dx], turn_angles=[pi / 2, -pi / 2], trans_in=Trans.R90 ) self.cpwrl_md3_2.place(tmp_reg) self.cpwrl_md3_end = MDriveLineEnd( list(self.cpwrl_md3_2.primitives.values())[-1], md_z1_params, md_transition, md_z1_length ) self.cpwrl_md3_end.place(tmp_reg) # place caplanar line 3 fl fl_l1 = (self.xmons[2].cpw_bempt.end.y - contact_pads[4].end.y) / 4 fl_l3 = fl_l1 dr = self.xmons[2].cpw_bempt.end - contact_pads[4].end dr.y = dr.y - fl_l1 - fl_l3 - z_md_fl_corrected.width turn_angle = atan2(-dr.x, dr.y) fl_l2 = dr.abs() self.cpwrl_fl3 = CPW_RL_Path( self.contact_pads[4].end, shape="LRLRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius] * 2, segment_lengths=[fl_l1, fl_l2, fl_l3], turn_angles=[turn_angle, -turn_angle], trans_in=Trans.R90 ) self.cpwrl_fl3.place(tmp_reg) self.cpwrl_fl3_end = FluxLineEnd(self.cpwrl_fl3.end, z_md_fl_corrected, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl3_end.place(tmp_reg) # place caplanar line 4 md md4_len_y = -contact_pads[7].end.y + xmon_center.y - shift_md_y md4_fl4_dx = 100e3 self.cpwrl_md4 = CPW_RL_Path( contact_pads[7].end, shape="LRLRLRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=ctr_line_turn_radius / 2, segment_lengths=[ contact_pads[7].end.x - xmon_center.x + xmon_x_distance - shift_md_x - md4_fl4_dx, md4_len_y - ctr_line_turn_radius / 2, md4_fl4_dx, ctr_line_turn_radius / 2 ], turn_angles=[-pi / 2, pi / 2, -pi / 2], trans_in=Trans.R180 ) self.cpwrl_md4.place(tmp_reg) self.cpwrl_md4_end = MDriveLineEnd( list(self.cpwrl_md4.primitives.values())[-1], md_z1_params, md_transition, md_z1_length ) self.cpwrl_md4_end.place(tmp_reg) # place caplanar line 4 fl self.cpwrl_fl4 = CPW_RL_Path( contact_pads[6].end, shape="LRLRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius] * 2, segment_lengths=[(contact_pads[6].end.x - xmon_center.x + xmon_x_distance) / 4, ((6 * (-contact_pads[6].end.y + xmon_center.y - shift_fl_y) / 8) ** 2 + (3 * (contact_pads[6].end.x - xmon_center.x + xmon_x_distance) / 4) ** 2) ** 0.5, 2 * (-contact_pads[6].end.y + xmon_center.y - shift_fl_y) / 8], turn_angles=[-atan2(6 * (-contact_pads[6].end.y + xmon_center.y - shift_fl_y) / 8, 3 * (contact_pads[6].end.x - xmon_center.x + xmon_x_distance) / 4), -pi / 2 + atan2(6 * (-contact_pads[6].end.y + xmon_center.y - shift_fl_y) / 8, 3 * (contact_pads[6].end.x - xmon_center.x + xmon_x_distance) / 4)], trans_in=Trans.R180 ) self.cpwrl_fl4.place(tmp_reg) self.cpwrl_fl4_end = FluxLineEnd(self.cpwrl_fl4.end, z_md_fl_corrected, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl4_end.place(tmp_reg) # place caplanar line 5 md md5_l1 = 2 * (contact_pads[9].end.y - xmon_center.y) / 3 md5_dy = 400e3 md5_dx = 400e3 md5_angle = atan2( 2 * (contact_pads[9].end.x - xmon_center.x - shift_md_x_side) / 3, (contact_pads[9].end.y - xmon_center.y) / 3 ) self.cpwrl_md5 = CPW_RL_Path( contact_pads[9].end, shape="LRLRLRLRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius] * 4, segment_lengths=[ md5_dy, md5_dx / sin(pi / 4), md5_l1 - md5_dy - md5_dx / tan(pi / 4) - md5_dx / tan(md5_angle), md5_dx / sin(md5_angle) + ( ( (contact_pads[9].end.y - xmon_center.y) / 3 ) ** 2 + ( 2 * (contact_pads[9].end.x - xmon_center.x - shift_md_x_side) / 3 ) ** 2 ) ** (0.5), (contact_pads[9].end.x - xmon_center.x - shift_md_x_side) / 3 - md0_md5_gnd ], turn_angles=[ pi / 4, -pi / 4, -md5_angle, -(pi / 2 - md5_angle) ], trans_in=Trans.R270 ) # self.cpwrl_md5 = CPW_RL_Path( # contact_pads[9].end, shape="LRLRL", cpw_parameters=z_md_fl_corrected, # turn_radiuses=[ctr_line_turn_radius] * 2, # segment_lengths=[ # md5_l1, # ( # ( # (contact_pads[9].end.y - xmon_center.y) / 3 # ) ** 2 + # ( # 2 * (contact_pads[9].end.x - xmon_center.x - shift_md_x_side) / 3 # ) ** 2 # ) ** (0.5), # (contact_pads[9].end.x - xmon_center.x - shift_md_x_side) / 3 - md0_md5_gnd # ], # turn_angles=[ # md5_angle, # -md5_angle - pi / 2 # ], # trans_in=Trans.R270 # ) self.cpwrl_md5.place(tmp_reg) self.cpwrl_md5_end = MDriveLineEnd( list(self.cpwrl_md5.primitives.values())[-1], md_z1_params, md_transition, md_z1_length ) self.cpwrl_md5_end.place(tmp_reg) # place caplanar line 5 fl self.cpwrl_fl5_1 = CPW_RL_Path( contact_pads[8].end, shape="LRLRLR", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius] * 3, segment_lengths=[ (contact_pads[8].end.x - xmon_center.x) / 4, ((contact_pads[8].end.y - xmon_center.y) + 250e3) / 3 + 50e3, ( (2 * ((contact_pads[8].end.y - xmon_center.y) + 250e3) / 3) ** 2 + ((contact_pads[8].end.x - xmon_center.x) / 2) ** 2 ) ** 0.5 ], turn_angles=[ pi / 2, -atan2((contact_pads[8].end.x - xmon_center.x) / 2, 2 * ((contact_pads[8].end.y - xmon_center.y) + 250e3) / 3), - pi / 2 + atan2((contact_pads[8].end.x - xmon_center.x) / 2, 2 * ((contact_pads[8].end.y - xmon_center.y) + 250e3) / 3) ], trans_in=Trans.R180 ) self.cpwrl_fl5_1.place(tmp_reg) self.cpwrl_fl5_2 = CPW_RL_Path( self.cpwrl_fl5_1.end, shape="LRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius], segment_lengths=[ self.cpwrl_fl5_1.end.x - (self.xmons[4].center.x + cross_width_y / 2 + cross_len_x + cross_gnd_gap_x - flux_end_width / 2), self.xmons[4].center.y - self.cpwrl_fl5_1.end.y - cross_width_x / 2 - cross_gnd_gap_x - z_md_fl_corrected.width + FABRICATION.OVERETCHING ], turn_angles=[-pi / 2], trans_in=Trans.R180 ) self.cpwrl_fl5_2.place(tmp_reg) self.cpwrl_fl5_end = FluxLineEnd(self.cpwrl_fl5_2.end, z_md_fl_corrected, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl5_end.place(tmp_reg)
def draw_readout_waveguide(self): ''' Subdividing horizontal waveguide adjacent to resonators into several waveguides. Even segments of this adjacent waveguide are adjacent to resonators. Bridges will be placed on odd segments later. Returns ------- None ''' # place readout waveguide ro_line_turn_radius = self.ro_line_turn_radius ro_line_dy = self.ro_line_dy ## calculating segment lengths of subdivided coupling part of ro coplanar ## # value that need to be added to `L_coupling` to get width of resonators bbox. def get_res_extension(resonator: EMResonatorTL3QbitWormRLTailXmonFork): return resonator.Z0.b + 2 * resonator.r def get_res_width(resonator: EMResonatorTL3QbitWormRLTailXmonFork): return (resonator.L_coupling + get_res_extension(resonator)) res_line_segments_lengths = [ self.resonators[0].origin.x - self.contact_pads[-1].end.x - get_res_extension(self.resonators[0]) / 2 ] # length from bend to first bbox of first resonator for i, resonator in enumerate(self.resonators[:-1]): resonator_extension = get_res_extension(resonator) resonator_width = get_res_width(resonator) next_resonator_extension = get_res_extension(self.resonators[i + 1]) # order of adding is from left to right (imagine chip geometry in your head to follow) res_line_segments_lengths.extend( [ resonator_width, # `resonator_extension` accounts for the next resonator extension # in this case all resonator's extensions are equal self.resonators_dx - (resonator_width - resonator_extension / 2) - next_resonator_extension / 2 ] ) res_line_segments_lengths.extend( [ get_res_width(self.resonators[-1]), self.resonators_dx / 2 ] ) # first and last segment will have length `self.resonator_dx/2` res_line_total_length = sum(res_line_segments_lengths) segment_lengths = [ro_line_dy] + res_line_segments_lengths + \ [ro_line_dy / 2, res_line_total_length - self.chip.pcb_feedline_d, ro_line_dy / 2] self.cpwrl_ro_line = CPW_RL_Path( self.contact_pads[-1].end, shape="LR" + ''.join(['L'] * len(res_line_segments_lengths)) + "RLRLRL", cpw_parameters=CPWParameters(self.Z0.width + 2 * FABRICATION.OVERETCHING, self.Z0.gap - 2 * FABRICATION.OVERETCHING), turn_radiuses=[ro_line_turn_radius] * 4, segment_lengths=segment_lengths, turn_angles=[pi / 2, pi / 2, pi / 2, -pi / 2], trans_in=Trans.R270 ) self.cpwrl_ro_line.place(self.region_ph)
class Design5Q(ChipDesign): def __init__(self, cell_name): super().__init__(cell_name) info_el2 = pya.LayerInfo(3, 0) # for DC contact deposition self.region_el2 = Region() self.layer_el2 = self.layout.layer(info_el2) info_bridges1 = pya.LayerInfo(4, 0) # bridge photo layer 1 self.region_bridges1 = Region() self.layer_bridges1 = self.layout.layer(info_bridges1) info_bridges2 = pya.LayerInfo(5, 0) # bridge photo layer 2 self.region_bridges2 = Region() self.layer_bridges2 = self.layout.layer(info_bridges2) # layer with polygons that will protect structures located # on the `self.region_el` - e-beam litography layer info_el_protection = pya.LayerInfo(6, 0) self.region_el_protection = Region() self.layer_el_protection = self.layout.layer(info_el_protection) self.lv.add_missing_layers() # has to call it once more to add new layers ### ADDITIONAL VARIABLES SECTION START ### # chip rectangle and contact pads self.chip = CHIP_10x10_12pads self.chip.pcb_gap -= 2 * FABRICATION.OVERETCHING self.chip.pcb_width += 2 * FABRICATION.OVERETCHING self.chip.pcb_Z = CPWParameters(self.chip.pcb_width, self.chip.pcb_gap) self.chip_box: pya.DBox = self.chip.box self.z_md_fl: CPWParameters = CPWParameters(11e3, 5.7e3) # Z = 50.09 E_eff = 6.235 (E = 11.45) self.ro_Z: CPWParameters = self.chip.chip_Z self.contact_pads: list[ContactPad] = self.chip.get_contact_pads( [self.z_md_fl] * 10 + [self.ro_Z] * 2, FABRICATION.OVERETCHING ) # readout line parameters self.ro_line_turn_radius: float = 200e3 self.ro_line_dy: float = 1600e3 self.cpwrl_ro_line: CPW_RL_Path = None self.Z0: CPWParameters = CHIP_10x10_12pads.chip_Z # resonators objects list self.resonators: List[EMResonatorTL3QbitWormRLTailXmonFork] = [] # distance between nearest resonators central conductors centers # constant step between resonators origin points along x-axis. self.resonators_dx: float = 900e3 # resonator parameters self.L_coupling_list: list[float] = [1e3 * x for x in [310, 320, 320, 310, 300]] # corresponding to resonanse freq is linspaced in interval [6,9) GHz self.L0 = 1150e3 self.L1_list = [1e3 * x for x in [60.7218, 91.3339, 133.001, 137.77, 79.9156]] self.r = 60e3 self.N_coils = [3] * len(self.L1_list) self.L2_list = [self.r] * len(self.L1_list) self.L3_list = [0e3] * len(self.L1_list) # to be constructed self.L4_list = [self.r] * len(self.L1_list) self.width_res = 20e3 self.gap_res = 10e3 self.Z_res = CPWParameters(self.width_res, self.gap_res) self.to_line_list = [56e3] * len(self.L1_list) self.fork_metal_width = 10e3 self.fork_gnd_gap = 15e3 self.xmon_fork_gnd_gap = 14e3 # resonator-fork parameters # for coarse C_qr evaluation self.fork_y_spans = [x * 1e3 for x in [8.73781, 78.3046, 26.2982, 84.8277, 35.3751]] # xmon parameters self.xmon_x_distance: float = 545e3 # from simulation of g_12 # for fine C_qr evaluation self.xmon_dys_Cg_coupling = [14e3] * 5 self.xmons: list[XmonCross] = [] self.cross_len_x = 180e3 self.cross_width_x = 60e3 self.cross_gnd_gap_x = 20e3 self.cross_len_y = 155e3 self.cross_width_y = 60e3 self.cross_gnd_gap_y = 20e3 # squids self.squids: List[AsymSquid] = [] self.test_squids: List[AsymSquid] = [] self.el_dc_contacts: List[List[ElementBase, ElementBase]] = [] # md and flux lines attributes self.shift_fl_y = self.cross_len_y + 60e3 self.shift_md_x = 60e3 self.shift_md_y = 510e3 self.cpwrl_md1: CPW_RL_Path = None self.cpwrl_md1_end: MDriveLineEnd = None self.cpwrl_fl1: CPW_RL_Path = None self.cpwrl_fl1_end: FluxLineEnd = None self.cpwrl_md2: CPW_RL_Path = None self.cpwrl_md2_end: MDriveLineEnd = None self.cpwrl_fl2: CPW_RL_Path = None self.cpwrl_fl2_end: FluxLineEnd = None self.cpwrl_md3: CPW_RL_Path = None self.cpwrl_md3_end: MDriveLineEnd = None self.cpwrl_fl3: CPW_RL_Path = None self.cpwrl_fl3_end: FluxLineEnd = None self.cpwrl_md4: CPW_RL_Path = None self.cpwrl_md4_end: MDriveLineEnd = None self.cpwrl_fl4: CPW_RL_Path = None self.cpwrl_fl4_end: FluxLineEnd = None self.cpwrl_md5: CPW_RL_Path = None self.cpwrl_md5_end: MDriveLineEnd = None self.cpwrl_fl5: CPW_RL_Path = None self.cpwrl_fl5_end: FluxLineEnd = None # marks self.marks: List[MarkBolgar] = [] ### ADDITIONAL VARIABLES SECTION END ### def draw(self, design_params=None): self.draw_chip() ''' Only creating object. This is due to the drawing of xmons and resonators require draw xmons, then draw resonators and then draw additional xmons. This is ugly and that how this was before migrating to `ChipDesign` based code structure This is also the reason why `self.__init__` is flooded with design parameters that are used across multiple drawing functions. TODO: This drawings sequence can be decoupled in the future. ''' self.create_resonator_objects() self.draw_readout_waveguide() self.draw_xmons_and_resonators() self.draw_md_and_flux_lines() # self.draw_test_structures() # self.draw_josephson_loops() # self.draw_el_dc_contacts() # self.draw_el_protection() # self.draw_photo_el_marks() # self.draw_bridges() # self.draw_pinning_holes() # self.inverse_destination(self.region_ph) # self.split_polygons_in_layers(max_pts=180) def _transfer_regs2cell(self): # this too methods assumes that all previous drawing # functions are placing their object on regions # in order to avoid extensive copying of the polygons # to/from cell.shapes during the logic operations on # polygons self.cell.shapes(self.layer_ph).insert(self.region_ph) self.cell.shapes(self.layer_el).insert(self.region_el) self.cell.shapes(self.layer_el2).insert(self.region_el2) self.cell.shapes(self.layer_bridges1).insert(self.region_bridges1) self.cell.shapes(self.layer_bridges2).insert(self.region_bridges2) self.cell.shapes(self.layer_el_protection).insert(self.region_el_protection) self.lv.zoom_fit() def draw_chip(self): # self.region_bridges2.insert(self.chip_box) self.region_ph.insert(self.chip_box) for contact_pad in self.contact_pads: contact_pad.place(self.region_ph) def create_resonator_objects(self): # fork at the end of resonator parameters fork_x_span = self.cross_width_y + 2 * (self.xmon_fork_gnd_gap + self.fork_metal_width) ### RESONATORS TAILS CALCULATIONS SECTION START ### # key to the calculations can be found in hand-written format here: # https://drive.google.com/file/d/1wFmv5YmHAMTqYyeGfiqz79a9kL1MtZHu/view?usp=sharing # x span between left long vertical line and # right-most center of central conductors resonators_widths = [2 * self.r + L_coupling for L_coupling in self.L_coupling_list] x1 = 2 * self.resonators_dx + resonators_widths[2] / 2 - 2 * self.xmon_x_distance x2 = x1 + self.xmon_x_distance - self.resonators_dx x3 = resonators_widths[2] / 2 x4 = 3 * self.resonators_dx - (x1 + 3 * self.xmon_x_distance) x5 = 4 * self.resonators_dx - (x1 + 4 * self.xmon_x_distance) res_tail_shape = "LRLRL" tail_turn_radiuses = self.r # list corrected for resonator-qubit coupling geomtry, so all transmons centers are placed # along single horizontal line self.L0_list = [self.L0 - xmon_dy_Cg_coupling for xmon_dy_Cg_coupling in self.xmon_dys_Cg_coupling] self.L2_list[0] += 6 * self.Z_res.b self.L2_list[1] += 0 self.L2_list[3] += 3 * self.Z_res.b self.L2_list[4] += 6 * self.Z_res.b self.L3_list[0] = x1 self.L3_list[1] = x2 self.L3_list[2] = x3 self.L3_list[3] = x4 self.L3_list[4] = x5 self.L4_list[1] += 6 * self.Z_res.b self.L4_list[2] += 6 * self.Z_res.b self.L4_list[3] += 3 * self.Z_res.b tail_segment_lengths_list = [[L2, L3, L4 + FABRICATION.OVERETCHING] for L2, L3, L4 in zip(self.L2_list, self.L3_list, self.L4_list)] tail_turn_angles_list = [ [pi / 2, -pi / 2], [pi / 2, -pi / 2], [pi / 2, -pi / 2], [-pi / 2, pi / 2], [-pi / 2, pi / 2], ] tail_trans_in_list = [ Trans.R270, Trans.R270, Trans.R270, Trans.R270, Trans.R270 ] ### RESONATORS TAILS CALCULATIONS SECTION END ### pars = list( zip( self.L1_list, self.to_line_list, self.L_coupling_list, self.fork_y_spans, tail_segment_lengths_list, tail_turn_angles_list, tail_trans_in_list, self.L0_list, self.N_coils ) ) for res_idx, params in enumerate(pars): # parameters exctraction L1 = params[0] to_line = params[1] L_coupling = params[2] fork_y_span = params[3] tail_segment_lengths = params[4] tail_turn_angles = params[5] tail_trans_in = params[6] L0 = params[7] n_coils = params[8] # deduction for resonator placements # under condition that Xmon-Xmon distance equals # `xmon_x_distance` worm_x = self.contact_pads[-1].end.x + (res_idx + 1 / 2) * self.resonators_dx worm_y = self.contact_pads[-1].end.y - self.ro_line_dy - to_line resonator_cpw = CPWParameters(self.Z_res.width + 2 * FABRICATION.OVERETCHING, self.Z_res.gap - 2 * FABRICATION.OVERETCHING) self.resonators.append( EMResonatorTL3QbitWormRLTailXmonFork( resonator_cpw, DPoint(worm_x, worm_y), L_coupling, L0, L1, self.r, n_coils, tail_shape=res_tail_shape, tail_turn_radiuses=tail_turn_radiuses, tail_segment_lengths=tail_segment_lengths, tail_turn_angles=tail_turn_angles, tail_trans_in=tail_trans_in, fork_x_span=fork_x_span + 2 * FABRICATION.OVERETCHING, fork_y_span=fork_y_span, fork_metal_width=self.fork_metal_width + 2 * FABRICATION.OVERETCHING, fork_gnd_gap=self.fork_gnd_gap - 2 * FABRICATION.OVERETCHING ) ) # print([self.L0 - xmon_dy_Cg_coupling for xmon_dy_Cg_coupling in self.xmon_dys_Cg_coupling]) # print(self.L1_list) # print(self.L2_list) # print(self.L3_list) # print(self.L4_list) def draw_readout_waveguide(self): ''' Subdividing horizontal waveguide adjacent to resonators into several waveguides. Even segments of this adjacent waveguide are adjacent to resonators. Bridges will be placed on odd segments later. Returns ------- None ''' # place readout waveguide ro_line_turn_radius = self.ro_line_turn_radius ro_line_dy = self.ro_line_dy ## calculating segment lengths of subdivided coupling part of ro coplanar ## # value that need to be added to `L_coupling` to get width of resonators bbox. def get_res_extension(resonator: EMResonatorTL3QbitWormRLTailXmonFork): return resonator.Z0.b + 2 * resonator.r def get_res_width(resonator: EMResonatorTL3QbitWormRLTailXmonFork): return (resonator.L_coupling + get_res_extension(resonator)) res_line_segments_lengths = [ self.resonators[0].origin.x - self.contact_pads[-1].end.x - get_res_extension(self.resonators[0]) / 2 ] # length from bend to first bbox of first resonator for i, resonator in enumerate(self.resonators[:-1]): resonator_extension = get_res_extension(resonator) resonator_width = get_res_width(resonator) next_resonator_extension = get_res_extension(self.resonators[i + 1]) # order of adding is from left to right (imagine chip geometry in your head to follow) res_line_segments_lengths.extend( [ resonator_width, # `resonator_extension` accounts for the next resonator extension # in this case all resonator's extensions are equal self.resonators_dx - (resonator_width - resonator_extension / 2) - next_resonator_extension / 2 ] ) res_line_segments_lengths.extend( [ get_res_width(self.resonators[-1]), self.resonators_dx / 2 ] ) # first and last segment will have length `self.resonator_dx/2` res_line_total_length = sum(res_line_segments_lengths) segment_lengths = [ro_line_dy] + res_line_segments_lengths + \ [ro_line_dy / 2, res_line_total_length - self.chip.pcb_feedline_d, ro_line_dy / 2] self.cpwrl_ro_line = CPW_RL_Path( self.contact_pads[-1].end, shape="LR" + ''.join(['L'] * len(res_line_segments_lengths)) + "RLRLRL", cpw_parameters=CPWParameters(self.Z0.width + 2 * FABRICATION.OVERETCHING, self.Z0.gap - 2 * FABRICATION.OVERETCHING), turn_radiuses=[ro_line_turn_radius] * 4, segment_lengths=segment_lengths, turn_angles=[pi / 2, pi / 2, pi / 2, -pi / 2], trans_in=Trans.R270 ) self.cpwrl_ro_line.place(self.region_ph) def draw_xmons_and_resonators(self): for resonator, fork_y_span, xmon_dy_Cg_coupling in \ list(zip( self.resonators, self.fork_y_spans, self.xmon_dys_Cg_coupling )): xmon_center = (resonator.fork_x_cpw.start + resonator.fork_x_cpw.end) / 2 + \ DVector(0, -xmon_dy_Cg_coupling - resonator.fork_metal_width / 2) # changes start # xmon_center += DPoint( 0, -(self.cross_len_y + self.cross_width_x / 2 + min(self.cross_gnd_gap_y, self.xmon_fork_gnd_gap)) + FABRICATION.OVERETCHING ) self.xmons.append( XmonCross(xmon_center, self.cross_len_x, self.cross_width_x + 2 * FABRICATION.OVERETCHING, self.cross_gnd_gap_x - 2 * FABRICATION.OVERETCHING, sideY_length=self.cross_len_y, sideY_width=self.cross_width_y + 2 * FABRICATION.OVERETCHING, sideY_gnd_gap=self.cross_gnd_gap_y - 2 * FABRICATION.OVERETCHING) ) self.xmons[-1].place(self.region_ph) resonator.place(self.region_ph) xmonCross_corrected = XmonCross( xmon_center, sideX_length=self.cross_len_x, sideX_width=self.cross_width_x + 2 * FABRICATION.OVERETCHING, sideX_gnd_gap=self.cross_gnd_gap_x - 2 * FABRICATION.OVERETCHING, sideY_length=self.cross_len_y, sideY_width=self.cross_width_y + 2 * FABRICATION.OVERETCHING, sideY_gnd_gap=min(self.cross_gnd_gap_y, self.xmon_fork_gnd_gap) - 2 * FABRICATION.OVERETCHING) xmonCross_corrected.place(self.region_ph) def draw_md_and_flux_lines(self): """ Drawing of md (microwave drive) and flux tuning lines for 5 qubits Returns ------- """ contact_pads = self.contact_pads ctr_line_turn_radius = 100e3 xmon_center = self.xmons[-1].center xmon_x_distance = self.xmon_x_distance cross_width_y = self.cross_width_y cross_width_x = self.cross_width_x cross_len_x = self.cross_len_x cross_len_y = self.cross_len_y cross_gnd_gap_y = self.cross_gnd_gap_y cross_gnd_gap_x = self.cross_gnd_gap_x width_res = self.Z_res.width tmp_reg = self.region_ph z_md_fl_corrected = CPWParameters( self.z_md_fl.width + 2 * FABRICATION.OVERETCHING, self.z_md_fl.gap - 2 * FABRICATION.OVERETCHING ) shift_fl_y = self.shift_fl_y shift_md_x = self.shift_md_x shift_md_y = self.shift_md_y md0_md5_gnd = 5e3 flux_end_width = self.cross_width_x + 2 * self.cross_gnd_gap_x - 2 * FABRICATION.OVERETCHING md_transition = 25e3 md_z1_params = z_md_fl_corrected md_z1_length = 245e3 shift_md_x_side = md_z1_length + md_transition + md_z1_params.b / 2 + cross_len_x + cross_width_x / 2 + cross_gnd_gap_x # place caplanar line 1md self.cpwrl_md1 = CPW_RL_Path( contact_pads[0].end, shape="LRLRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius] * 2, segment_lengths=[ 2 * (-contact_pads[0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16, ( (contact_pads[0].end.y - xmon_center.y) ** 2 + (9 * (-contact_pads[0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16) ** 2 ) ** 0.5, 5 * (-contact_pads[ 0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16 - md0_md5_gnd], turn_angles=[-atan2(contact_pads[0].end.y - xmon_center.y, 9 * (-contact_pads[ 0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16), atan2(contact_pads[0].end.y - xmon_center.y, 9 * (-contact_pads[ 0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16)], trans_in=Trans.R0 ) self.cpwrl_md1.place(tmp_reg) self.cpwrl_md1_end = MDriveLineEnd(list(self.cpwrl_md1.primitives.values())[-1], md_z1_params, md_transition, md_z1_length) self.cpwrl_md1_end.place(tmp_reg) # place caplanar line 1 fl self.cpwrl_fl1 = CPW_RL_Path( contact_pads[1].end, shape="LRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius], segment_lengths=[ -contact_pads[1].end.x + xmon_center.x - 4 * xmon_x_distance - cross_len_x, xmon_center.y - contact_pads[1].end.y - cross_width_x / 2 - cross_gnd_gap_x - z_md_fl_corrected.width + FABRICATION.OVERETCHING ], turn_angles=[pi / 2], trans_in=Trans.R0 ) self.cpwrl_fl1.place(tmp_reg) self.cpwrl_fl1_end = FluxLineEnd(self.cpwrl_fl1.end, z_md_fl_corrected, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl1_end.place(tmp_reg) # place caplanar line 2md self.cpwrl_md2 = CPW_RL_Path( contact_pads[3].end, shape="LRLRLRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius] * 3, segment_lengths=[ (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 4, (-contact_pads[3].end.x + xmon_center.x + shift_md_x - 3 * xmon_x_distance) / 2, ( ( (-contact_pads[3].end.x + xmon_center.x + shift_md_x - 3 * xmon_x_distance) / 2 ) ** 2 + ( 5 * (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 8 ) ** 2 ) ** 0.5, (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 8 ], turn_angles=[-pi / 2, atan2(5 * (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 8, ( -contact_pads[3].end.x + xmon_center.x + shift_md_x - 3 * xmon_x_distance) / 2), pi / 2 - atan2(5 * (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 8, ( -contact_pads[3].end.x + xmon_center.x + shift_md_x - 3 * xmon_x_distance) / 2)], trans_in=Trans.R90 ) self.cpwrl_md2.place(tmp_reg) self.cpwrl_md2_end = MDriveLineEnd( list(self.cpwrl_md2.primitives.values())[-1], md_z1_params, md_transition, md_z1_length ) self.cpwrl_md2_end.place(tmp_reg) # place caplanar line 2 fl self.cpwrl_fl2 = CPW_RL_Path( contact_pads[2].end, shape="LRLRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius] * 2, segment_lengths=[(-contact_pads[2].end.x + xmon_center.x - 3 * xmon_x_distance) / 4, ( (3 * (-contact_pads[2].end.x + xmon_center.x - 3 * xmon_x_distance) / 4) ** 2 + ( 7 * (-contact_pads[2].end.y + xmon_center.y - shift_fl_y) / 8) ** 2) ** 0.5, (-contact_pads[2].end.y + xmon_center.y - shift_fl_y) / 8], turn_angles=[atan2(7 * (-contact_pads[2].end.y + xmon_center.y - shift_fl_y) / 8, 3 * (-contact_pads[2].end.x + xmon_center.x - 3 * xmon_x_distance) / 4), pi / 2 - atan2(7 * (-contact_pads[2].end.y + xmon_center.y - shift_fl_y) / 8, 3 * (-contact_pads[2].end.x + xmon_center.x - 3 * xmon_x_distance) / 4)], trans_in=Trans.R0 ) self.cpwrl_fl2.place(tmp_reg) self.cpwrl_fl2_end = FluxLineEnd(self.cpwrl_fl2.end, z_md_fl_corrected, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl2_end.place(tmp_reg) # place caplanar line 3md self.cpwrl_md3_1 = CPW_RL_Path( contact_pads[5].end, shape="LRLRLRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius] * 3, segment_lengths=[ (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 4, (contact_pads[5].end.x - xmon_center.x - shift_md_x + 2 * xmon_x_distance) / 2, ( ( (contact_pads[5].end.x - xmon_center.x - shift_md_x + 2 * xmon_x_distance) / 2 ) ** 2 + ( 5 * (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 8 ) ** 2 ) ** 0.5 - 400e3, (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 8], turn_angles=[pi / 2, -atan2(5 * (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 8, (contact_pads[5].end.x - xmon_center.x - shift_md_x + 2 * xmon_x_distance) / 2), -pi / 2 + atan2(5 * (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 8, ( contact_pads[5].end.x - xmon_center.x - shift_md_x + 2 * xmon_x_distance) / 2)], trans_in=Trans.R90 ) self.cpwrl_md3_1.place(tmp_reg) dy = self.cpwrl_md2.end.y - self.cpwrl_md3_1.end.y dx = self.cpwrl_md3_1.end.x - (self.xmons[2].center.x + shift_md_x) md3_2_radius = ctr_line_turn_radius - 50e3 self.cpwrl_md3_2 = CPW_RL_Path( self.cpwrl_md3_1.end, shape="LRLR", cpw_parameters=z_md_fl_corrected, turn_radiuses=[md3_2_radius] * 2, segment_lengths=[dy - md3_2_radius, dx], turn_angles=[pi / 2, -pi / 2], trans_in=Trans.R90 ) self.cpwrl_md3_2.place(tmp_reg) self.cpwrl_md3_end = MDriveLineEnd( list(self.cpwrl_md3_2.primitives.values())[-1], md_z1_params, md_transition, md_z1_length ) self.cpwrl_md3_end.place(tmp_reg) # place caplanar line 3 fl fl_l1 = (self.xmons[2].cpw_bempt.end.y - contact_pads[4].end.y) / 4 fl_l3 = fl_l1 dr = self.xmons[2].cpw_bempt.end - contact_pads[4].end dr.y = dr.y - fl_l1 - fl_l3 - z_md_fl_corrected.width turn_angle = atan2(-dr.x, dr.y) fl_l2 = dr.abs() self.cpwrl_fl3 = CPW_RL_Path( self.contact_pads[4].end, shape="LRLRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius] * 2, segment_lengths=[fl_l1, fl_l2, fl_l3], turn_angles=[turn_angle, -turn_angle], trans_in=Trans.R90 ) self.cpwrl_fl3.place(tmp_reg) self.cpwrl_fl3_end = FluxLineEnd(self.cpwrl_fl3.end, z_md_fl_corrected, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl3_end.place(tmp_reg) # place caplanar line 4 md md4_len_y = -contact_pads[7].end.y + xmon_center.y - shift_md_y md4_fl4_dx = 100e3 self.cpwrl_md4 = CPW_RL_Path( contact_pads[7].end, shape="LRLRLRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=ctr_line_turn_radius / 2, segment_lengths=[ contact_pads[7].end.x - xmon_center.x + xmon_x_distance - shift_md_x - md4_fl4_dx, md4_len_y - ctr_line_turn_radius / 2, md4_fl4_dx, ctr_line_turn_radius / 2 ], turn_angles=[-pi / 2, pi / 2, -pi / 2], trans_in=Trans.R180 ) self.cpwrl_md4.place(tmp_reg) self.cpwrl_md4_end = MDriveLineEnd( list(self.cpwrl_md4.primitives.values())[-1], md_z1_params, md_transition, md_z1_length ) self.cpwrl_md4_end.place(tmp_reg) # place caplanar line 4 fl self.cpwrl_fl4 = CPW_RL_Path( contact_pads[6].end, shape="LRLRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius] * 2, segment_lengths=[(contact_pads[6].end.x - xmon_center.x + xmon_x_distance) / 4, ((6 * (-contact_pads[6].end.y + xmon_center.y - shift_fl_y) / 8) ** 2 + (3 * (contact_pads[6].end.x - xmon_center.x + xmon_x_distance) / 4) ** 2) ** 0.5, 2 * (-contact_pads[6].end.y + xmon_center.y - shift_fl_y) / 8], turn_angles=[-atan2(6 * (-contact_pads[6].end.y + xmon_center.y - shift_fl_y) / 8, 3 * (contact_pads[6].end.x - xmon_center.x + xmon_x_distance) / 4), -pi / 2 + atan2(6 * (-contact_pads[6].end.y + xmon_center.y - shift_fl_y) / 8, 3 * (contact_pads[6].end.x - xmon_center.x + xmon_x_distance) / 4)], trans_in=Trans.R180 ) self.cpwrl_fl4.place(tmp_reg) self.cpwrl_fl4_end = FluxLineEnd(self.cpwrl_fl4.end, z_md_fl_corrected, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl4_end.place(tmp_reg) # place caplanar line 5 md md5_l1 = 2 * (contact_pads[9].end.y - xmon_center.y) / 3 md5_dy = 400e3 md5_dx = 400e3 md5_angle = atan2( 2 * (contact_pads[9].end.x - xmon_center.x - shift_md_x_side) / 3, (contact_pads[9].end.y - xmon_center.y) / 3 ) self.cpwrl_md5 = CPW_RL_Path( contact_pads[9].end, shape="LRLRLRLRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius] * 4, segment_lengths=[ md5_dy, md5_dx / sin(pi / 4), md5_l1 - md5_dy - md5_dx / tan(pi / 4) - md5_dx / tan(md5_angle), md5_dx / sin(md5_angle) + ( ( (contact_pads[9].end.y - xmon_center.y) / 3 ) ** 2 + ( 2 * (contact_pads[9].end.x - xmon_center.x - shift_md_x_side) / 3 ) ** 2 ) ** (0.5), (contact_pads[9].end.x - xmon_center.x - shift_md_x_side) / 3 - md0_md5_gnd ], turn_angles=[ pi / 4, -pi / 4, -md5_angle, -(pi / 2 - md5_angle) ], trans_in=Trans.R270 ) # self.cpwrl_md5 = CPW_RL_Path( # contact_pads[9].end, shape="LRLRL", cpw_parameters=z_md_fl_corrected, # turn_radiuses=[ctr_line_turn_radius] * 2, # segment_lengths=[ # md5_l1, # ( # ( # (contact_pads[9].end.y - xmon_center.y) / 3 # ) ** 2 + # ( # 2 * (contact_pads[9].end.x - xmon_center.x - shift_md_x_side) / 3 # ) ** 2 # ) ** (0.5), # (contact_pads[9].end.x - xmon_center.x - shift_md_x_side) / 3 - md0_md5_gnd # ], # turn_angles=[ # md5_angle, # -md5_angle - pi / 2 # ], # trans_in=Trans.R270 # ) self.cpwrl_md5.place(tmp_reg) self.cpwrl_md5_end = MDriveLineEnd( list(self.cpwrl_md5.primitives.values())[-1], md_z1_params, md_transition, md_z1_length ) self.cpwrl_md5_end.place(tmp_reg) # place caplanar line 5 fl self.cpwrl_fl5_1 = CPW_RL_Path( contact_pads[8].end, shape="LRLRLR", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius] * 3, segment_lengths=[ (contact_pads[8].end.x - xmon_center.x) / 4, ((contact_pads[8].end.y - xmon_center.y) + 250e3) / 3 + 50e3, ( (2 * ((contact_pads[8].end.y - xmon_center.y) + 250e3) / 3) ** 2 + ((contact_pads[8].end.x - xmon_center.x) / 2) ** 2 ) ** 0.5 ], turn_angles=[ pi / 2, -atan2((contact_pads[8].end.x - xmon_center.x) / 2, 2 * ((contact_pads[8].end.y - xmon_center.y) + 250e3) / 3), - pi / 2 + atan2((contact_pads[8].end.x - xmon_center.x) / 2, 2 * ((contact_pads[8].end.y - xmon_center.y) + 250e3) / 3) ], trans_in=Trans.R180 ) self.cpwrl_fl5_1.place(tmp_reg) self.cpwrl_fl5_2 = CPW_RL_Path( self.cpwrl_fl5_1.end, shape="LRL", cpw_parameters=z_md_fl_corrected, turn_radiuses=[ctr_line_turn_radius], segment_lengths=[ self.cpwrl_fl5_1.end.x - (self.xmons[4].center.x + cross_width_y / 2 + cross_len_x + cross_gnd_gap_x - flux_end_width / 2), self.xmons[4].center.y - self.cpwrl_fl5_1.end.y - cross_width_x / 2 - cross_gnd_gap_x - z_md_fl_corrected.width + FABRICATION.OVERETCHING ], turn_angles=[-pi / 2], trans_in=Trans.R180 ) self.cpwrl_fl5_2.place(tmp_reg) self.cpwrl_fl5_end = FluxLineEnd(self.cpwrl_fl5_2.end, z_md_fl_corrected, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl5_end.place(tmp_reg) def draw_josephson_loops(self): new_pars_squid = AsymSquidParams( pad_r=5e3, pads_distance=30e3, p_ext_width=10e3, p_ext_r=200, sq_len=15e3, sq_area=200e6, j_width_1=95, j_width_2=348, intermediate_width=500, b_ext=1e3, j_length=94, n=20, bridge=180, j_length_2=250 ) # place left squid xmon0 = self.xmons[0] center1 = DPoint( self.cpwrl_fl1_end.end.x, xmon0.center.y - (xmon0.sideX_width + xmon0.sideX_gnd_gap) / 2 ) squid = AsymSquid(center1, new_pars_squid, 0) self.squids.append(squid) squid.place(self.region_el) # place intermediate squids for xmon_cross in self.xmons[1:-1]: squid_center = (xmon_cross.cpw_bempt.start + xmon_cross.cpw_bempt.end) / 2 squid = AsymSquid(squid_center, new_pars_squid, 0) self.squids.append(squid) squid.place(self.region_el) # place right squid xmon5 = self.xmons[4] center5 = DPoint( self.cpwrl_fl5_end.end.x, xmon5.center.y - (xmon5.sideX_width + xmon5.sideX_gnd_gap) / 2 ) squid = AsymSquid(center5, new_pars_squid, 0) self.squids.append(squid) squid.place(self.region_el) def draw_el_dc_contacts(self, squids: AsymSquid = None): # if argument is omitted, use all squids stored in `self.squids` if squids is None: squids = self.squids + self.test_squids for squid in squids: r_pad = squid.params.pad_r center_up = squid.pad_up.center + DPoint(0, r_pad) center_down = squid.pad_down.center + DPoint(0, -r_pad) big_circle_r = 1.5 * r_pad self.el_dc_contacts.append( [Circle(center_up, big_circle_r), Circle(center_down, big_circle_r)] ) for contact in self.el_dc_contacts[-1]: contact.place(self.region_el2) # DC contacts has to have intersection with empty layer in photo litography # to ensure that first e-beam layer does not broke at the step between # substrate and photolytography polygons. # Following rectangle pads are cutted from photo region to ensure # DC contacts are covering aforementioned level step. squid_pad_r = squid.params.pad_r squid_pads_d = squid.params.pads_distance - 2 * squid_pad_r rec_width = 1.6 * squid_pad_r - 2 * FABRICATION.OVERETCHING rec_height = 1.6 * squid_pad_r - FABRICATION.OVERETCHING # Rectangle for top DC contact pad p1 = squid.origin + DVector(-rec_width / 2, squid_pads_d / 2) + \ DVector(0, -FABRICATION.OVERETCHING) rec_top = Rectangle(p1, rec_width, rec_height, inverse=True) rec_top.place(self.region_ph) # Rectangle for bottom DC contact pad p2 = squid.origin + DVector(-rec_width / 2, -squid_pads_d / 2) + \ DVector(0, FABRICATION.OVERETCHING) rec_bot = Rectangle(p2, rec_width, -rec_height, inverse=True) rec_bot.place(self.region_ph) def draw_test_structures(self): new_pars_squid = AsymSquidParams( pad_r=5e3, pads_distance=30e3, p_ext_width=10e3, p_ext_r=200, sq_len=15e3, sq_area=200e6, j_width_1=94, j_width_2=347, intermediate_width=500, b_ext=1e3, j_length=94, n=20, bridge=180, j_length_2=250 ) struct_centers = [DPoint(1e6, 4e6), DPoint(8.7e6, 5.7e6), DPoint(6.5e6, 2.7e6)] for struct_center in struct_centers: ## JJ test structures ## # test structure with big critical current test_struct1 = TestStructurePads(struct_center) test_struct1.place(self.region_ph) text_reg = pya.TextGenerator.default_generator().text("48.32 nA", 0.001, 50, False, 0, 0) text_bl = test_struct1.empty_rectangle.origin + DPoint( test_struct1.gnd_gap, -4 * test_struct1.gnd_gap ) text_reg.transform(ICplxTrans(1.0, 0, False, text_bl.x, text_bl.y)) self.region_ph -= text_reg test_jj = AsymSquid(test_struct1.center, new_pars_squid, side=1) self.test_squids.append(test_jj) test_jj.place(self.region_el) # test structure with low critical current test_struct2 = TestStructurePads(struct_center + DPoint(0.3e6, 0)) test_struct2.place(self.region_ph) text_reg = pya.TextGenerator.default_generator().text("9.66 nA", 0.001, 50, False, 0, 0) text_bl = test_struct2.empty_rectangle.origin + DPoint( test_struct2.gnd_gap, -4 * test_struct2.gnd_gap ) text_reg.transform(ICplxTrans(1.0, 0, False, text_bl.x, text_bl.y)) self.region_ph -= text_reg test_jj = AsymSquid(test_struct2.center, new_pars_squid, side=-1) self.test_squids.append(test_jj) test_jj.place(self.region_el) # test structure for bridge DC contact test_struct3 = TestStructurePads(struct_center + DPoint(0.6e6, 0)) test_struct3.place(self.region_ph) text_reg = pya.TextGenerator.default_generator().text("DC", 0.001, 50, False, 0, 0) text_bl = test_struct3.empty_rectangle.origin + DPoint( test_struct3.gnd_gap, -4 * test_struct3.gnd_gap ) text_reg.transform(ICplxTrans(1.0, 0, False, test_struct3.center.x, text_bl.y)) self.region_ph -= text_reg test_bridges = [] for i in range(3): bridge = Bridge1(test_struct3.center + DPoint(50e3 * (i - 1), 0), gnd_touch_dx=20e3) test_bridges.append(bridge) bridge.place(self.region_bridges1, region_name="bridges_1") bridge.place(self.region_bridges2, region_name="bridges_2") # bandages test structures test_dc_el2_centers = [ DPoint(2.5e6, 2.4e6), DPoint(4.2e6, 1.6e6), DPoint(9.0e6, 3.8e6) ] for struct_center in test_dc_el2_centers: test_struct1 = TestStructurePads(struct_center) test_struct1.place(self.region_ph) text_reg = pya.TextGenerator.default_generator().text("Bandage", 0.001, 40, False, 0, 0) text_bl = test_struct1.empty_rectangle.origin + DPoint( test_struct1.gnd_gap, -4 * test_struct1.gnd_gap ) text_reg.transform(ICplxTrans(1.0, 0, False, text_bl.x, text_bl.y)) self.region_ph -= text_reg rec_width = 10e3 rec_height = test_struct1.rectangles_gap + 2 * FABRICATION.OVERETCHING + 2 * rec_width p1 = struct_center - DVector(rec_width / 2, rec_height / 2) dc_rec = Rectangle(p1, rec_width, rec_height) dc_rec.place(self.region_el2) def draw_el_protection(self): protection_a = 300e3 for squid in (self.squids + self.test_squids): self.region_el_protection.insert( pya.Box().from_dbox( pya.DBox( squid.origin - 0.5 * DVector(protection_a, protection_a), squid.origin + 0.5 * DVector(protection_a, protection_a) ) ) ) def draw_photo_el_marks(self): marks_centers = [ DPoint(1e6, 9e6), DPoint(1e6, 1e6), DPoint(9e6, 1e6), DPoint(9e6, 9e6), DPoint(8e6, 4e6), DPoint(1e6, 6e6) ] for mark_center in marks_centers: self.marks.append( MarkBolgar(mark_center, overetching=FABRICATION.OVERETCHING) ) self.marks[-1].place(self.region_ph) def draw_bridges(self): bridges_step = 150e3 # for resonators for resonator in self.resonators: for name, res_primitive in resonator.primitives.items(): if "coil0" in name: # skip L_coupling coplanar. # bridgyfy all in "coil0" except for the first cpw that # is adjacent to readout line and has length equal to `L_coupling` for primitive in list(res_primitive.primitives.values())[1:]: Bridge1.bridgify_CPW( primitive, bridges_step, dest=self.region_bridges1, dest2=self.region_bridges2 ) continue elif "fork" in name: # skip fork primitives continue else: # bridgify everything else Bridge1.bridgify_CPW( res_primitive, bridges_step, dest=self.region_bridges1, dest2=self.region_bridges2 ) # for contact wires for key, val in self.__dict__.items(): if "cpwrl_md" in key: Bridge1.bridgify_CPW( val, bridges_step, dest=self.region_bridges1, dest2=self.region_bridges2 ) elif "cpwrl_fl" in key: Bridge1.bridgify_CPW( val, bridges_step, dest=self.region_bridges1, dest2=self.region_bridges2, avoid_points=[squid.origin for squid in self.squids], avoid_distance=500e3 ) # for readout waveguide bridgified_primitives_idxs = list(range(2)) bridgified_primitives_idxs += list(range(2, 2 * (len(self.resonators) + 1) + 1, 2)) bridgified_primitives_idxs += list(range( 2 * (len(self.resonators) + 1) + 1, len(self.cpwrl_ro_line.primitives.values())) ) for idx, primitive in enumerate(self.cpwrl_ro_line.primitives.values()): if idx in bridgified_primitives_idxs: Bridge1.bridgify_CPW( primitive, bridges_step, dest=self.region_bridges1, dest2=self.region_bridges2 ) def draw_pinning_holes(self): selection_region = Region( pya.Box(Point(100e3, 100e3), Point(101e3, 101e3)) ) tmp_ph = self.region_ph.dup() other_regs = tmp_ph.select_not_interacting(selection_region) reg_to_fill = self.region_ph.select_interacting(selection_region) filled_reg = fill_holes(reg_to_fill) self.region_ph = filled_reg + other_regs def split_polygons_in_layers(self, max_pts=200): self.region_ph = split_polygons(self.region_ph, max_pts) self.region_bridges2 = split_polygons(self.region_bridges2, max_pts) for poly in self.region_ph: if poly.num_points() > max_pts: print("exists photo") for poly in self.region_ph: if poly.num_points() > max_pts: print("exists bridge2")
cell.clear() tmp_reg = Region() # faster to call `place` on single region # place chip metal layer chip_box = pya.Box(DPoint(0, 0), DPoint(CHIP_10x10_12pads.dx, CHIP_10x10_12pads.dy)) tmp_reg.insert(chip_box) contact_pads = CHIP_10x10_12pads.get_contact_pads() for contact_pad in contact_pads: contact_pad.place(tmp_reg) # place readout waveguide ro_line_turn_radius = 200e3 ro_line_dy = 600e3 cpwrl_ro = CPW_RL_Path( contact_pads[-1].end, shape="LRLRL", cpw_parameters=Z0, turn_radiuses=[ro_line_turn_radius]*2, segment_lengths=[ro_line_dy, CHIP_10x10_12pads.pcb_feedline_d, ro_line_dy], turn_angles=[pi/2, pi/2], trans_in=Trans.R270 ) cpwrl_ro.place(tmp_reg) params = zip(L1_list, L2_list, L_coupling_list, xmon_fork_penetrations) for res_idx, (L1, L2, L_coupling, xmon_fork_penetration) in enumerate(params): fork_y_span = xmon_fork_penetration + xmon_fork_gnd_gap worm_x = None # deduction for resonator placements # under condition that Xmon-Xmon distance equals # `xmon_x_distance` if res_idx == 0: worm_x = 1.2 * CHIP_10x10_12pads.pcb_feedline_d else:
def draw_md_and_flux_lines(self): """ Drawing of md (microwave drive) and flux tuning lines for 5 qubits Returns ------- """ contact_pads = self.contact_pads ctr_line_turn_radius = 200e3 xmon_center = self.xmons[-1].center xmon_x_distance = self.xmon_x_distance cross_width_y = self.cross_width_y cross_width_x = self.cross_width_x cross_len_x = self.cross_len_x cross_gnd_gap_y = self.cross_gnd_gap_y cross_gnd_gap_x = self.cross_gnd_gap_x width_res = self.Z_res.width tmp_reg = self.region_ph z_md_fl = self.Z0 shift_fl_y = self.shift_fl_y shift_md_x = self.shift_md_x shift_md_y = self.shift_md_y flux_end_width = self.cross_width_x + 2 * self.cross_gnd_gap_x md_transition = 25e3 md_z1_params = CPWParameters( 7e3, 4e3 ) # Z = 50.04 Ohm, E_eff = 6.237 (E_0 = 11.45) (8e3, 4.15e3) md_z1_length = 100e3 shift_md_x_side = md_z1_length + md_transition + md_z1_params.b / 2 + cross_len_x + cross_width_x / 2 + cross_gnd_gap_x # place caplanar line 1md self.cpwrl_md1 = CPW_RL_Path( contact_pads[0].end, shape="LRLRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius] * 2, segment_lengths=[ 2 * (-contact_pads[0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16, ((contact_pads[0].end.y - xmon_center.y)**2 + (9 * (-contact_pads[0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16)**2)**0.5, 5 * (-contact_pads[0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16 - 140e3 ], turn_angles=[ -atan2( contact_pads[0].end.y - xmon_center.y, 9 * (-contact_pads[0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16), atan2( contact_pads[0].end.y - xmon_center.y, 9 * (-contact_pads[0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16) ], trans_in=Trans.R0) self.cpwrl_md1.place(tmp_reg) self.cpwrl_md1_end = MDriveLineEnd( list(self.cpwrl_md1.primitives.values())[-1], md_z1_params, md_transition, md_z1_length) self.cpwrl_md1_end.place(tmp_reg) # place caplanar line 1 fl self.cpwrl_fl1 = CPW_RL_Path( contact_pads[1].end, shape="LRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius], segment_lengths=[(-contact_pads[1].end.x + xmon_center.x - 4 * xmon_x_distance - cross_len_x), (-contact_pads[1].end.y + xmon_center.y - cross_width_y / 2 - cross_gnd_gap_y - width_res) ], turn_angles=[pi / 2], trans_in=Trans.R0) self.cpwrl_fl1.place(tmp_reg) self.cpwrl_fl1_end = FluxLineEnd(self.cpwrl_fl1.end, z_md_fl, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl1_end.place(tmp_reg) # place caplanar line 2md self.cpwrl_md2 = CPW_RL_Path( contact_pads[3].end, shape="LRLRLRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius] * 3, segment_lengths=[ (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 4, (-contact_pads[3].end.x + xmon_center.x + shift_md_x - 3 * xmon_x_distance) / 2, (((-contact_pads[3].end.x + xmon_center.x + shift_md_x - 3 * xmon_x_distance) / 2)**2 + (5 * (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 8)**2)**0.5, (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 8 ], turn_angles=[ -pi / 2, atan2( 5 * (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 8, (-contact_pads[3].end.x + xmon_center.x + shift_md_x - 3 * xmon_x_distance) / 2), pi / 2 - atan2( 5 * (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 8, (-contact_pads[3].end.x + xmon_center.x + shift_md_x - 3 * xmon_x_distance) / 2) ], trans_in=Trans.R90) self.cpwrl_md2.place(tmp_reg) self.cpwrl_md2_end = MDriveLineEnd( list(self.cpwrl_md2.primitives.values())[-1], md_z1_params, md_transition, md_z1_length) self.cpwrl_md2_end.place(tmp_reg) # place caplanar line 2 fl self.cpwrl_fl2 = CPW_RL_Path( contact_pads[2].end, shape="LRLRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius] * 2, segment_lengths=[ (-contact_pads[2].end.x + xmon_center.x - 3 * xmon_x_distance) / 4, ((3 * (-contact_pads[2].end.x + xmon_center.x - 3 * xmon_x_distance) / 4)**2 + (7 * (-contact_pads[2].end.y + xmon_center.y - shift_fl_y) / 8)**2)**0.5, (-contact_pads[2].end.y + xmon_center.y - shift_fl_y) / 8 ], turn_angles=[ atan2( 7 * (-contact_pads[2].end.y + xmon_center.y - shift_fl_y) / 8, 3 * (-contact_pads[2].end.x + xmon_center.x - 3 * xmon_x_distance) / 4), pi / 2 - atan2( 7 * (-contact_pads[2].end.y + xmon_center.y - shift_fl_y) / 8, 3 * (-contact_pads[2].end.x + xmon_center.x - 3 * xmon_x_distance) / 4) ], trans_in=Trans.R0) self.cpwrl_fl2.place(tmp_reg) self.cpwrl_fl2_end = FluxLineEnd(self.cpwrl_fl2.end, z_md_fl, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl2_end.place(tmp_reg) # place caplanar line 3md self.cpwrl_md3 = CPW_RL_Path( contact_pads[5].end, shape="LRLRLRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius] * 3, segment_lengths=[ (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 4, (contact_pads[5].end.x - xmon_center.x - shift_md_x + 2 * xmon_x_distance) / 2, (((contact_pads[5].end.x - xmon_center.x - shift_md_x + 2 * xmon_x_distance) / 2)**2 + (5 * (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 8)**2)**0.5, (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 8 ], turn_angles=[ pi / 2, -atan2( 5 * (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 8, (contact_pads[5].end.x - xmon_center.x - shift_md_x + 2 * xmon_x_distance) / 2), -pi / 2 + atan2( 5 * (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 8, (contact_pads[5].end.x - xmon_center.x - shift_md_x + 2 * xmon_x_distance) / 2) ], trans_in=Trans.R90) self.cpwrl_md3.place(tmp_reg) self.cpwrl_md3_end = MDriveLineEnd( list(self.cpwrl_md3.primitives.values())[-1], md_z1_params, md_transition, md_z1_length) self.cpwrl_md3_end.place(tmp_reg) # place caplanar line 3 fl fl_l1 = (self.xmons[2].cpw_bempt.end.y - contact_pads[4].end.y) / 4 fl_l3 = fl_l1 dr = self.xmons[2].cpw_bempt.end - contact_pads[4].end dr.y = dr.y - fl_l1 - fl_l3 - z_md_fl.width turn_angle = atan2(-dr.x, dr.y) fl_l2 = dr.abs() self.cpwrl_fl3 = CPW_RL_Path(self.contact_pads[4].end, shape="LRLRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius] * 2, segment_lengths=[fl_l1, fl_l2, fl_l3], turn_angles=[turn_angle, -turn_angle], trans_in=Trans.R90) self.cpwrl_fl3.place(tmp_reg) self.cpwrl_fl3_end = FluxLineEnd(self.cpwrl_fl3.end, z_md_fl, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl3_end.place(tmp_reg) # place caplanar line 4 md self.cpwrl_md4 = CPW_RL_Path( contact_pads[7].end, shape="LRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius], segment_lengths=[ contact_pads[7].end.x - xmon_center.x + xmon_x_distance - shift_md_x, -contact_pads[7].end.y + xmon_center.y - shift_md_y ], turn_angles=[-pi / 2], trans_in=Trans.R180) self.cpwrl_md4.place(tmp_reg) self.cpwrl_md4_end = MDriveLineEnd( list(self.cpwrl_md4.primitives.values())[-1], md_z1_params, md_transition, md_z1_length) self.cpwrl_md4_end.place(tmp_reg) # place caplanar line 4 fl self.cpwrl_fl4 = CPW_RL_Path( contact_pads[6].end, shape="LRLRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius] * 2, segment_lengths=[ (contact_pads[6].end.x - xmon_center.x + xmon_x_distance) / 4, ((6 * (-contact_pads[6].end.y + xmon_center.y - shift_fl_y) / 8)**2 + (3 * (contact_pads[6].end.x - xmon_center.x + xmon_x_distance) / 4)**2)**0.5, 2 * (-contact_pads[6].end.y + xmon_center.y - shift_fl_y) / 8 ], turn_angles=[ -atan2( 6 * (-contact_pads[6].end.y + xmon_center.y - shift_fl_y) / 8, 3 * (contact_pads[6].end.x - xmon_center.x + xmon_x_distance) / 4), -pi / 2 + atan2( 6 * (-contact_pads[6].end.y + xmon_center.y - shift_fl_y) / 8, 3 * (contact_pads[6].end.x - xmon_center.x + xmon_x_distance) / 4) ], trans_in=Trans.R180) self.cpwrl_fl4.place(tmp_reg) self.cpwrl_fl4_end = FluxLineEnd(self.cpwrl_fl4.end, z_md_fl, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl4_end.place(tmp_reg) # place caplanar line 5 md self.cpwrl_md5 = CPW_RL_Path( contact_pads[9].end, shape="LRLRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius] * 2, segment_lengths=[ 2 * (contact_pads[9].end.y - xmon_center.y) / 3, (((contact_pads[9].end.y - xmon_center.y) / 3)**2 + (2 * (contact_pads[9].end.x - xmon_center.x - shift_md_x_side) / 3)**2)**(0.5), (contact_pads[9].end.x - xmon_center.x - shift_md_x_side) / 3 - 140e3 ], turn_angles=[ -atan2( 2 * (contact_pads[9].end.x - xmon_center.x - shift_md_x_side) / 3, (contact_pads[9].end.y - xmon_center.y) / 3), atan2( 2 * (contact_pads[9].end.x - xmon_center.x - shift_md_x_side) / 3, (contact_pads[9].end.y - xmon_center.y) / 3) - pi / 2 ], trans_in=Trans.R270) self.cpwrl_md5.place(tmp_reg) self.cpwrl_md5_end = MDriveLineEnd( list(self.cpwrl_md5.primitives.values())[-1], md_z1_params, md_transition, md_z1_length) self.cpwrl_md5_end.place(tmp_reg) # place caplanar line 5 fl self.cpwrl_fl5 = CPW_RL_Path( contact_pads[8].end, shape="LRLRLRLRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius] * 4, segment_lengths=[ (contact_pads[8].end.x - xmon_center.x) / 4, ((contact_pads[8].end.y - xmon_center.y) + 250e3) / 3 + 50e3, ((2 * ((contact_pads[8].end.y - xmon_center.y) + 250e3) / 3)**2 + ((contact_pads[8].end.x - xmon_center.x) / 2)**2)**0.5, (contact_pads[8].end.x - xmon_center.x) / 4 - cross_len_x, 230e3 ], turn_angles=[ pi / 2, -atan2( (contact_pads[8].end.x - xmon_center.x) / 2, 2 * ((contact_pads[8].end.y - xmon_center.y) + 250e3) / 3), -pi / 2 + atan2( (contact_pads[8].end.x - xmon_center.x) / 2, 2 * ((contact_pads[8].end.y - xmon_center.y) + 250e3) / 3), -pi / 2 ], trans_in=Trans.R180) self.cpwrl_fl5.place(tmp_reg) self.cpwrl_fl5_end = FluxLineEnd(self.cpwrl_fl5.end, z_md_fl, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl5_end.place(tmp_reg)
class Design5Q(ChipDesign): def __init__(self, cell_name): super().__init__(cell_name) info_el2 = pya.LayerInfo(3, 0) # for DC contact deposition self.region_el2 = Region() self.layer_el2 = self.layout.layer(info_el2) info_bridges1 = pya.LayerInfo(4, 0) # bridge photo layer 1 self.region_bridges1 = Region() self.layer_bridges1 = self.layout.layer(info_bridges1) info_bridges2 = pya.LayerInfo(5, 0) # bridge photo layer 2 self.region_bridges2 = Region() self.layer_bridges2 = self.layout.layer(info_bridges2) self.lv.add_missing_layers( ) # has to call it once more to add new layers ### ADDITIONAL VARIABLES SECTION START ### self.contact_pads: list[ContactPad] = None # chip rectangle and contact pads self.chip = CHIP_10x10_12pads self.chip_box = self.chip.box # readout line parameters self.ro_line_turn_radius: float = 200e3 self.ro_line_dy: float = 1600e3 self.cpwrl_ro_line: CPW_RL_Path = None self.Z0 = CPWParameters(CHIP_10x10_12pads.chip_cpw_width, CHIP_10x10_12pads.chip_cpw_gap) # resonators objects list self.resonators: List[EMResonatorTL3QbitWormRLTailXmonFork] = [] # distance between nearest resonators central conductors centers # constant step between resonators origin points along x-axis. self.resonators_dx = 790e3 # resonator parameters self.L_coupling_list = [1e3 * x for x in [230, 225, 225, 220, 215]] # corresponding to resonanse freq is linspaced in interval [6,9) GHz self.L0 = 1600e3 self.L1_list = [1e3 * x for x in [53.7163, 73, 91, 87, 48]] self.r = 60e3 self.N = 5 self.L2_list = [self.r] * len(self.L1_list) self.L3_list = [None] * len(self.L1_list) # to be constructed self.L4_list = [self.r] * len(self.L1_list) self.width_res = 20e3 self.gap_res = 10e3 self.Z_res = CPWParameters(self.width_res, self.gap_res) self.to_line_list = [53e3] * len(self.L1_list) self.fork_metal_width = 20e3 self.fork_gnd_gap = 10e3 self.xmon_fork_gnd_gap = 25e3 # resonator-fork parameters # -20e3 for Xmons in upper sweet-spot # -10e3 for Xmons in lower sweet-spot self.xmon_fork_penetration_list = [-25e3] * len(self.L1_list) # xmon parameters self.cross_width: float = 60e3 self.cross_len: float = 60e3 self.cross_gnd_gap: float = 20e3 self.xmon_x_distance: float = 485e3 # from simulation of g_12 self.xmon_dys_Cg_coupling = [ 1e3 * x for x in [11.2065, 9.31433, 12.0965, 10.0777, 12.9573] ] self.xmons: list[XmonCross] = [] self.cross_len_x = 180e3 self.cross_width_x = 60e3 self.cross_gnd_gap_x = 20e3 self.cross_len_y = 60e3 self.cross_width_y = 60e3 self.cross_gnd_gap_y = 20e3 # squids self.squids: List[AsymSquid] = [] self.el_dc_contacts: List[List[ElementBase, ElementBase]] = [] # md and flux lines attributes self.shift_fl_y = self.cross_len_y + 70e3 self.shift_md_x = 150e3 self.shift_md_y = 360e3 self.cpwrl_md1: CPW_RL_Path = None self.cpwrl_md1_end: MDriveLineEnd = None self.cpwrl_fl1: CPW_RL_Path = None self.cpwrl_fl1_end: FluxLineEnd = None self.cpwrl_md2: CPW_RL_Path = None self.cpwrl_md2_end: MDriveLineEnd = None self.cpwrl_fl2: CPW_RL_Path = None self.cpwrl_fl2_end: FluxLineEnd = None self.cpwrl_md3: CPW_RL_Path = None self.cpwrl_md3_end: MDriveLineEnd = None self.cpwrl_fl3: CPW_RL_Path = None self.cpwrl_fl3_end: FluxLineEnd = None self.cpwrl_md4: CPW_RL_Path = None self.cpwrl_md4_end: MDriveLineEnd = None self.cpwrl_fl4: CPW_RL_Path = None self.cpwrl_fl4_end: FluxLineEnd = None self.cpwrl_md5: CPW_RL_Path = None self.cpwrl_md5_end: MDriveLineEnd = None self.cpwrl_fl5: CPW_RL_Path = None self.cpwrl_fl5_end: FluxLineEnd = None # marks self.marks: List[Mark2] = [] ### ADDITIONAL VARIABLES SECTION END ### def draw(self, design_params=None): self.draw_chip() ''' Only creating object. This is due to the drawing of xmons and resonators require draw xmons, then draw resonators and then draw additional xmons. This is ugly and that how this was before migrating to `ChipDesign` based code structure This is also the reason why `self.__init__` is flooded with design parameters that are used across multiple drawing functions. TODO: This drawings sequence can be decoupled in the future. ''' self.create_resonator_objects() self.draw_readout_waveguide() self.draw_xmons_and_resonators() self.draw_md_and_flux_lines() self.draw_josephson_loops() self.draw_el_dc_contacts() self.draw_photo_el_marks() self.draw_bridges() # self.inverse_destination(self.region_ph) self.cell.shapes(self.layer_ph).insert(self.region_ph) self.cell.shapes(self.layer_el).insert(self.region_el) self.cell.shapes(self.layer_el2).insert(self.region_el2) self.cell.shapes(self.layer_bridges1).insert(self.region_bridges1) self.cell.shapes(self.layer_bridges2).insert(self.region_bridges2) def draw_chip(self): self.region_ph.insert(self.chip_box) self.contact_pads = self.chip.get_contact_pads() for contact_pad in self.contact_pads: contact_pad.place(self.region_ph) def create_resonator_objects(self): # fork at the end of resonator parameters fork_x_span = self.cross_width + 2 * (self.xmon_fork_gnd_gap + self.fork_metal_width) ### RESONATORS TAILS CALCULATIONS SECTION START ### # key to the calculations can be found in hand-written format here: # https://drive.google.com/file/d/1wFmv5YmHAMTqYyeGfiqz79a9kL1MtZHu/view?usp=sharing # x span between left long vertical line and # right-most center of central conductors resonators_widths = [ 2 * self.r + L_coupling for L_coupling in self.L_coupling_list ] x1 = 2 * self.resonators_dx + resonators_widths[ 2] / 2 - 2 * self.xmon_x_distance x2 = x1 + self.xmon_x_distance - self.resonators_dx x3 = resonators_widths[2] / 2 x4 = 3 * self.resonators_dx - (x1 + 3 * self.xmon_x_distance) x5 = 4 * self.resonators_dx - (x1 + 4 * self.xmon_x_distance) res_tail_shape = "LRLRL" tail_turn_radiuses = self.r # list corrected for resonator-qubit coupling geomtry, so all transmons centers are placed # along single horizontal line self.L0_list = [ self.L0 - xmon_dy_Cg_coupling for xmon_dy_Cg_coupling in self.xmon_dys_Cg_coupling ] self.L2_list[0] += 6 * self.Z_res.b self.L2_list[1] += 0 self.L2_list[3] += 3 * self.Z_res.b self.L2_list[4] += 6 * self.Z_res.b self.L3_list[0] = x1 self.L3_list[1] = x2 self.L3_list[2] = x3 self.L3_list[3] = x4 self.L3_list[4] = x5 self.L4_list[1] += 6 * self.Z_res.b self.L4_list[2] += 6 * self.Z_res.b self.L4_list[3] += 3 * self.Z_res.b tail_segment_lengths_list = [[ L2, L3, L4 ] for L2, L3, L4 in zip(self.L2_list, self.L3_list, self.L4_list)] tail_turn_angles_list = [ [pi / 2, -pi / 2], [pi / 2, -pi / 2], [pi / 2, -pi / 2], [-pi / 2, pi / 2], [-pi / 2, pi / 2], ] tail_trans_in_list = [ Trans.R270, Trans.R270, Trans.R270, Trans.R270, Trans.R270 ] ### RESONATORS TAILS CALCULATIONS SECTION END ### pars = list( zip(self.L1_list, self.to_line_list, self.L_coupling_list, self.xmon_fork_penetration_list, tail_segment_lengths_list, tail_turn_angles_list, tail_trans_in_list, self.L0_list)) for res_idx, params in enumerate(pars): # parameters exctraction L1 = params[0] to_line = params[1] L_coupling = params[2] xmon_fork_penetration = params[3] tail_segment_lengths = params[4] tail_turn_angles = params[5] tail_trans_in = params[6] L0 = params[7] # deduction for resonator placements # under condition that Xmon-Xmon distance equals # `xmon_x_distance` worm_x = self.contact_pads[-1].end.x + (res_idx + 1 / 2) * self.resonators_dx worm_y = self.contact_pads[-1].end.y - self.ro_line_dy - to_line # `fork_y_span` based on coupling modulated with # xmon_fork_penetration from `self.xmon_fork_penetration` fork_y_span = xmon_fork_penetration + self.xmon_fork_gnd_gap self.resonators.append( EMResonatorTL3QbitWormRLTailXmonFork( self.Z_res, DPoint(worm_x, worm_y), L_coupling, L0, L1, self.r, self.N, tail_shape=res_tail_shape, tail_turn_radiuses=tail_turn_radiuses, tail_segment_lengths=tail_segment_lengths, tail_turn_angles=tail_turn_angles, tail_trans_in=tail_trans_in, fork_x_span=fork_x_span, fork_y_span=fork_y_span, fork_metal_width=self.fork_metal_width, fork_gnd_gap=self.fork_gnd_gap)) # print([self.L0 - xmon_dy_Cg_coupling for xmon_dy_Cg_coupling in self.xmon_dys_Cg_coupling]) # print(self.L1_list) # print(self.L2_list) # print(self.L3_list) # print(self.L4_list) def draw_readout_waveguide(self): ''' Subdividing horizontal waveguide adjacent to resonators into several waveguides. Even segments of this adjacent waveguide are adjacent to resonators. Bridges will be placed on odd segments later. Returns ------- None ''' # place readout waveguide ro_line_turn_radius = self.ro_line_turn_radius ro_line_dy = self.ro_line_dy pcb_feedline_d = CHIP_10x10_12pads.pcb_feedline_d # first and last segment will have length `self.resonator_dx/2` res_line_total_length = (1 + self.resonators_dx) * len(self.resonators) ## calculating segment lengths of subdivided coupling part of ro coplanar ## # value that need to be added to `L_coupling` to get width of resonators bbox. def get_res_extension(resonator: EMResonatorTL3QbitWormRLTailXmonFork): return resonator.Z0.b + 2 * resonator.r def get_res_width(resonator: EMResonatorTL3QbitWormRLTailXmonFork): return (resonator.L_coupling + get_res_extension(resonator)) res_line_segments_lengths = [ self.resonators[0].origin.x - self.contact_pads[-1].end.x - get_res_extension(self.resonators[0]) / 2 ] # length from bend to first bbox of first resonator for i, resonator in enumerate(self.resonators[:-1]): resonator_extension = get_res_extension(resonator) resonator_width = get_res_width(resonator) next_resonator_extension = get_res_extension(self.resonators[i + 1]) # order of adding is from left to right (imagine chip geometry in your head to follow) res_line_segments_lengths.extend([ resonator_width, # `resonator_extension` accounts for the next resonator extension # in this case all resonator's extensions are equal self.resonators_dx - (resonator_width - resonator_extension / 2) - next_resonator_extension / 2 ]) res_line_segments_lengths.extend( [get_res_width(self.resonators[-1]), self.resonators_dx / 2]) segment_lengths = [ro_line_dy] + res_line_segments_lengths + \ [ro_line_dy / 2, res_line_total_length - self.chip.pcb_feedline_d, ro_line_dy / 2] self.cpwrl_ro_line = CPW_RL_Path( self.contact_pads[-1].end, shape="LR" + ''.join(['L'] * len(res_line_segments_lengths)) + "RLRLRL", cpw_parameters=self.Z0, turn_radiuses=[ro_line_turn_radius] * 4, segment_lengths=segment_lengths, turn_angles=[pi / 2, pi / 2, pi / 2, -pi / 2], trans_in=Trans.R270) self.cpwrl_ro_line.place(self.region_ph) def draw_xmons_and_resonators(self): for resonator, xmon_fork_penetration, xmon_dy_Cg_coupling in zip( self.resonators, self.xmon_fork_penetration_list, self.xmon_dys_Cg_coupling): xmon_center = (resonator.fork_y_cpw1.end + resonator.fork_y_cpw2.end) / 2 + \ DVector(0, -xmon_dy_Cg_coupling) xmon_center += DPoint( 0, -(self.cross_len + self.cross_width / 2) + xmon_fork_penetration) self.xmons.append( XmonCross(xmon_center, self.cross_len_x, self.cross_width_x, self.cross_gnd_gap_x, sideY_length=self.cross_len_y, sideY_width=self.cross_width_y, sideY_gnd_gap=self.cross_gnd_gap_y)) self.xmons[-1].place(self.region_ph) resonator.place(self.region_ph) xmonCross_corrected = XmonCross(xmon_center, sideX_length=self.cross_len_x, sideX_width=self.cross_width_x, sideX_gnd_gap=self.cross_gnd_gap_x, sideY_length=self.cross_len_y, sideY_width=self.cross_width_y, sideY_gnd_gap=min( self.cross_gnd_gap_y, self.xmon_fork_gnd_gap)) xmonCross_corrected.place(self.region_ph) def draw_md_and_flux_lines(self): """ Drawing of md (microwave drive) and flux tuning lines for 5 qubits Returns ------- """ contact_pads = self.contact_pads ctr_line_turn_radius = 200e3 xmon_center = self.xmons[-1].center xmon_x_distance = self.xmon_x_distance cross_width_y = self.cross_width_y cross_width_x = self.cross_width_x cross_len_x = self.cross_len_x cross_gnd_gap_y = self.cross_gnd_gap_y cross_gnd_gap_x = self.cross_gnd_gap_x width_res = self.Z_res.width tmp_reg = self.region_ph z_md_fl = self.Z0 shift_fl_y = self.shift_fl_y shift_md_x = self.shift_md_x shift_md_y = self.shift_md_y flux_end_width = self.cross_width_x + 2 * self.cross_gnd_gap_x md_transition = 25e3 md_z1_params = CPWParameters( 7e3, 4e3 ) # Z = 50.04 Ohm, E_eff = 6.237 (E_0 = 11.45) (8e3, 4.15e3) md_z1_length = 100e3 shift_md_x_side = md_z1_length + md_transition + md_z1_params.b / 2 + cross_len_x + cross_width_x / 2 + cross_gnd_gap_x # place caplanar line 1md self.cpwrl_md1 = CPW_RL_Path( contact_pads[0].end, shape="LRLRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius] * 2, segment_lengths=[ 2 * (-contact_pads[0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16, ((contact_pads[0].end.y - xmon_center.y)**2 + (9 * (-contact_pads[0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16)**2)**0.5, 5 * (-contact_pads[0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16 - 140e3 ], turn_angles=[ -atan2( contact_pads[0].end.y - xmon_center.y, 9 * (-contact_pads[0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16), atan2( contact_pads[0].end.y - xmon_center.y, 9 * (-contact_pads[0].end.x + xmon_center.x - 4 * xmon_x_distance - shift_md_x_side) / 16) ], trans_in=Trans.R0) self.cpwrl_md1.place(tmp_reg) self.cpwrl_md1_end = MDriveLineEnd( list(self.cpwrl_md1.primitives.values())[-1], md_z1_params, md_transition, md_z1_length) self.cpwrl_md1_end.place(tmp_reg) # place caplanar line 1 fl self.cpwrl_fl1 = CPW_RL_Path( contact_pads[1].end, shape="LRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius], segment_lengths=[(-contact_pads[1].end.x + xmon_center.x - 4 * xmon_x_distance - cross_len_x), (-contact_pads[1].end.y + xmon_center.y - cross_width_y / 2 - cross_gnd_gap_y - width_res) ], turn_angles=[pi / 2], trans_in=Trans.R0) self.cpwrl_fl1.place(tmp_reg) self.cpwrl_fl1_end = FluxLineEnd(self.cpwrl_fl1.end, z_md_fl, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl1_end.place(tmp_reg) # place caplanar line 2md self.cpwrl_md2 = CPW_RL_Path( contact_pads[3].end, shape="LRLRLRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius] * 3, segment_lengths=[ (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 4, (-contact_pads[3].end.x + xmon_center.x + shift_md_x - 3 * xmon_x_distance) / 2, (((-contact_pads[3].end.x + xmon_center.x + shift_md_x - 3 * xmon_x_distance) / 2)**2 + (5 * (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 8)**2)**0.5, (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 8 ], turn_angles=[ -pi / 2, atan2( 5 * (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 8, (-contact_pads[3].end.x + xmon_center.x + shift_md_x - 3 * xmon_x_distance) / 2), pi / 2 - atan2( 5 * (-contact_pads[3].end.y + xmon_center.y - shift_md_y) / 8, (-contact_pads[3].end.x + xmon_center.x + shift_md_x - 3 * xmon_x_distance) / 2) ], trans_in=Trans.R90) self.cpwrl_md2.place(tmp_reg) self.cpwrl_md2_end = MDriveLineEnd( list(self.cpwrl_md2.primitives.values())[-1], md_z1_params, md_transition, md_z1_length) self.cpwrl_md2_end.place(tmp_reg) # place caplanar line 2 fl self.cpwrl_fl2 = CPW_RL_Path( contact_pads[2].end, shape="LRLRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius] * 2, segment_lengths=[ (-contact_pads[2].end.x + xmon_center.x - 3 * xmon_x_distance) / 4, ((3 * (-contact_pads[2].end.x + xmon_center.x - 3 * xmon_x_distance) / 4)**2 + (7 * (-contact_pads[2].end.y + xmon_center.y - shift_fl_y) / 8)**2)**0.5, (-contact_pads[2].end.y + xmon_center.y - shift_fl_y) / 8 ], turn_angles=[ atan2( 7 * (-contact_pads[2].end.y + xmon_center.y - shift_fl_y) / 8, 3 * (-contact_pads[2].end.x + xmon_center.x - 3 * xmon_x_distance) / 4), pi / 2 - atan2( 7 * (-contact_pads[2].end.y + xmon_center.y - shift_fl_y) / 8, 3 * (-contact_pads[2].end.x + xmon_center.x - 3 * xmon_x_distance) / 4) ], trans_in=Trans.R0) self.cpwrl_fl2.place(tmp_reg) self.cpwrl_fl2_end = FluxLineEnd(self.cpwrl_fl2.end, z_md_fl, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl2_end.place(tmp_reg) # place caplanar line 3md self.cpwrl_md3 = CPW_RL_Path( contact_pads[5].end, shape="LRLRLRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius] * 3, segment_lengths=[ (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 4, (contact_pads[5].end.x - xmon_center.x - shift_md_x + 2 * xmon_x_distance) / 2, (((contact_pads[5].end.x - xmon_center.x - shift_md_x + 2 * xmon_x_distance) / 2)**2 + (5 * (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 8)**2)**0.5, (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 8 ], turn_angles=[ pi / 2, -atan2( 5 * (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 8, (contact_pads[5].end.x - xmon_center.x - shift_md_x + 2 * xmon_x_distance) / 2), -pi / 2 + atan2( 5 * (-contact_pads[5].end.y + xmon_center.y - shift_md_y) / 8, (contact_pads[5].end.x - xmon_center.x - shift_md_x + 2 * xmon_x_distance) / 2) ], trans_in=Trans.R90) self.cpwrl_md3.place(tmp_reg) self.cpwrl_md3_end = MDriveLineEnd( list(self.cpwrl_md3.primitives.values())[-1], md_z1_params, md_transition, md_z1_length) self.cpwrl_md3_end.place(tmp_reg) # place caplanar line 3 fl fl_l1 = (self.xmons[2].cpw_bempt.end.y - contact_pads[4].end.y) / 4 fl_l3 = fl_l1 dr = self.xmons[2].cpw_bempt.end - contact_pads[4].end dr.y = dr.y - fl_l1 - fl_l3 - z_md_fl.width turn_angle = atan2(-dr.x, dr.y) fl_l2 = dr.abs() self.cpwrl_fl3 = CPW_RL_Path(self.contact_pads[4].end, shape="LRLRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius] * 2, segment_lengths=[fl_l1, fl_l2, fl_l3], turn_angles=[turn_angle, -turn_angle], trans_in=Trans.R90) self.cpwrl_fl3.place(tmp_reg) self.cpwrl_fl3_end = FluxLineEnd(self.cpwrl_fl3.end, z_md_fl, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl3_end.place(tmp_reg) # place caplanar line 4 md self.cpwrl_md4 = CPW_RL_Path( contact_pads[7].end, shape="LRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius], segment_lengths=[ contact_pads[7].end.x - xmon_center.x + xmon_x_distance - shift_md_x, -contact_pads[7].end.y + xmon_center.y - shift_md_y ], turn_angles=[-pi / 2], trans_in=Trans.R180) self.cpwrl_md4.place(tmp_reg) self.cpwrl_md4_end = MDriveLineEnd( list(self.cpwrl_md4.primitives.values())[-1], md_z1_params, md_transition, md_z1_length) self.cpwrl_md4_end.place(tmp_reg) # place caplanar line 4 fl self.cpwrl_fl4 = CPW_RL_Path( contact_pads[6].end, shape="LRLRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius] * 2, segment_lengths=[ (contact_pads[6].end.x - xmon_center.x + xmon_x_distance) / 4, ((6 * (-contact_pads[6].end.y + xmon_center.y - shift_fl_y) / 8)**2 + (3 * (contact_pads[6].end.x - xmon_center.x + xmon_x_distance) / 4)**2)**0.5, 2 * (-contact_pads[6].end.y + xmon_center.y - shift_fl_y) / 8 ], turn_angles=[ -atan2( 6 * (-contact_pads[6].end.y + xmon_center.y - shift_fl_y) / 8, 3 * (contact_pads[6].end.x - xmon_center.x + xmon_x_distance) / 4), -pi / 2 + atan2( 6 * (-contact_pads[6].end.y + xmon_center.y - shift_fl_y) / 8, 3 * (contact_pads[6].end.x - xmon_center.x + xmon_x_distance) / 4) ], trans_in=Trans.R180) self.cpwrl_fl4.place(tmp_reg) self.cpwrl_fl4_end = FluxLineEnd(self.cpwrl_fl4.end, z_md_fl, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl4_end.place(tmp_reg) # place caplanar line 5 md self.cpwrl_md5 = CPW_RL_Path( contact_pads[9].end, shape="LRLRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius] * 2, segment_lengths=[ 2 * (contact_pads[9].end.y - xmon_center.y) / 3, (((contact_pads[9].end.y - xmon_center.y) / 3)**2 + (2 * (contact_pads[9].end.x - xmon_center.x - shift_md_x_side) / 3)**2)**(0.5), (contact_pads[9].end.x - xmon_center.x - shift_md_x_side) / 3 - 140e3 ], turn_angles=[ -atan2( 2 * (contact_pads[9].end.x - xmon_center.x - shift_md_x_side) / 3, (contact_pads[9].end.y - xmon_center.y) / 3), atan2( 2 * (contact_pads[9].end.x - xmon_center.x - shift_md_x_side) / 3, (contact_pads[9].end.y - xmon_center.y) / 3) - pi / 2 ], trans_in=Trans.R270) self.cpwrl_md5.place(tmp_reg) self.cpwrl_md5_end = MDriveLineEnd( list(self.cpwrl_md5.primitives.values())[-1], md_z1_params, md_transition, md_z1_length) self.cpwrl_md5_end.place(tmp_reg) # place caplanar line 5 fl self.cpwrl_fl5 = CPW_RL_Path( contact_pads[8].end, shape="LRLRLRLRL", cpw_parameters=z_md_fl, turn_radiuses=[ctr_line_turn_radius] * 4, segment_lengths=[ (contact_pads[8].end.x - xmon_center.x) / 4, ((contact_pads[8].end.y - xmon_center.y) + 250e3) / 3 + 50e3, ((2 * ((contact_pads[8].end.y - xmon_center.y) + 250e3) / 3)**2 + ((contact_pads[8].end.x - xmon_center.x) / 2)**2)**0.5, (contact_pads[8].end.x - xmon_center.x) / 4 - cross_len_x, 230e3 ], turn_angles=[ pi / 2, -atan2( (contact_pads[8].end.x - xmon_center.x) / 2, 2 * ((contact_pads[8].end.y - xmon_center.y) + 250e3) / 3), -pi / 2 + atan2( (contact_pads[8].end.x - xmon_center.x) / 2, 2 * ((contact_pads[8].end.y - xmon_center.y) + 250e3) / 3), -pi / 2 ], trans_in=Trans.R180) self.cpwrl_fl5.place(tmp_reg) self.cpwrl_fl5_end = FluxLineEnd(self.cpwrl_fl5.end, z_md_fl, width=flux_end_width, trans_in=Trans.R0) self.cpwrl_fl5_end.place(tmp_reg) def draw_josephson_loops(self): new_pars_squid = AsymSquidParams(pad_r=5e3, pads_distance=30e3, p_ext_width=5e3, p_ext_r=200, sq_len=7e3, sq_area=35e6, j_width_1=94, j_width_2=347, intermediate_width=500, b_ext=1e3, j_length=94, n=20, bridge=180, j_length_2=250) # place left squid xmon0 = self.xmons[0] center1 = DPoint( self.cpwrl_fl1_end.end.x, xmon0.center.y - (xmon0.sideX_width + xmon0.sideX_gnd_gap) / 2) squid = AsymSquid(center1, new_pars_squid, 0) squid.place(self.region_el) self.squids.append(squid) # place intermediate squids for xmon_cross in self.xmons[1:-1]: squid_center = (xmon_cross.cpw_bempt.start + xmon_cross.cpw_bempt.end) / 2 squid = AsymSquid(squid_center, new_pars_squid, 0) squid.place(self.region_el) # place right squid xmon5 = self.xmons[4] center5 = DPoint( self.cpwrl_fl5_end.end.x, xmon5.center.y - (xmon5.sideX_width + xmon5.sideX_gnd_gap) / 2) squid = AsymSquid(center5, new_pars_squid, 0) squid.place(self.region_el) def draw_el_dc_contacts(self): for squid in self.squids: r_pad = squid.params.pad_r center_up = squid.pad_up.center + DPoint(0, r_pad) center_down = squid.pad_down.center + DPoint(0, -r_pad) self.el_dc_contacts.append( [Circle(center_up, 2 * r_pad), Circle(center_down, 2 * r_pad)]) for contact in self.el_dc_contacts[-1]: contact.place(self.region_el2) def draw_photo_el_marks(self): marks_centers = [DPoint(1200e3, 9000e3), DPoint(8000e3, 4000e3)] for mark_center in marks_centers: self.marks.append(Mark2(mark_center)) self.marks[-1].place(self.region_ph) def draw_bridges(self): self.region_bridges2.insert(self.chip_box) bridges_step = 50e3 # for resonators for resonator in self.resonators: for name, res_primitive in resonator.primitives.items(): if "coil0" in name: # skip L_coupling coplanar. bridgify_lambda = lambda x: Bridge1.bridgify_CPW( x, bridges_step, dest=self.region_bridges1, dest2=self.region_bridges2) # bridgyfy all in "coil0" except for the first cpw that # is adjacent to readout line and has length equal to `L_coupling` map(bridgify_lambda, list(res_primitive.primitives.values())[1:]) continue elif "fork" in name: # skip fork primitives continue else: # bridgify everything else Bridge1.bridgify_CPW(res_primitive, bridges_step, dest=self.region_bridges1, dest2=self.region_bridges2) # for contact wires for key, val in self.__dict__.items(): if ("cpwrl_md" in key) or ("cpwrl_fl" in key): Bridge1.bridgify_CPW(val, bridges_step, dest=self.region_bridges1, dest2=self.region_bridges2) # for readout waveguide bridgified_primitives_idxs = list(range(2)) bridgified_primitives_idxs += list( range(2, 2 * (len(self.resonators) + 1) + 1, 2)) bridgified_primitives_idxs += list( range(2 * (len(self.resonators) + 1) + 1, len(self.cpwrl_ro_line.primitives.values()))) for idx, primitive in enumerate( self.cpwrl_ro_line.primitives.values()): if idx in bridgified_primitives_idxs: Bridge1.bridgify_CPW(primitive, bridges_step, dest=self.region_bridges1, dest2=self.region_bridges2)