Note
This page was generated from circuit-examples//full-design-flow-examples//Example-full-chip-design.ipynb.
Example full chip design¶
[1]:
%load_ext autoreload
%autoreload 2
Make sure to have the right kernel selected!
[2]:
import qiskit_metal as metal
from qiskit_metal import designs, draw
from qiskit_metal import MetalGUI, Dict, open_docs
%metal_heading Welcome to Qiskit Metal!
Welcome to Qiskit Metal!
Welcome to Qiskit Metal!
For this example tutorial, we will attempt to create a multi qubit chip with a variety of components. We will want to generate the layout, simulate/analyze and tune the chip to hit the parameters we are wanting, finally rendering to a GDS file.
One could generate subsections of the layout and tune individual components first, but in this case we will create all of the layout. We will be using both transmon pockets and crossmons, meandered and simple transmission lines, capacitive couplers, and launchers for wirebond connections. So we will import these, and also create a design instance and launch the GUI.
Layout¶
[3]:
from qiskit_metal.qlibrary.qubits.transmon_pocket_6 import TransmonPocket6
from qiskit_metal.qlibrary.qubits.transmon_cross_fl import TransmonCrossFL
from qiskit_metal.qlibrary.couplers.tunable_coupler_01 import TunableCoupler01
from qiskit_metal.qlibrary.tlines.meandered import RouteMeander
from qiskit_metal.qlibrary.tlines.pathfinder import RoutePathfinder
from qiskit_metal.qlibrary.tlines.anchored_path import RouteAnchors
from qiskit_metal.qlibrary.lumped.cap_n_interdigital import CapNInterdigital
from qiskit_metal.qlibrary.couplers.cap_n_interdigital_tee import CapNInterdigitalTee
from qiskit_metal.qlibrary.couplers.coupled_line_tee import CoupledLineTee
from qiskit_metal.qlibrary.terminations.launchpad_wb import LaunchpadWirebond
from qiskit_metal.qlibrary.terminations.launchpad_wb_coupled import LaunchpadWirebondCoupled
[4]:
design = metal.designs.DesignPlanar()
gui = metal.MetalGUI(design)
Since we are likely to be making many changes while tuning and modifying our design, we will enable overwriting. We can also check all of the chip properties to see if we want to change the size or any other parameter.
[5]:
design.overwrite_enabled = True
design.chips.main
[5]:
{'material': 'silicon',
'layer_start': '0',
'layer_end': '2048',
'size': {'center_x': '0.0mm',
'center_y': '0.0mm',
'center_z': '0.0mm',
'size_x': '9mm',
'size_y': '6mm',
'size_z': '-750um',
'sample_holder_top': '890um',
'sample_holder_bottom': '1650um'}}
[6]:
design.chips.main.size.size_x = '11mm'
design.chips.main.size.size_y = '9mm'
The Qubits¶
We will add a collection of qubits. First we will place a transmon pocket with six connection pads. We can see any options the qubit qcomponent has to figure out what we might want to modify when creating the component. This will include the components default options (which the component designer included) as well as renderer options (which are added based on what renderers are present in Metal).
[7]:
TransmonPocket6.get_template_options(design)
[7]:
{'pos_x': '0um',
'pos_y': '0um',
'connection_pads': {},
'_default_connection_pads': {'pad_gap': '15um',
'pad_width': '125um',
'pad_height': '30um',
'pad_cpw_shift': '0um',
'pad_cpw_extent': '25um',
'cpw_width': '10um',
'cpw_gap': '6um',
'cpw_extend': '100um',
'pocket_extent': '5um',
'pocket_rise': '0um',
'loc_W': '+1',
'loc_H': '+1'},
'chip': 'main',
'pad_gap': '30um',
'inductor_width': '20um',
'pad_width': '455um',
'pad_height': '90um',
'pocket_width': '650um',
'pocket_height': '650um',
'orientation': '0',
'hfss_wire_bonds': False,
'q3d_wire_bonds': False,
'hfss_inductance': '10nH',
'hfss_capacitance': 0,
'hfss_resistance': 0,
'hfss_mesh_kw_jj': 7e-06,
'q3d_inductance': '10nH',
'q3d_capacitance': 0,
'q3d_resistance': 0,
'q3d_mesh_kw_jj': 7e-06,
'gds_cell_name': 'my_other_junction'}
[8]:
options = dict(
pad_width = '425 um',
pocket_height = '650um',
connection_pads=dict(
readout = dict(loc_W=0, loc_H=-1, pad_width = '80um', pad_gap = '50um'),
bus_01 = dict(loc_W=-1, loc_H=-1, pad_width = '60um', pad_gap = '10um'),
bus_02 = dict(loc_W=-1, loc_H=+1, pad_width = '60um', pad_gap = '10um'),
bus_03 = dict(loc_W=0, loc_H=+1, pad_width = '90um', pad_gap = '30um'),
bus_04 = dict(loc_W=+1, loc_H=+1, pad_width = '60um', pad_gap = '10um'),
bus_05 = dict(loc_W=+1, loc_H=-1, pad_width = '60um', pad_gap = '10um')
))
q_main = TransmonPocket6(design,'Q_Main', options = dict(
pos_x='0mm',
pos_y='-1mm',
gds_cell_name ='FakeJunction_01',
hfss_inductance ='14nH',
**options))
gui.rebuild()
gui.autoscale()
We then will add a mixture of additional qubits. This is not (though do not let me stop any experimental investigation) a design one would normally create for any experiment of computational purpose, but allows for having a mixture of different components on one chip.
[9]:
TransmonCrossFL.get_template_options(design)
[9]:
{'pos_x': '0um',
'pos_y': '0um',
'connection_pads': {},
'_default_connection_pads': {'connector_type': '0',
'claw_length': '30um',
'ground_spacing': '5um',
'claw_width': '10um',
'claw_gap': '6um',
'connector_location': '0'},
'cross_width': '20um',
'cross_length': '200um',
'cross_gap': '20um',
'orientation': '0',
'layer': '1',
'make_fl': True,
'fl_options': {'t_top': '15um',
't_offset': '0um',
't_inductive_gap': '3um',
't_width': '5um',
't_gap': '3um'},
'hfss_wire_bonds': False,
'q3d_wire_bonds': False,
'hfss_inductance': '10nH',
'hfss_capacitance': 0,
'hfss_resistance': 0,
'hfss_mesh_kw_jj': 7e-06,
'q3d_inductance': '10nH',
'q3d_capacitance': 0,
'q3d_resistance': 0,
'q3d_mesh_kw_jj': 7e-06,
'gds_cell_name': 'my_other_junction'}
We will add two crossmons with flux lines to the west side of the chip, which we will couple to each other using a tunable coupler. To make sure the various readout and control lines will have space to connect to launchers at the chip edge, we have to be mindful of where we place them, and making sure we have enough space for routing while avoiding cross talk.
[10]:
Q1 = TransmonCrossFL(design, 'Q1', options = dict(pos_x = '-2.75mm', pos_y='-1.8mm',
connection_pads = dict(
bus_01 = dict(connector_location = '180',claw_length ='95um'),
readout = dict(connector_location = '0')),
fl_options = dict()))
Q2 = TransmonCrossFL(design, 'Q2', options = dict(pos_x = '-2.75mm', pos_y='-1.2mm', orientation = '180',
connection_pads = dict(
bus_02 = dict(connector_location = '0',claw_length ='95um'),
readout = dict(connector_location = '180')),
fl_options = dict()))
tune_c_Q12 = TunableCoupler01(design,'Tune_C_Q12', options = dict(pos_x = '-2.81mm', pos_y = '-1.5mm',
orientation=90, c_width='500um'))
gui.rebuild()
gui.autoscale()
We then will add three transmon pockets to the north side of the chip, with the intention of having them in a linear series of coupling to each other, as well as the ‘main’ qubit to the south.
[11]:
Q3 = TransmonPocket6(design,'Q3', options = dict(
pos_x='-3mm',
pos_y='0.5mm',
gds_cell_name ='FakeJunction_01',
hfss_inductance ='14nH',
connection_pads = dict(
bus_03 = dict(loc_W=0, loc_H=-1, pad_width = '80um', pad_gap = '15um'),
bus_q3_q4 = dict(loc_W=1, loc_H=-1, pad_width = '80um', pad_gap = '15um'),
readout = dict(loc_W=0, loc_H=1, pad_width = '80um', pad_gap = '50um'))))
Q4 = TransmonPocket6(design,'Q4', options = dict(
pos_x='0mm',
pos_y='1mm',
gds_cell_name ='FakeJunction_01',
hfss_inductance ='14nH',
connection_pads = dict(
bus_04 = dict(loc_W=0, loc_H=-1, pad_width = '80um', pad_gap = '15um'),
bus_q3_q4 = dict(loc_W=-1, loc_H=-1, pad_width = '80um', pad_gap = '15um'),
bus_q4_q5 = dict(loc_W=1, loc_H=-1, pad_width = '80um', pad_gap = '15um'),
readout = dict(loc_W=0, loc_H=1, pad_width = '80um', pad_gap = '50um'))))
Q5 = TransmonPocket6(design,'Q5', options = dict(
pos_x='3mm',
pos_y='0.5mm',
gds_cell_name ='FakeJunction_01',
hfss_inductance ='14nH',
connection_pads = dict(
bus_05 = dict(loc_W=0, loc_H=-1, pad_width = '80um', pad_gap = '15um'),
bus_q4_q5 = dict(loc_W=-1, loc_H=-1, pad_width = '80um', pad_gap = '15um'),
readout = dict(loc_W=0, loc_H=1, pad_width = '80um', pad_gap = '50um'))))
The Busses¶
We now couple the qubits to each other, primarily using RouteMeander. Although one needs to run simulations to properly tune the line lengths for target frequencies, an initial estimate could be determined from the below method;
[12]:
from qiskit_metal.analyses.em.cpw_calculations import guided_wavelength
def find_resonator_length(frequency, line_width, line_gap, N):
#frequency in GHz
#line_width/line_gap in um
#N -> 2 for lambda/2, 4 for lambda/4
[lambdaG, etfSqrt, q] = guided_wavelength(frequency*10**9, line_width*10**-6,
line_gap*10**-6, 750*10**-6, 200*10**-9)
return str(lambdaG/N*10**3)+" mm"
As we are not worried about a creating a functional chip in this tutorial, we will give the resonators somewhat arbitraty lengths. First coupling the two crossmons to Q_Main.
[13]:
bus_01 = RouteMeander(design,'Bus_01', options = dict(hfss_wire_bonds = True,
pin_inputs=Dict(
start_pin=Dict(
component='Q_Main',
pin='bus_01'),
end_pin=Dict(
component='Q1',
pin='bus_01')
),
lead=Dict(
start_straight='125um',
end_straight = '225um'
),
meander=Dict(
asymmetry = '1305um'),
fillet = "99um",
total_length = '6mm'))
bus_02 = RouteMeander(design,'Bus_02', options = dict(hfss_wire_bonds = True,
pin_inputs=Dict(
start_pin=Dict(
component='Q_Main',
pin='bus_02'),
end_pin=Dict(
component='Q2',
pin='bus_02')
),
lead=Dict(
start_straight='325um',
end_straight = '125um'
),
meander=Dict(
asymmetry = '450um'),
fillet = "99um",
total_length = '6.4mm'))
gui.rebuild()
Then the three transmon pockets on the north side to Q_Main.
[14]:
bus_03 = RouteMeander(design,'Bus_03', options = dict(hfss_wire_bonds = True,
pin_inputs=Dict(
start_pin=Dict(
component='Q_Main',
pin='bus_03'),
end_pin=Dict(
component='Q3',
pin='bus_03')
),
lead=Dict(
start_straight='225um',
end_straight = '25um'
),
meander=Dict(
asymmetry = '50um'),
fillet = "99um",
total_length = '6.8mm'))
#To help set the right spacing, jogs can be used to set some initially controlled routing paths
from collections import OrderedDict
jogs_start = OrderedDict()
jogs_start[0] = ["L", '250um']
jogs_start[1] = ["R", '200um']
jogs_end = OrderedDict()
jogs_end[0] = ["L", '600um']
bus_04 = RouteMeander(design,'Bus_04', options = dict(hfss_wire_bonds = True,
pin_inputs=Dict(
start_pin=Dict(
component='Q_Main',
pin='bus_04'),
end_pin=Dict(
component='Q4',
pin='bus_04')
),
lead=Dict(
start_straight='225um',
#end_straight = '25um',
start_jogged_extension=jogs_start,
#end_jogged_extension = jogs_end
),
meander=Dict(
asymmetry = '150um'),
fillet = "99um",
total_length = '7.2mm'))
bus_05 = RouteMeander(design,'Bus_05', options = dict(hfss_wire_bonds = True,
pin_inputs=Dict(
start_pin=Dict(
component='Q_Main',
pin='bus_05'),
end_pin=Dict(
component='Q5',
pin='bus_05')
),
lead=Dict(
start_straight='225um',
end_straight = '25um'
),
meander=Dict(
asymmetry = '50um'),
fillet = "99um",
total_length = '7.6mm'))
gui.rebuild()
Finally the three transmon pockets on the north side to each other. This concludes the interconnectivity between the qubits.
[15]:
bus_q3_q4 = RouteMeander(design,'Bus_Q3_Q4', options = dict(hfss_wire_bonds = True,
pin_inputs=Dict(
start_pin=Dict(
component='Q3',
pin='bus_q3_q4'),
end_pin=Dict(
component='Q4',
pin='bus_q3_q4')
),
lead=Dict(
start_straight='125um',
end_straight = '125um'
),
meander=Dict(
asymmetry = '50um'),
fillet = "99um",
total_length = '6.4mm'))
bus_q4_q5 = RouteMeander(design,'Bus_Q4_Q5', options = dict(hfss_wire_bonds = True,
pin_inputs=Dict(
start_pin=Dict(
component='Q4',
pin='bus_q4_q5'),
end_pin=Dict(
component='Q5',
pin='bus_q4_q5')
),
lead=Dict(
start_straight='125um',
end_straight = '25um'
),
meander=Dict(
asymmetry = '50um'),
fillet = "99um",
total_length = '6.8mm'))
gui.rebuild()
The Readouts and Control Lines¶
The intention for this design is to have the three north transmon pockets be multiplexed to one readout line. The crossmons to their own readouts, as well as Q_Main. The tunable coupler, and the two crossmons also have flux lines which need to be connected to launchers. First we will place the wirebond launchers at the edges of the chip.
[16]:
launch_qmain_read = LaunchpadWirebond(design, 'Launch_QMain_Read', options = dict(pos_x = '2mm', pos_y ='-4mm', orientation = '90'))
launch_q1_fl = LaunchpadWirebond(design, 'Launch_Q1_FL', options = dict(pos_x = '0mm', pos_y ='-4mm', orientation = '90',
trace_width = '5um',
trace_gap = '3um',))
launch_q1_read = LaunchpadWirebondCoupled(design, 'Launch_Q1_Read', options = dict(pos_x = '-2mm', pos_y ='-4mm', orientation = '90'))
launch_tcoup_fl = LaunchpadWirebond(design, 'Launch_TuneC_FL', options = dict(pos_x = '-4mm', pos_y ='-4mm', orientation = '90',
trace_width = '5um',
trace_gap = '3um',))
launch_tcoup_read = LaunchpadWirebondCoupled(design, 'Launch_TuneC_Read', options = dict(pos_x = '-5mm', pos_y ='-3mm', orientation = '0'))
launch_q2_read = LaunchpadWirebondCoupled(design, 'Launch_Q2_Read', options = dict(pos_x = '-5mm', pos_y ='-1mm', orientation = '0'))
launch_q2_fl = LaunchpadWirebond(design, 'Launch_Q2_FL', options = dict(pos_x = '-5mm', pos_y ='1mm', orientation = '0',
trace_width = '5um',
trace_gap = '3um',))
launch_nw = LaunchpadWirebond(design, 'Launch_NW',options = dict(pos_x = '-5mm', pos_y='3mm', orientation=0))
launch_ne = LaunchpadWirebond(design, 'Launch_NE',options = dict(pos_x = '5mm', pos_y='3mm', orientation=180))
gui.rebuild()
We then will add in the readout resonators for Q_Main, Q1, Q2 and the tuneable coupler. We will add a finger capacitor for the Q_Main readout, instead of just using the LaunchpadWirebondCoupled.
[17]:
#Main Readout
read_q_main_cap = CapNInterdigital(design,'Read_Q_Main_Cap', options = dict(pos_x = '2mm', pos_y ='-3.5mm', orientation = '0'))
jogs_end = OrderedDict()
jogs_end[0] = ["L", '600um']
jogs_start = OrderedDict()
jogs_start[0] = ["L", '250um']
read_q_main = RouteMeander(design,'Read_Q_Main', options = dict(hfss_wire_bonds = True,
pin_inputs=Dict(
start_pin=Dict(
component='Q_Main',
pin='readout'),
end_pin=Dict(
component='Read_Q_Main_Cap',
pin='north_end')
),
lead=Dict(
start_straight='725um',
end_straight = '625um',
start_jogged_extension = jogs_start,
end_jogged_extension = jogs_end
),
meander=Dict(
asymmetry = '50um'),
fillet = "99um",
total_length = '5.6mm'))
read_q_main_cap_launch = RoutePathfinder(design, 'Read_Q_Main_Cap_Launch', options = dict(hfss_wire_bonds = True,
pin_inputs = dict(
start_pin=Dict(
component='Read_Q_Main_Cap',
pin='south_end'),
end_pin=Dict(
component='Launch_QMain_Read',
pin='tie')),
lead=Dict(
start_straight='0um',
end_straight = '0um',
#start_jogged_extension = jogs_start,
#end_jogged_extension = jogs_end
)))
gui.rebuild()
[18]:
#Crossmon's Readouts
jogs_end = OrderedDict()
jogs_end[0] = ["L", '600um']
jogs_start = OrderedDict()
jogs_start[0] = ["L", '250um']
read_q1 = RouteMeander(design,'Read_Q1', options = dict(hfss_wire_bonds = True,
pin_inputs=Dict(
start_pin=Dict(
component='Q1',
pin='readout'),
end_pin=Dict(
component='Launch_Q1_Read',
pin='tie')
),
lead=Dict(
start_straight='250um',
end_straight = '25um',
#start_jogged_extension = jogs_start,
#end_jogged_extension = jogs_end
),
meander=Dict(
asymmetry = '50um'),
fillet = "99um",
total_length = '6.8mm'))
jogs_end = OrderedDict()
jogs_end[0] = ["L", '600um']
jogs_start = OrderedDict()
jogs_start[0] = ["L", '250um']
read_tunec = RouteMeander(design,'Read_TuneC', options = dict(hfss_wire_bonds = True,
pin_inputs=Dict(
start_pin=Dict(
component='Tune_C_Q12',
pin='Control'),
end_pin=Dict(
component='Launch_TuneC_Read',
pin='tie')
),
lead=Dict(
start_straight='1525um',
end_straight = '125um',
#start_jogged_extension = jogs_start,
#end_jogged_extension = jogs_end
),
meander=Dict(
asymmetry = '50um'),
fillet = "99um",
total_length = '5.8mm'))
jogs_end = OrderedDict()
jogs_end[0] = ["L", '600um']
jogs_start = OrderedDict()
jogs_start[0] = ["L", '250um']
read_q2 = RouteMeander(design,'Read_Q2', options = dict(hfss_wire_bonds = True,
pin_inputs=Dict(
start_pin=Dict(
component='Q2',
pin='readout'),
end_pin=Dict(
component='Launch_Q2_Read',
pin='tie')
),
lead=Dict(
start_straight='350um',
end_straight = '0um',
#start_jogged_extension = jogs_start,
#end_jogged_extension = jogs_end
),
meander=Dict(
asymmetry = '-450um'),
fillet = "99um",
total_length = '5.4mm'))
gui.rebuild()
Finishing off this section of the chip by connecting the flux lines to appropraite wirebond launch pads.
[19]:
#Crossmon flux lines
flux_line_Q1 = RoutePathfinder(design,'Flux_Line_Q1', options = dict(hfss_wire_bonds = True,
pin_inputs=Dict(
start_pin=Dict(
component='Q1',
pin='flux_line'),
end_pin=Dict(
component='Launch_Q1_FL',
pin='tie')),
fillet = '99um',
trace_width = '5um',
trace_gap = '3um',
#anchors = anchors
))
jogs_start = OrderedDict()
jogs_start[0] = ["L", '750um']
flux_line_tunec = RoutePathfinder(design,'Flux_Line_TuneC', options = dict(hfss_wire_bonds = True,
pin_inputs=Dict(
start_pin=Dict(
component='Tune_C_Q12',
pin='Flux'),
end_pin=Dict(
component='Launch_TuneC_FL',
pin='tie')),
lead=Dict(
start_straight='875um',
end_straight = '350um',
start_jogged_extension = jogs_start,
#end_jogged_extension = jogs_end
),
fillet = '99um',
trace_width = '5um',
trace_gap = '3um',
#anchors = anchors
))
jogs_start = OrderedDict()
jogs_start[0] = ["L", '525um']
jogs_start[1] = ["R", '625um']
flux_line_Q2 = RoutePathfinder(design,'Flux_Line_Q2', options = dict(hfss_wire_bonds = True,
pin_inputs=Dict(
start_pin=Dict(
component='Q2',
pin='flux_line'),
end_pin=Dict(
component='Launch_Q2_FL',
pin='tie')),
lead=Dict(
start_straight='175um',
end_straight = '150um',
start_jogged_extension = jogs_start,
#end_jogged_extension = jogs_end
),
fillet = '99um',
trace_width = '5um',
trace_gap = '3um',
#anchors = anchors
))
gui.rebuild()
Shifting our focus now to the three transmon pockets in the north. As we want these to be multiplexed to a single readout line, we will add in a few three port components, such as the CoupledLineTee and CapNInterdigitalTee. Q3 will have an inductive coupling to the readout line (as we want a lambda/4 resonator), Q4 will have a simple gap capacitor, and Q5 will have an interdigitated capacitor.
[20]:
q3_read_T = CoupledLineTee(design,'Q3_Read_T', options=dict(pos_x = '-3mm', pos_y = '3mm',
orientation = '0',
coupling_length = '200um',
open_termination = False))
#We use finger count to set the width of the gap capacitance, -> N*cap_width + (N-1)*cap_gap
q4_read_T = CapNInterdigitalTee(design,'Q4_Read_T', options=dict(pos_x = '0mm', pos_y = '3mm',
orientation = '0',
finger_length = '0um',
finger_count = '8'))
q5_read_T = CapNInterdigitalTee(design,'Q5_Read_T', options=dict(pos_x = '3mm', pos_y = '3mm',
orientation = '0',
finger_length = '50um',
finger_count = '11'))
gui.rebuild()
We add in the readout resonators to each respective qubit.
[21]:
read_q3 = RouteMeander(design,'Read_Q3', options = dict(hfss_wire_bonds = True,
pin_inputs=Dict(
start_pin=Dict(
component='Q3',
pin='readout'),
end_pin=Dict(
component='Q3_Read_T',
pin='second_end')
),
lead=Dict(
start_straight='150um',
end_straight = '150um',
#start_jogged_extension = jogs_start,
#end_jogged_extension = jogs_end
),
meander=Dict(
asymmetry = '0um'),
fillet = "99um",
total_length = '5mm'))
read_q4 = RouteMeander(design,'Read_Q4', options = dict(hfss_wire_bonds = True,
pin_inputs=Dict(
start_pin=Dict(
component='Q4',
pin='readout'),
end_pin=Dict(
component='Q4_Read_T',
pin='second_end')
),
lead=Dict(
start_straight='125um',
end_straight = '125um',
#start_jogged_extension = jogs_start,
#end_jogged_extension = jogs_end
),
meander=Dict(
asymmetry = '0um'),
fillet = "99um",
total_length = '5.8mm'))
read_q5 = RouteMeander(design,'Read_Q5', options = dict(hfss_wire_bonds = True,
pin_inputs=Dict(
start_pin=Dict(
component='Q5',
pin='readout'),
end_pin=Dict(
component='Q5_Read_T',
pin='second_end')
),
lead=Dict(
start_straight='125um',
end_straight = '125um',
#start_jogged_extension = jogs_start,
#end_jogged_extension = jogs_end
),
meander=Dict(
asymmetry = '0um'),
fillet = "99um",
total_length = '5.4mm'))
gui.rebuild()
We complete the layout by connecting the multiplexed readout line to the launchpads on either side of the chip.
[22]:
mp_tl_01 = RoutePathfinder(design, 'ML_TL_01', options = dict(hfss_wire_bonds = True,
pin_inputs = dict(
start_pin=Dict(
component='Launch_NW',
pin='tie'),
end_pin=Dict(
component='Q3_Read_T',
pin='prime_start'))
))
mp_tl_02 = RoutePathfinder(design, 'ML_TL_02', options = dict(hfss_wire_bonds = True,
pin_inputs = dict(
start_pin=Dict(
component='Q3_Read_T',
pin='prime_end'),
end_pin=Dict(
component='Q4_Read_T',
pin='prime_start'))
))
mp_tl_03 = RoutePathfinder(design, 'ML_TL_03', options = dict(hfss_wire_bonds = True,
pin_inputs = dict(
start_pin=Dict(
component='Q4_Read_T',
pin='prime_end'),
end_pin=Dict(
component='Q5_Read_T',
pin='prime_start'))
))
mp_tl_04 = RoutePathfinder(design, 'ML_TL_04', options = dict(hfss_wire_bonds = True,
pin_inputs = dict(
start_pin=Dict(
component='Q5_Read_T',
pin='prime_end'),
end_pin=Dict(
component='Launch_NE',
pin='tie'))
))
gui.rebuild()
With this, we have completed the construction of our layout.
Now, anyone familiar with chip design might find some of the location choices to be sub-optimal, with large sections of your chip left unused, or perhaps some CPW transmission lines running a bit closer to each other than would be ideal for avoiding cross talk concerns. These could be address by shifting the origin of your chip, or modifying component options to better compact your layout and alleviate crosstalk concerns.
For this tutorial, we aren’t too concerned how much space we may use up on our fictional chip, so we will instead continue on to analysis and tuning.
[23]:
gui.autoscale()
gui.screenshot()
Analyze¶
First we want to quickly look at the qubit parameters. Initial simulation and analysis is to use a lumped element approximation, by extracting the capacitance matrix of the qubit. We first analyze the qubit Q_Main
, by first extracting the matrix and then using LOM analysis on it.
For starters, let’s select the appropriate QAnalysis class.
[24]:
from qiskit_metal.analyses.quantization import LOManalysis
c1 = LOManalysis(design, "q3d")
We can check if we wish to change any of the default options for the analysis. You should modify the number of passes and convergence based on the accuracy you require for your simulation.
Depending on the complexity of the simulation, it could take a minute, or multiple hours. It is generally best to start with a small number of max_passes
if you are unsure, so can you get a sense on the timing. As each adaptive pass adds additional tetrahedrons, the simulation time per pass will increase significantly (as well as the amount of system memory necessary).
[25]:
c1.sim.setup
[25]:
{'name': 'Setup',
'reuse_selected_design': True,
'freq_ghz': 5.0,
'save_fields': False,
'enabled': True,
'max_passes': 15,
'min_passes': 2,
'min_converged_passes': 2,
'percent_error': 0.5,
'percent_refinement': 30,
'auto_increase_solution_order': True,
'solution_order': 'High',
'solver_type': 'Iterative'}
[26]:
c1.sim.setup.name = 'Tune_Q_Main'
c1.sim.setup.max_passes = 16
c1.sim.setup.min_converged_passes = 2
c1.sim.setup.percent_error = 0.05
c1.sim.setup
[26]:
{'name': 'Tune_Q_Main',
'reuse_selected_design': True,
'freq_ghz': 5.0,
'save_fields': False,
'enabled': True,
'max_passes': 16,
'min_passes': 2,
'min_converged_passes': 2,
'percent_error': 0.05,
'percent_refinement': 30,
'auto_increase_solution_order': True,
'solution_order': 'High',
'solver_type': 'Iterative'}
Next we will want to run the simulation for Q_Main. To obtain the complete capacitance matrix from this simulation, we will want to terminate the unconnected pins of Q_Main with opens, so that they are regarded as isolated charge islands in the simulation. You will need to list all of the pin names in the call. To recall them, one can look at the GUI, or check the pin dictionary attached to Q_Main: q_main.pins.keys()
.
[27]:
c1.sim.run(name="Q_Main", components=['Q_Main'], open_terminations=[('Q_Main', 'readout'), ('Q_Main', 'bus_01'),('Q_Main', 'bus_02'),('Q_Main', 'bus_03'),
('Q_Main', 'bus_04'), ('Q_Main', 'bus_05')])
INFO 09:51AM [connect_project]: Connecting to Ansys Desktop API...
INFO 09:51AM [load_ansys_project]: Opened Ansys App
INFO 09:51AM [load_ansys_project]: Opened Ansys Desktop v2020.2.0
INFO 09:51AM [load_ansys_project]: Opened Ansys Project
Folder: C:/Ansoft/
Project: Project23
INFO 09:51AM [connect_design]: No active design found (or error getting active design).
INFO 09:51AM [connect]: Connected to project "Project23". No design detected
INFO 09:51AM [connect_design]: Opened active design
Design: Q_Main_q3d [Solution type: Q3D]
WARNING 09:51AM [connect_setup]: No design setup detected.
WARNING 09:51AM [connect_setup]: Creating Q3D default setup.
INFO 09:51AM [get_setup]: Opened setup `Setup` (<class 'pyEPR.ansys.AnsysQ3DSetup'>)
INFO 09:51AM [get_setup]: Opened setup `Tune_Q_Main` (<class 'pyEPR.ansys.AnsysQ3DSetup'>)
INFO 09:51AM [analyze]: Analyzing setup Tune_Q_Main
INFO 09:55AM [get_matrix]: Exporting matrix data to (C:\Temp\tmpjks6h_rl.txt, C, , Tune_Q_Main:LastAdaptive, "Original", "ohm", "nH", "fF", "mSie", 5000000000, Maxwell, 1, False
INFO 09:55AM [get_matrix]: Exporting matrix data to (C:\Temp\tmpmpomn8hh.txt, C, , Tune_Q_Main:AdaptivePass, "Original", "ohm", "nH", "fF", "mSie", 5000000000, Maxwell, 1, False
INFO 09:55AM [get_matrix]: Exporting matrix data to (C:\Temp\tmpo1bs65q6.txt, C, , Tune_Q_Main:AdaptivePass, "Original", "ohm", "nH", "fF", "mSie", 5000000000, Maxwell, 2, False
INFO 09:55AM [get_matrix]: Exporting matrix data to (C:\Temp\tmp27ap2rm7.txt, C, , Tune_Q_Main:AdaptivePass, "Original", "ohm", "nH", "fF", "mSie", 5000000000, Maxwell, 3, False
INFO 09:55AM [get_matrix]: Exporting matrix data to (C:\Temp\tmpid24udcc.txt, C, , Tune_Q_Main:AdaptivePass, "Original", "ohm", "nH", "fF", "mSie", 5000000000, Maxwell, 4, False
INFO 09:55AM [get_matrix]: Exporting matrix data to (C:\Temp\tmpanpc3fp0.txt, C, , Tune_Q_Main:AdaptivePass, "Original", "ohm", "nH", "fF", "mSie", 5000000000, Maxwell, 5, False
INFO 09:55AM [get_matrix]: Exporting matrix data to (C:\Temp\tmp7xe__y8o.txt, C, , Tune_Q_Main:AdaptivePass, "Original", "ohm", "nH", "fF", "mSie", 5000000000, Maxwell, 6, False
INFO 09:55AM [get_matrix]: Exporting matrix data to (C:\Temp\tmpzbj0ejdi.txt, C, , Tune_Q_Main:AdaptivePass, "Original", "ohm", "nH", "fF", "mSie", 5000000000, Maxwell, 7, False
INFO 09:55AM [get_matrix]: Exporting matrix data to (C:\Temp\tmp_kgnraw6.txt, C, , Tune_Q_Main:AdaptivePass, "Original", "ohm", "nH", "fF", "mSie", 5000000000, Maxwell, 8, False
INFO 09:55AM [get_matrix]: Exporting matrix data to (C:\Temp\tmpa99kh4q1.txt, C, , Tune_Q_Main:AdaptivePass, "Original", "ohm", "nH", "fF", "mSie", 5000000000, Maxwell, 9, False
INFO 09:55AM [get_matrix]: Exporting matrix data to (C:\Temp\tmp_e2tr4z4.txt, C, , Tune_Q_Main:AdaptivePass, "Original", "ohm", "nH", "fF", "mSie", 5000000000, Maxwell, 10, False
INFO 09:55AM [get_matrix]: Exporting matrix data to (C:\Temp\tmpfth1uezt.txt, C, , Tune_Q_Main:AdaptivePass, "Original", "ohm", "nH", "fF", "mSie", 5000000000, Maxwell, 11, False
INFO 09:55AM [get_matrix]: Exporting matrix data to (C:\Temp\tmpzhz29lld.txt, C, , Tune_Q_Main:AdaptivePass, "Original", "ohm", "nH", "fF", "mSie", 5000000000, Maxwell, 12, False
INFO 09:55AM [get_matrix]: Exporting matrix data to (C:\Temp\tmp2ly1bynz.txt, C, , Tune_Q_Main:AdaptivePass, "Original", "ohm", "nH", "fF", "mSie", 5000000000, Maxwell, 13, False
INFO 09:55AM [get_matrix]: Exporting matrix data to (C:\Temp\tmppd5sj06r.txt, C, , Tune_Q_Main:AdaptivePass, "Original", "ohm", "nH", "fF", "mSie", 5000000000, Maxwell, 14, False
INFO 09:55AM [get_matrix]: Exporting matrix data to (C:\Temp\tmpx3ryjtku.txt, C, , Tune_Q_Main:AdaptivePass, "Original", "ohm", "nH", "fF", "mSie", 5000000000, Maxwell, 15, False
INFO 09:55AM [get_matrix]: Exporting matrix data to (C:\Temp\tmpqgpyoudh.txt, C, , Tune_Q_Main:AdaptivePass, "Original", "ohm", "nH", "fF", "mSie", 5000000000, Maxwell, 16, False
INFO 09:55AM [get_matrix]: Exporting matrix data to (C:\Temp\tmp0ypb80s2.txt, C, , Tune_Q_Main:AdaptivePass, "Original", "ohm", "nH", "fF", "mSie", 5000000000, Maxwell, 17, False
With the simulation completed, we can look at the capacitance matrix.
[28]:
c1.sim.capacitance_matrix
[28]:
bus_01_connector_pad_Q_Main | bus_02_connector_pad_Q_Main | bus_03_connector_pad_Q_Main | bus_04_connector_pad_Q_Main | bus_05_connector_pad_Q_Main | ground_main_plane | pad_bot_Q_Main | pad_top_Q_Main | readout_connector_pad_Q_Main | |
---|---|---|---|---|---|---|---|---|---|
bus_01_connector_pad_Q_Main | 41.02176 | -0.24001 | -0.11719 | -0.04481 | -0.07874 | -29.00822 | -9.26982 | -1.06835 | -0.69738 |
bus_02_connector_pad_Q_Main | -0.24001 | 41.00041 | -0.75929 | -0.07826 | -0.04484 | -28.98620 | -1.07415 | -9.21369 | -0.10640 |
bus_03_connector_pad_Q_Main | -0.11719 | -0.75929 | 45.49485 | -0.75936 | -0.11710 | -31.95144 | -1.30891 | -9.60366 | -0.15780 |
bus_04_connector_pad_Q_Main | -0.04481 | -0.07826 | -0.75936 | 41.02315 | -0.24004 | -29.00650 | -1.07408 | -9.21787 | -0.10629 |
bus_05_connector_pad_Q_Main | -0.07874 | -0.04484 | -0.11710 | -0.24004 | 41.00041 | -28.98777 | -9.26969 | -1.06800 | -0.69718 |
ground_main_plane | -29.00822 | -28.98620 | -31.95144 | -29.00650 | -28.98777 | 308.85307 | -33.31374 | -32.77926 | -31.47933 |
pad_bot_Q_Main | -9.26982 | -1.07415 | -1.30891 | -1.07408 | -9.26969 | -33.31374 | 95.77645 | -31.23494 | -7.05105 |
pad_top_Q_Main | -1.06835 | -9.21369 | -9.60366 | -9.21787 | -1.06800 | -32.77926 | -31.23494 | 97.45815 | -1.13125 |
readout_connector_pad_Q_Main | -0.69738 | -0.10640 | -0.15780 | -0.10629 | -0.69718 | -31.47933 | -7.05105 | -1.13125 | 42.10847 |
But more importantly, we can use that matrix to run LOM analysis.
[29]:
c1.setup.junctions = Dict({'Lj': 14, 'Cj': 2})
c1.setup.freq_readout = 7.0
c1.setup.freq_bus = [5.6, 5.7, 5.8, 5.9, 6.0] # list of the bus frequencies
c1.run_lom()
c1.lumped_oscillator_all
[6, 7] [8 0 1 2 3 4]
Predicted Values
Transmon Properties
f_Q 4.963607 [GHz]
EC 298.739021 [MHz]
EJ 11.671114 [GHz]
alpha -351.473280 [MHz]
dispersion 85.768110 [KHz]
Lq 13.994355 [nH]
Cq 64.839966 [fF]
T1 139.259252 [us]
**Coupling Properties**
tCqbus1 3.015572 [fF]
gbus1_in_MHz 43.820486 [MHz]
χ_bus1 -0.287307 [MHz]
1/T1bus1 223.182422 [Hz]
T1bus1 713.115943 [us]
tCqbus2 4.171076 [fF]
gbus2_in_MHz 48.504025 [MHz]
χ_bus2 -2.645931 [MHz]
1/T1bus2 287.292183 [Hz]
T1bus2 553.982853 [us]
tCqbus3 -3.999772 [fF]
gbus3_in_MHz -47.339949 [MHz]
χ_bus3 -1.980823 [MHz]
1/T1bus3 204.154172 [Hz]
T1bus3 779.582126 [us]
tCqbus4 -4.073126 [fF]
gbus4_in_MHz -49.034442 [MHz]
χ_bus4 -1.716249 [MHz]
1/T1bus4 169.570131 [Hz]
T1bus4 938.578876 [us]
tCqbus5 -4.001869 [fF]
gbus5_in_MHz -49.021470 [MHz]
χ_bus5 -1.415561 [MHz]
1/T1bus5 135.025422 [Hz]
T1bus5 1178.703542 [us]
tCqbus6 4.171183 [fF]
gbus6_in_MHz 51.958983 [MHz]
χ_bus6 -1.335697 [MHz]
1/T1bus6 123.643673 [Hz]
T1bus6 1287.206527 [us]
Bus-Bus Couplings
gbus1_2 3.325733 [MHz]
gbus1_3 1.912509 [MHz]
gbus1_4 2.174045 [MHz]
gbus1_5 1.979171 [MHz]
gbus1_6 3.559683 [MHz]
gbus2_3 2.144945 [MHz]
gbus2_4 2.034516 [MHz]
gbus2_5 1.819268 [MHz]
gbus2_6 1.928359 [MHz]
gbus3_4 3.378480 [MHz]
gbus3_5 1.912662 [MHz]
gbus3_6 1.881624 [MHz]
gbus4_5 3.496435 [MHz]
gbus4_6 2.177719 [MHz]
gbus5_6 2.376495 [MHz]
[29]:
fQ | EC | EJ | alpha | dispersion | gbus | chi_in_MHz | χr MHz | gr MHz | |
---|---|---|---|---|---|---|---|---|---|
1 | 5.334856 | 349.017036 | 11.671114 | -418.169804 | 304.17916 | [46.33925002733205, 44.187331992065, -42.60569... | [-0.5299131495471634, -9.027355440831576, -5.3... | 0.529913 | 46.339250 |
2 | 5.293479 | 343.185353 | 11.671114 | -410.316354 | 266.531163 | [44.48347532561871, 43.91119291374231, -40.557... | [-0.46063358481393896, -7.215266047760587, -4.... | 0.460634 | 44.483475 |
3 | 5.17092 | 326.250466 | 11.671114 | -387.687301 | 177.943279 | [43.075350634431345, 44.952056360711815, -42.4... | [-0.3648586676742546, -4.484695488473718, -2.8... | 0.364859 | 43.075351 |
4 | 5.108373 | 317.801003 | 11.671114 | -376.493737 | 143.687618 | [43.13448774561514, 43.30507017705921, -44.091... | [-0.3364016456250303, -3.3214019525977982, -2.... | 0.336402 | 43.134488 |
5 | 5.074637 | 313.297364 | 11.671114 | -370.553464 | 127.750448 | [43.277211774574475, 45.44982592921459, -43.97... | [-0.3238225188245248, -3.2664264401609686, -2.... | 0.323823 | 43.277212 |
6 | 5.041406 | 308.897746 | 11.671114 | -364.767715 | 113.602489 | [43.129687798475445, 46.338514084696286, -45.2... | [-0.3078723909186688, -3.0514480686225833, -2.... | 0.307872 | 43.129688 |
7 | 5.023692 | 306.56726 | 11.671114 | -361.709895 | 106.643367 | [43.19413642807277, 46.657953431831764, -45.44... | [-0.3017295453629039, -2.9276804873799436, -2.... | 0.301730 | 43.194136 |
8 | 5.008631 | 304.593954 | 11.671114 | -359.124452 | 101.0268 | [43.35990049055785, 46.99778023673387, -46.254... | [-0.2981493080591482, -2.837011006665539, -2.1... | 0.298149 | 43.359900 |
9 | 4.995019 | 302.81687 | 11.671114 | -356.799016 | 96.177974 | [43.46480555843615, 47.44716630141518, -46.470... | [-0.29435169781569703, -2.77574777235584, -2.0... | 0.294352 | 43.464806 |
10 | 4.989574 | 302.107679 | 11.671114 | -355.871761 | 94.296886 | [43.597944296844695, 47.654276741440626, -46.5... | [-0.294078462456382, -2.7551199777315323, -2.0... | 0.294078 | 43.597944 |
11 | 4.98144 | 301.050061 | 11.671114 | -354.489758 | 91.547639 | [43.550558591120705, 48.01342068567195, -46.89... | [-0.2903720998583706, -2.7305526898818075, -2.... | 0.290372 | 43.550559 |
12 | 4.975829 | 300.321846 | 11.671114 | -353.538756 | 89.693095 | [43.677893070257284, 48.10303127872349, -47.06... | [-0.28996661844835814, -2.6961457251648193, -2... | 0.289967 | 43.677893 |
13 | 4.97308 | 299.965387 | 11.671114 | -353.073412 | 88.796586 | [43.74422948775013, 48.268028637087, -47.10813... | [-0.28981954135701093, -2.693030802856854, -2.... | 0.289820 | 43.744229 |
14 | 4.969275 | 299.47245 | 11.671114 | -352.430083 | 87.568934 | [43.73302237009102, 48.38885048108347, -47.226... | [-0.2882553488551673, -2.6768170445299937, -2.... | 0.288255 | 43.733022 |
15 | 4.966898 | 299.164667 | 11.671114 | -352.028505 | 86.809485 | [43.77570019556721, 48.46146286708871, -47.343... | [-0.2879360055703413, -2.6664620128030103, -1.... | 0.287936 | 43.775700 |
16 | 4.963607 | 298.739021 | 11.671114 | -351.47328 | 85.76811 | [43.82048616757409, 48.50402461483827, -47.339... | [-0.2873072774566821, -2.6459305257029584, -1.... | 0.287307 | 43.820486 |
Which gives us the qubits frequency, anharmonicity, and coupling strength to the different connection pads.
We can further check if these parameters converged well. If they have not, we may want to modify our simulation in order to get a more accurate result. We then will want to make modifications to our qubit options, such as pad_gap
of the qubit, or modifying the size of the connection pads, in order to hit the desired qubit anharmonicity or readout chi values respectively.
[30]:
c1.plot_convergence();
c1.plot_convergence_chi()
INFO 09:55AM [hfss_report_full_convergence]: Creating report for variation 0
Design "Q_Main_q3d" info:
# eigenmodes 0
# variations 1
Once the analysis and tuning is complete, we can stop the analysis and the renderer.
[31]:
c1.sim.close()
Once each of our qubits have been run through LOM, we can begin to look at the resonant busses and readouts, and larger coupled sections of the chip. One such case could be looking at Q_Main, Q5, and Bus_05. This allows us not only to look at some of the parameters of the individual qubits, but also the bus frequency and if the qubits are coupled (via the bus) to the degree we wish.
Preparations¶
We will setup the design and simulation in the same manner as we did previously, but with the methods needed for an eigenmode simulation.
[32]:
from qiskit_metal.analyses.quantization import EPRanalysis
eig_qb = EPRanalysis(design, "hfss")
(optional) you can tune the wirebond size by directly modifying the renderer options.
[33]:
eig_qb.sim.renderer.options['wb_size'] = 5
Review and update the simulation setup by executing following two cells.
[34]:
em_p = eig_qb.sim.setup
[35]:
em_p.name = '3Modes'
em_p.min_freq_ghz = 4
em_p.n_modes = 3
em_p.max_passes = 10
em_p.max_delta_f = 0.1
em_p.min_converged = 2
# Design variables can also be added in for direct simulation sweeps.
em_p.vars = Dict({'Lj1': '13 nH', 'Cj1': '0 fF', 'Lj2': '15 nH', 'Cj2': '0 fF'})
eig_qb.sim.setup
[35]:
{'name': '3Modes',
'reuse_selected_design': True,
'min_freq_ghz': 4,
'n_modes': 3,
'max_delta_f': 0.1,
'max_passes': 10,
'min_passes': 1,
'min_converged': 2,
'pct_refinement': 30,
'basis_order': 1,
'vars': {'Lj1': '13 nH', 'Cj1': '0 fF', 'Lj2': '15 nH', 'Cj2': '0 fF'}}
Before we execute the analysis, we want to update the design if needed. For example we may want to modify the junction inductance of the two qubits based on the previous LOM analysis, so they are near the desired frequency. Further, one may want to change the length of the bus after initial simulations to get it to the target frequency:
[36]:
q_main.options.hfss_inductance
[36]:
'14nH'
[37]:
Q5.options.hfss_inductance
[37]:
'14nH'
[38]:
q_main.options.hfss_inductance = '13nH'
Q5.options.hfss_inductance = '15nH'
bus_05.options.total_length = '7.5mm'
gui.rebuild()
We can now run the simulation on the specified layout. All unconnected pins are left as shorts, as we are only concerned about simulating the resonant mode of the three components listed.
[39]:
eig_qb.sim.run(name="QMain_Q5_Bus05", components=['Q_Main', 'Q5','Bus_05'], open_terminations=[])
INFO 09:55AM [connect_project]: Connecting to Ansys Desktop API...
INFO 09:55AM [load_ansys_project]: Opened Ansys App
INFO 09:55AM [load_ansys_project]: Opened Ansys Desktop v2020.2.0
INFO 09:55AM [load_ansys_project]: Opened Ansys Project
Folder: C:/Ansoft/
Project: Project23
INFO 09:55AM [connect_design]: Opened active design
Design: Q_Main_q3d [Solution type: Q3D]
INFO 09:55AM [get_setup]: Opened setup `Setup` (<class 'pyEPR.ansys.AnsysQ3DSetup'>)
INFO 09:55AM [connect]: Connected to project "Project23" and design "Q_Main_q3d" 😀
INFO 09:55AM [connect_design]: Opened active design
Design: QMain_Q5_Bus05_hfss [Solution type: Eigenmode]
WARNING 09:55AM [connect_setup]: No design setup detected.
WARNING 09:55AM [connect_setup]: Creating eigenmode default setup.
INFO 09:55AM [get_setup]: Opened setup `Setup` (<class 'pyEPR.ansys.HfssEMSetup'>)
INFO 09:55AM [get_setup]: Opened setup `3Modes` (<class 'pyEPR.ansys.HfssEMSetup'>)
INFO 09:55AM [analyze]: Analyzing setup 3Modes
09:59AM 09s INFO [get_f_convergence]: Saved convergences to C:\workspace\qiskit-metal\docs\circuit-examples\full-design-flow-examples\hfss_eig_f_convergence.csv
Once the simulation is complete, we can check to see if the convergence was good.
[40]:
eig_qb.sim.plot_convergences()
With the eigenmode simulation complete (and nicely converged) we can run some EPR analysis on the result.
At first we need to define the junctions in terms of name, inductance_variable, capacitance_variable, rectancle that was defined in the rendering to represent the junction port
and line that was defined in the rendering to represent the direction of the current thorugh the junction.
[41]:
eig_qb.del_junction()
eig_qb.add_junction('jj1', 'Lj1', 'Cj1', rect='JJ_rect_Lj_Q_Main_rect_jj', line='JJ_Lj_Q_Main_rect_jj_')
eig_qb.add_junction('jj2', 'Lj2', 'Cj2', rect='JJ_rect_Lj_Q5_rect_jj', line='JJ_Lj_Q5_rect_jj_')
eig_qb.setup.sweep_variable = 'Lj1'
eig_qb.setup
[41]:
{'junctions': {'jj1': {'Lj_variable': 'Lj1',
'Cj_variable': 'Cj1',
'rect': 'JJ_rect_Lj_Q_Main_rect_jj',
'line': 'JJ_Lj_Q_Main_rect_jj_'},
'jj2': {'Lj_variable': 'Lj2',
'Cj_variable': 'Cj2',
'rect': 'JJ_rect_Lj_Q5_rect_jj',
'line': 'JJ_Lj_Q5_rect_jj_'}},
'dissipatives': {'dielectrics_bulk': ['main']},
'cos_trunc': 8,
'fock_trunc': 7,
'sweep_variable': 'Lj1'}
Note in the previous cell output that the dissipatives have alrady been defined by default.
Now we can start looking at the EPR values. First we look at the electric field and subtrate participation. Then extract the kerr matrix.
[42]:
eig_qb.run_epr()
# (pyEPR allows to switch modes: eprd.set_mode(1))
Design "QMain_Q5_Bus05_hfss" info:
# eigenmodes 3
# variations 1
Design "QMain_Q5_Bus05_hfss" info:
# eigenmodes 3
# variations 1
energy_elec_all = 5.30807060349227e-24
energy_elec_substrate = 4.86434514599116e-24
EPR of substrate = 91.6%
energy_mag = 2.32419129800195e-26
energy_mag % of energy_elec_all = 0.4%
Variation 0 [1/1]
Mode 0 at 4.81 GHz [1/3]
Calculating ℰ_magnetic,ℰ_electric
(ℰ_E-ℰ_H)/ℰ_E ℰ_E ℰ_H
99.6% 2.654e-24 1.162e-26
Calculating junction energy participation ration (EPR)
method=`line_voltage`. First estimates:
junction EPR p_0j sign s_0j (p_capacitive)
Energy fraction (Lj over Lj&Cj)= 97.68%
jj1 3.29205e-06 (+) 7.83062e-08
Energy fraction (Lj over Lj&Cj)= 97.33%
jj2 0.994398 (+) 0.0272922
(U_tot_cap-U_tot_ind)/mean=1.41%
Calculating Qdielectric_main for mode 0 (0/2)
p_dielectric_main_0 = 0.9164055095255939
Mode 1 at 7.39 GHz [2/3]
Calculating ℰ_magnetic,ℰ_electric
(ℰ_E-ℰ_H)/ℰ_E ℰ_E ℰ_H
0.1% 3.353e-24 3.35e-24
Calculating junction energy participation ration (EPR)
method=`line_voltage`. First estimates:
junction EPR p_1j sign s_1j (p_capacitive)
Energy fraction (Lj over Lj&Cj)= 94.69%
jj1 0.000383918 (+) 2.15125e-05
Energy fraction (Lj over Lj&Cj)= 93.93%
jj2 0.000723443 (+) 4.6774e-05
(U_tot_cap-U_tot_ind)/mean=0.00%
Calculating Qdielectric_main for mode 1 (1/2)
p_dielectric_main_1 = 0.9185431895828703
Mode 2 at 14.79 GHz [3/3]
Calculating ℰ_magnetic,ℰ_electric
(ℰ_E-ℰ_H)/ℰ_E ℰ_E ℰ_H
0.0% 2.501e-24 2.501e-24
Calculating junction energy participation ration (EPR)
method=`line_voltage`. First estimates:
junction EPR p_2j sign s_2j (p_capacitive)
Energy fraction (Lj over Lj&Cj)= 81.67%
jj1 5.19757e-05 (+) 1.16685e-05
Energy fraction (Lj over Lj&Cj)= 79.43%
jj2 8.11545e-05 (+) 2.1022e-05
(U_tot_cap-U_tot_ind)/mean=0.00%
Calculating Qdielectric_main for mode 2 (2/2)
p_dielectric_main_2 = 0.91725087597056
WARNING 09:59AM [__init__]: <p>Error: <class 'IndexError'></p>
ANALYSIS DONE. Data saved to:
C:\data-pyEPR\Project23\QMain_Q5_Bus05_hfss\2021-07-20 09-59-11.npz
Differences in variations:
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Variation 0
Starting the diagonalization
Finished the diagonalization
Pm_norm=
modes
0 1.028611
1 1.031457
2 1.123854
dtype: float64
Pm_norm idx =
jj1 jj2
0 False True
1 False False
2 False False
*** P (participation matrix, not normlz.)
jj1 jj2
0 0.000003 0.967980
1 0.000384 0.000723
2 0.000052 0.000081
*** S (sign-bit matrix)
s_jj1 s_jj2
0 1 1
1 1 1
2 1 1
*** P (participation matrix, normalized.)
3.2e-06 1
0.00038 0.00072
5.2e-05 8.1e-05
*** Chi matrix O1 PT (MHz)
Diag is anharmonicity, off diag is full cross-Kerr.
264 0.588 0.132
0.588 0.000408 0.000191
0.132 0.000191 2.24e-05
*** Chi matrix ND (MHz)
298 0.5 0.116
0.5 0.000317 0.000173
0.116 0.000173 2.28e-05
*** Frequencies O1 PT (MHz)
0 4550.033083
1 7388.261062
2 14788.982401
dtype: float64
*** Frequencies ND (MHz)
0 4533.470356
1 7388.272216
2 14788.988393
dtype: float64
*** Q_coupling
Empty DataFrame
Columns: []
Index: [0, 1, 2]
Mode frequencies (MHz)¶
Numerical diagonalization
Lj1 | 13 |
---|---|
eigenmode | |
0 | 4550.03 |
1 | 7388.26 |
2 | 14788.98 |
Kerr Non-linear coefficient table (MHz)¶
Numerical diagonalization
0 | 1 | 2 | ||
---|---|---|---|---|
Lj1 | ||||
13 | 0 | 297.70 | 5.00e-01 | 1.16e-01 |
1 | 0.50 | 3.17e-04 | 1.73e-04 | |
2 | 0.12 | 1.73e-04 | 2.28e-05 |
From the analysis results we can determine the qubits anharmonicities and coupling strength. Once the analysis and tuning is complete, we can close the connection to Ansys.
[43]:
eig_qb.sim.close()
Rendering to a GDS File¶
Once all of the tuning is complete, we will want to prepare a GDS file so we can create a mask and fabricate our chip. We first create a gds render instance.
[44]:
full_chip_gds = design.renderers.gds
The various options for the gds renderer can also be checked and changed as necessary. A key option is the gds file which holds the cells for your junction ebeam design. Make sure this is pointing at the correct file so they are placed in your final mask at the appropriate locations.
[45]:
full_chip_gds.options
[45]:
{'short_segments_to_not_fillet': 'True',
'check_short_segments_by_scaling_fillet': '2.0',
'gds_unit': 0.001,
'ground_plane': 'True',
'negative_mask': {'main': []},
'corners': 'circular bend',
'tolerance': '0.00001',
'precision': '0.000000001',
'width_LineString': '10um',
'path_filename': '../resources/Fake_Junctions.GDS',
'junction_pad_overlap': '5um',
'max_points': '199',
'cheese': {'datatype': '100',
'shape': '0',
'cheese_0_x': '25um',
'cheese_0_y': '25um',
'cheese_1_radius': '100um',
'view_in_file': {'main': {1: True}},
'delta_x': '100um',
'delta_y': '100um',
'edge_nocheese': '200um'},
'no_cheese': {'datatype': '99',
'buffer': '25um',
'cap_style': '2',
'join_style': '2',
'view_in_file': {'main': {1: True}}},
'bounding_box_scale_x': '1.2',
'bounding_box_scale_y': '1.2'}
[46]:
full_chip_gds.options['path_filename'] ='../resources/Fake_Junctions.GDS'
full_chip_gds.options['no_cheese']['buffer']='50um'
[47]:
full_chip_gds.export_to_gds('Full_Chip_01.gds')
[47]:
1
(optional) With the design complete, we can close the GUI.
[48]:
# gui.main_window.close()
For more information, review the Introduction to Quantum Computing and Quantum Hardware lectures below
|
Lecture Video | Lecture Notes | Lab |
|
Lecture Video | Lecture Notes | Lab |
|
Lecture Video | Lecture Notes | Lab |
|
Lecture Video | Lecture Notes | Lab |
|
Lecture Video | Lecture Notes | Lab |
|
Lecture Video | Lecture Notes | Lab |