Note

This page was generated from tut/2-From-components-to-chip/2.12-Simple-Meander.ipynb.

2.12 Simple Meander

Open in Colab Binder

💡 Running in Colab or Binder? Skip the desktop GUI install — the cell below grabs the lite (no-Qt) wheel, and qm.gui(design) auto-picks an inline matplotlib viewer with the same API (gui.rebuild(), gui.screenshot(), gui.edit_component(...)) as the desktop MetalGUI.

[1]:
# In Colab / Binder, uncomment to install Quantum Metal (lite, no Qt).
# Locally you should already have it via `pip install quantum-metal` or
# `pip install 'quantum-metal[gui]'` for the desktop GUI.
# !pip install -q quantum-metal

💡 Using this tutorial without the Qt GUI

This tutorial uses the desktop MetalGUI. To follow along on Colab, Binder, JupyterHub, or any environment where Qt isn’t available, replace any ``gui.rebuild()`` / ``gui.screenshot()`` call with ``qm.view(design)`` — it renders the design to a matplotlib Figure you can display inline or save with fig.savefig(...).

See 1.1 Quick start for a complete runnable walkthrough and `docs/headless-usage.rst <../../docs/headless-usage.rst>`__ for the full reference.

Creates 3 transmon pockets, connected in different ways by the mean of transmission lines.

These transmission line QComponents create basic meanders to accommodate the user-defined line length.

Preparations

Import key libraries and open the Metal GUI. Also we configure the notebook to enable overwriting of existing components

[2]:
import qiskit_metal as qm
from qiskit_metal import designs
from qiskit_metal import Dict

design = designs.DesignPlanar()
gui = qm.gui(design)

# if you disable the next line, then you will need to delete a component [<component>.delete()] before recreating it
design.overwrite_enabled = True
Quantum Metal — headless viewer active. Rendering inline via qm.view(design); gui.rebuild(), gui.screenshot(), gui.edit_component(...) work as in the desktop GUI.
For the full desktop experience (Qt window, dockable panels): pip install 'quantum-metal[gui]' and re-import.
[3]:
from qiskit_metal.qlibrary.core import QRouteLead

Create 3 Transmon Qbits with 4 pins. This uses the same definition (options) for all 3 Qbits, but it places them in 3 different (x,y) origin points.

[4]:
from qiskit_metal.qlibrary.qubits.transmon_pocket import TransmonPocket

optionsQ = dict(
    pad_width="425 um",
    pocket_height="650um",
    connection_pads=dict(  # Qbits defined to have 4 pins
        a=dict(loc_W=+1, loc_H=+1),
        b=dict(loc_W=-1, loc_H=+1, pad_height="30um"),
        c=dict(loc_W=+1, loc_H=-1, pad_width="200um"),
        d=dict(loc_W=-1, loc_H=-1, pad_height="50um"),
    ),
)

q1 = TransmonPocket(
    design, "Q1", options=dict(pos_x="-1.5mm", pos_y="+0.0mm", **optionsQ)
)
q2 = TransmonPocket(
    design,
    "Q2",
    options=dict(pos_x="+0.35mm", pos_y="+1.0mm", orientation="90", **optionsQ),
)
q3 = TransmonPocket(
    design, "Q3", options=dict(pos_x="2.0mm", pos_y="+0.0mm", **optionsQ)
)

gui.rebuild()
gui.autoscale()
gui.highlight_components(
    ["Q1", "Q2", "Q3"]
)  # This is to show the pins, so we can choose what to connect

gui.screenshot()
../../_images/tut_2-From-components-to-chip_2.12-Simple-Meander_10_0.png

Using CPW meanders to connect the 3 Qbits

Import the RouteMeander and inspect what options are available for you to initialize

[5]:
from qiskit_metal.qlibrary.tlines.meandered import RouteMeander

