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
[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()
10:39PM 41s 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.
10:39PM 41s 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.
10:39PM 42s 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.
10:39PM 42s 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]:
<Figure size 800x800 with 2 Axes>

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]:
<Figure size 800x800 with 2 Axes>
[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()
10:39PM 42s 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.
10:39PM 42s 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]:
<Figure size 800x800 with 2 Axes>

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]:
<Figure size 800x800 with 2 Axes>

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]:
<Figure size 800x800 with 2 Axes>
[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]:
<Figure size 800x800 with 2 Axes>
[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]:
<Figure size 800x800 with 2 Axes>
[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]:
<Figure size 800x800 with 2 Axes>

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()
10:39PM 44s WARNING [connect_meandered]: cpw_6: reduced meander_number from 3.0 to 1.0 so each wiggle has room for the 0.09mm fillet (length_perp=0.035mm). The requested meander.spacing packs more wiggles into this route than the available length_excess can support without producing sharp, unfileted kinks. Increase total_length, increase meander.spacing, or decrease fillet to avoid this adjustment.
10:39PM 44s WARNING [connect_meandered]: cpw_6: even at the minimum meander_number=1.0, length_perp=0.035mm is still smaller than fillet=0.09mm -- this route's meander cannot be cleanly filleted with the current total_length / spacing / fillet combination and will still show sharp kinks.
10:39PM 44s WARNING [connect_meandered]: cpw_6: reduced meander_number from 3.0 to 1.0 so each wiggle has room for the 0.09mm fillet (length_perp=0.035mm). The requested meander.spacing packs more wiggles into this route than the available length_excess can support without producing sharp, unfileted kinks. Increase total_length, increase meander.spacing, or decrease fillet to avoid this adjustment.
10:39PM 44s WARNING [connect_meandered]: cpw_6: even at the minimum meander_number=1.0, length_perp=0.035mm is still smaller than fillet=0.09mm -- this route's meander cannot be cleanly filleted with the current total_length / spacing / fillet combination and will still show sharp kinks.
[19]:
<Figure size 800x800 with 2 Axes>
[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()
10:39PM 44s WARNING [connect_meandered]: cpw_6: reduced meander_number from 3.0 to 1.0 so each wiggle has room for the 0.09mm fillet (length_perp=0.035mm). The requested meander.spacing packs more wiggles into this route than the available length_excess can support without producing sharp, unfileted kinks. Increase total_length, increase meander.spacing, or decrease fillet to avoid this adjustment.
10:39PM 44s WARNING [connect_meandered]: cpw_6: even at the minimum meander_number=1.0, length_perp=0.035mm is still smaller than fillet=0.09mm -- this route's meander cannot be cleanly filleted with the current total_length / spacing / fillet combination and will still show sharp kinks.
[20]:
<Figure size 800x800 with 2 Axes>
[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()
10:39PM 45s WARNING [connect_meandered]: cpw_6: reduced meander_number from 3.0 to 1.0 so each wiggle has room for the 0.09mm fillet (length_perp=0.035mm). The requested meander.spacing packs more wiggles into this route than the available length_excess can support without producing sharp, unfileted kinks. Increase total_length, increase meander.spacing, or decrease fillet to avoid this adjustment.
10:39PM 45s WARNING [connect_meandered]: cpw_6: even at the minimum meander_number=1.0, length_perp=0.035mm is still smaller than fillet=0.09mm -- this route's meander cannot be cleanly filleted with the current total_length / spacing / fillet combination and will still show sharp kinks.
[21]:
<Figure size 800x800 with 2 Axes>
[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