RouteMeander.get_template_options(design)
[5]:
{'chip': 'main',
 'layer': '1',
 'pin_inputs': {'start_pin': {'component': '', 'pin': ''},
  'end_pin': {'component': '', 'pin': ''}},
 'fillet': '0',
 'lead': {'start_straight': '0mm',
  'end_straight': '0mm',
  'start_jogged_extension': '',
  'end_jogged_extension': ''},
 'total_length': '7mm',
 'trace_width': 'cpw_width',
 'meander': {'spacing': '200um', 'asymmetry': '0um'},
 'snap': 'true',
 'prevent_short_edges': 'true',
 'hfss_wire_bonds': False,
 'q3d_wire_bonds': False,
 'aedt_q3d_wire_bonds': False,
 'aedt_hfss_wire_bonds': False}

Let’s define a dictionary with the options we want to keep global. We will then concatenate this dictionary to the ones we will use to describe the individual Qbits

[6]:
ops = dict(fillet="90um")

Let’s define the first CPW QComponent.

[7]:
options = Dict(
    total_length="8mm",
    hfss_wire_bonds=True,
    pin_inputs=Dict(
        start_pin=Dict(component="Q1", pin="a"), end_pin=Dict(component="Q2", pin="b")
    ),
    lead=Dict(start_straight="0mm", end_straight="0.5mm"),
    meander=Dict(asymmetry="-1mm"),
    **ops,
)

# Below I am creating a CPW without assigning its name.
#  Therefore running this cell twice will create two CPW's instead of overwriting the previous one
#  To prevent that we add the cpw.delete() statement.
#  The try-except wrapping is needed to suppress errors during the first run of this cell
try:
    cpw.delete()
except NameError:
    pass

cpw = RouteMeander(design, options=options)
gui.rebuild()
gui.autoscale()
07:22PM 10s WARNING [check_lengths]: For path table, component=cpw_1, key=trace has short segments that could cause issues with fillet. Values in (1-1)  are index(es) in shapely geometry.
07:22PM 10s WARNING [check_lengths]: For path table, component=cpw_1, key=cut has short segments that could cause issues with fillet. Values in (1-1)  are index(es) in shapely geometry.
07:22PM 10s WARNING [check_lengths]: For path table, component=cpw_1, key=trace has short segments that could cause issues with fillet. Values in (1-1)  are index(es) in shapely geometry.
07:22PM 10s WARNING [check_lengths]: For path table, component=cpw_1, key=cut has short segments that could cause issues with fillet. Values in (1-1)  are index(es) in shapely geometry.
[7]:
../../_images/tut_2-From-components-to-chip_2.12-Simple-Meander_17_1.png

You might have received an expected python “warning - check_lengths” message. This indicates that one of the CPW edges is too short to accommodate the fillet corner rounding previous defined at 90um. Also, the CPW “start lead” does not offer enough clearance from the Qbit, causing a short between two pins.

Please take a minute to observe this behavior in the GUI

[8]:
gui.screenshot()
../../_images/tut_2-From-components-to-chip_2.12-Simple-Meander_19_0.png

You can inspect the points forming the CPW route to find the culprit edge (the warning message should have indicated the index of the offending edge)

[9]:
cpw.get_points()
[9]:
array([[-1.075     ,  0.195     ],
       [-1.07      ,  0.195     ],
       [-1.07      , -0.44916667],
       [-0.87      , -0.44916667],
       [-0.87      , -1.29421683],
       [-0.67      , -1.29421683],
       [-0.67      , -0.31578317],
       [-0.47      , -0.31578317],
       [-0.47      , -1.29421683],
       [-0.27      , -1.29421683],
       [-0.27      , -0.31578317],
       [-0.07      , -0.31578317],
       [-0.07      , -1.29421683],
       [ 0.155     , -1.29421683],
       [ 0.155     ,  0.575     ]])

Turns out that both issues can be resolved by just adding enough clearance at the start of the CPW.

[10]:
cpw.options["lead"]["start_straight"] = "100um"
gui.rebuild()
gui.autoscale()
[10]:
../../_images/tut_2-From-components-to-chip_2.12-Simple-Meander_23_0.png
[11]:
gui.screenshot()
../../_images/tut_2-From-components-to-chip_2.12-Simple-Meander_24_0.png

Notice how the routing algorithm tries to prevent creation of edges too short to apply the fillet corner rounding. If your design requires it, you can disable this algorithm behavior for individual CPWs. For example try the cell below, and expect warning similar to the ones encountered earlier to show up

[12]:
cpw.options["prevent_short_edges"] = "false"
gui.rebuild()
gui.autoscale()
07:22PM 10s WARNING [check_lengths]: For path table, component=cpw_1, key=trace has short segments that could cause issues with fillet. Values in (12-13)  are index(es) in shapely geometry.
07:22PM 10s WARNING [check_lengths]: For path table, component=cpw_1, key=cut has short segments that could cause issues with fillet. Values in (12-13)  are index(es) in shapely geometry.
[12]:
../../_images/tut_2-From-components-to-chip_2.12-Simple-Meander_26_1.png

You can eliminate the warning by either re-enabling the algorithm, or by changing the fillet for this specific CPW. Let’s try the second approach for demonstration purposes

[13]:
cpw.options["fillet"] = "65um"
gui.rebuild()
gui.autoscale()
[13]:
../../_images/tut_2-From-components-to-chip_2.12-Simple-Meander_28_0.png

Now let’s create other 3 CPWs for practice

[14]:
options = Dict(
    total_length="6mm",
    pin_inputs=Dict(
        start_pin=Dict(component="Q2", pin="d"), end_pin=Dict(component="Q3", pin="b")
    ),
    lead=Dict(start_straight="0.1mm", end_straight="0.2mm"),
    meander=Dict(asymmetry="-0.9mm"),
    **ops,
)

try:
    cpw2.delete()
except NameError:
    pass

cpw2 = RouteMeander(design, options=options)
gui.rebuild()
gui.autoscale()
[14]:
../../_images/tut_2-From-components-to-chip_2.12-Simple-Meander_30_0.png
[15]:
options = Dict(
    total_length="8mm",
    pin_inputs=Dict(
        start_pin=Dict(component="Q3", pin="a"), end_pin=Dict(component="Q2", pin="c")
    ),
    lead=Dict(start_straight="0.5mm", end_straight="0.1mm"),
    meander=Dict(asymmetry="-1mm"),
    **ops,
)

try:
    cpw3.delete()
except NameError:
    pass

cpw3 = RouteMeander(design, options=options)
gui.rebuild()
gui.autoscale()
[15]:
../../_images/tut_2-From-components-to-chip_2.12-Simple-Meander_31_0.png
[16]:
options = Dict(
    total_length="8mm",
    pin_inputs=Dict(
        start_pin=Dict(component="Q1", pin="b"), end_pin=Dict(component="Q2", pin="a")
    ),
    lead=Dict(start_straight="0.5mm", end_straight="0.1mm"),
    meander=Dict(asymmetry="1mm"),
    **ops,
)

try:
    cpw4.delete()
except NameError:
    pass

cpw4 = RouteMeander(design, options=options)
gui.rebuild()
gui.autoscale()
[16]:
../../_images/tut_2-From-components-to-chip_2.12-Simple-Meander_32_0.png
[17]:
gui.screenshot()
../../_images/tut_2-From-components-to-chip_2.12-Simple-Meander_33_0.png

Let’s try a more complex utilization of the leads. So far we have demonstrated lead->start_straight and lead->end_straight. We can “append” to the straight lead any number of custom jogs, which might be useful to get out of complex layout arrangements or to fine tune the meander in case of collisions with other components.

To define a jogged lead, you need an ordered sequence of turn-length pairs, which we define here as an ordered dictionary. We then apply the sequence of jogs to both the start and end leads (or you could apply it to only one them, or you can define the two leads separately with two ordered dictionaries)

[18]:
from collections import OrderedDict

jogs = OrderedDict()
jogs[0] = ["L", "800um"]
jogs[1] = ["L", "500um"]
jogs[2] = ["R", "200um"]
jogs[3] = ["R", "500um"]

options = Dict(
    total_length="14mm",
    pin_inputs=Dict(
        start_pin=Dict(component="Q1", pin="d"), end_pin=Dict(component="Q3", pin="d")
    ),
    lead=Dict(
        start_straight="0.1mm",
        end_straight="0.1mm",
        start_jogged_extension=jogs,
        end_jogged_extension=jogs,
    ),
    meander=Dict(asymmetry="-1.2mm"),
    **ops,
)

try:
    cpw5.delete()
except NameError:
    pass

cpw5 = RouteMeander(design, options=options)
gui.rebuild()
gui.autoscale()
[18]:
../../_images/tut_2-From-components-to-chip_2.12-Simple-Meander_35_0.png

Here a few additional examples routing flexibility on a brand-new set of Qbits

[19]:
q4 = TransmonPocket(
    design, "Q4", options=dict(pos_x="-7.5mm", pos_y="-0.5mm", **optionsQ)
)
q5 = TransmonPocket(
    design,
    "Q5",
    options=dict(pos_x="-5.65mm", pos_y="+0.5mm", orientation="90", **optionsQ),
)
q6 = TransmonPocket(
    design, "Q6", options=dict(pos_x="-4.0mm", pos_y="-0.6mm", **optionsQ)
)
gui.rebuild()

options = Dict(
    total_length="3.4mm",
    pin_inputs=Dict(
        start_pin=Dict(component="Q4", pin="a"), end_pin=Dict(component="Q5", pin="b")
    ),
    lead=Dict(start_straight="0.5mm", end_straight="0.1mm"),
    meander=Dict(asymmetry="1mm"),
    **ops,
)
try:
    cpw6.delete()
except NameError:
    pass
cpw6 = RouteMeander(design, options=options)
gui.rebuild()
gui.autoscale()
[19]:
../../_images/tut_2-From-components-to-chip_2.12-Simple-Meander_37_0.png
[20]:
options = Dict(
    total_length="12mm",
    pin_inputs=Dict(
        start_pin=Dict(component="Q4", pin="d"), end_pin=Dict(component="Q6", pin="c")
    ),
    lead=Dict(start_straight="0.1mm", end_straight="0.1mm"),
    meander=Dict(asymmetry="-1.2mm"),
    **ops,
)
try:
    cpw7.delete()
except NameError:
    pass
cpw7 = RouteMeander(design, options=options)
gui.rebuild()
gui.autoscale()
[20]:
../../_images/tut_2-From-components-to-chip_2.12-Simple-Meander_38_0.png
[21]:
options = Dict(
    total_length="13mm",
    pin_inputs=Dict(
        start_pin=Dict(component="Q6", pin="a"), end_pin=Dict(component="Q4", pin="b")
    ),
    lead=Dict(start_straight="0.1mm", end_straight="0.1mm"),
    meander=Dict(asymmetry="-1.7mm"),
    **ops,
)
try:
    cpw8.delete()
except NameError:
    pass
cpw8 = RouteMeander(design, options=options)
gui.rebuild()
gui.autoscale()
[21]:
../../_images/tut_2-From-components-to-chip_2.12-Simple-Meander_39_0.png
[22]:
gui.screenshot()
../../_images/tut_2-From-components-to-chip_2.12-Simple-Meander_40_0.png
[23]:
# If you would like to close the GUI. Remove the comment.
# gui.main_window.close()


For more information, review the Introduction to Quantum Computing and Quantum Hardware lectures below

  • Superconducting Qubits I: Quantizing a Harmonic Oscillator, Josephson Junctions Part 1
Lecture Video Lecture Notes Lab
  • Superconducting Qubits I: Quantizing a Harmonic Oscillator, Josephson Junctions Part 2
Lecture Video Lecture Notes Lab
  • Superconducting Qubits I: Quantizing a Harmonic Oscillator, Josephson Junctions Part 3
Lecture Video Lecture Notes Lab
  • Superconducting Qubits II: Circuit Quantum Electrodynamics, Readout and Calibration Methods Part 1
Lecture Video Lecture Notes Lab
  • Superconducting Qubits II: Circuit Quantum Electrodynamics, Readout and Calibration Methods Part 2
Lecture Video Lecture Notes Lab
  • Superconducting Qubits II: Circuit Quantum Electrodynamics, Readout and Calibration Methods Part 3
Lecture Video Lecture Notes Lab