{ "cells": [ { "cell_type": "markdown", "id": "15674248", "metadata": {}, "source": [ "## Basic use of the package" ] }, { "cell_type": "markdown", "id": "356fa57f", "metadata": {}, "source": [ "QuLTRA is an open-source Python library for the analysis of superconducting circuits that include both lumped elements (capacitors, inductors, Josephson junctions, resistors) and distributed components (such as coplanar waveguides and CPW couplers).\n", "\n", "The library provides tools to compute:\n", "\n", "1) Eigenfrequencies of the circuit modes,\n", "\n", "2) Dissipation rates, including coupling to external lines,\n", "\n", "3) The cross-Kerr matrix, describing the nonlinear interactions between modes.\n", "\n", "QuLTRA is designed to support fast, layout-independent modeling in the early design stages, before full electromagnetic simulations." ] }, { "cell_type": "markdown", "id": "ff62b590", "metadata": {}, "source": [ "To create the circuit, we need to instantiate an object of the QCircuit class.\n", "We must provide:\n", "\n", "1) a list of components that define the circuit topology,\n", "\n", "2) the minimum and maximum frequencies expressed in GHz over which the circuit will be analyzed.\n", "\n", "For lumped components (C, L, J, R), we need to provide:\n", "\n", "1) the positive and negative nodes the component connects to,\n", "\n", "2) the value of the component (in SI units).\n", "\n", "It is also possible to simulate an array of Josephson junction by simply instantiating a J component and passing the number of junctions in the array as the fourth argument.\n", "\n", "For a CPW component, we need to provide:\n", "\n", "1) the negative and positive nodes it connects to,\n", "\n", "2) its length (in meters),\n", "\n", "3) and optionally its characteristic impedance (in Ohms).\n", "\n", "By default, the impedance is set to 50 Ω if not specified. It is assumed that the CPWs are placed on a substrate with a dielectric constant of 11.9, which corresponds to the dielectric constant that ANSYS uses for silicon. If a different dielectric constant is desired, it can be manually modified in the constants.py file.\n", "\n", "**Note**: Node 0 is considered the ground node\n", "\n", "For instance, in the case of a qubit coupled to a $\\lambda/4$ resonator, we can write:\n" ] }, { "cell_type": "code", "execution_count": 1, "id": "3d4330f4", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import qultra as qu\n", "\n", "\n", "Cj=90e-15 #qubit capacitance\n", "Lj=8e-9 #qubit junction\n", "Cg=5e-15 #coupling capacitance\n", "l=4.5e-3 #cpw length\n", "\n", "f_min=3 #minimum frequency [GHz]\n", "f_max=12 #maximum frequency [GHz]\n", "\n", "net=[qu.C(0,1,Cj),qu.J(0,1,Lj,1),qu.C(1,2,Cg),qu.CPW(0,2,l)]\n", "\n", "circuit=qu.QCircuit(net,f_min,f_max)\n" ] }, { "cell_type": "markdown", "id": "21ecf94e", "metadata": {}, "source": [ "# Mode frequencies\n", "The mode frequencies together with the dissipation rates are extracted by calculating the zeros of the admittance matrix determinant defined as $\\frac{2\\pi \\kappa}{2}+j2\\pi f$.\n", "It is possible to retrieve the mode frequencies (in GHz) as a list—using the mode_frequencies() method—for further processing or numerical calculations,\n", "or simply use the show_modes() method to print them in a nicely formatted table.\n", "\n", "The show_modes() method also plots the dissipation rates $\\kappa$ for each mode.\n", "Since the circuit contains no dissipative elements, the κ values will be zero, and no quality factor (Q) is defined." ] }, { "cell_type": "code", "execution_count": null, "id": "fc277bf0", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Mode Frequencies (GHz): [5.765693573044772, 6.529970034428903]\n", "+------+------------+----------+\n", "| Mode | Freq [GHz] | k [MHz] |\n", "+------+------------+----------+\n", "| 1 | 5.77e+00 | 0.00e+00 |\n", "| 2 | 6.53e+00 | 0.00e+00 |\n", "+------+------------+----------+\n" ] } ], "source": [ "frequencies = circuit.mode_frequencies()\n", "print(\"Mode Frequencies (GHz):\", frequencies)\n", "\n", "circuit.show_modes()" ] }, { "cell_type": "markdown", "id": "ca61d09a", "metadata": {}, "source": [ "# Cross-Kerr matrix\n", "Since the circuit contains a Josephson junction component, we can also compute the cross-Kerr matrix (expressed in MHz), which describes the nonlinear interactions between the modes.\n", "\n", "As with the mode frequencies, the cross-Kerr matrix can either be retrieved as a matrix using the run_epr() method, for further analysis, or visualized directly using the show_chi() method, which plots the matrix in a clear and readable format." ] }, { "cell_type": "code", "execution_count": 3, "id": "6461375c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[[1.98809413e+02 5.07443676e+00]\n", " [5.07443676e+00 3.23801424e-02]]\n", "Chi matrix [MHz]:\n", "+------+----------+----------+\n", "| Mode | 1 | 2 |\n", "+------+----------+----------+\n", "| 1 | 1.99e+02 | 5.07e+00 |\n", "| 2 | 5.07e+00 | 3.24e-02 |\n", "+------+----------+----------+\n" ] } ], "source": [ "cross_kerr_matrix=circuit.run_epr()\n", "print(cross_kerr_matrix)\n", "circuit.show_chi()" ] }, { "cell_type": "markdown", "id": "7d868d6c", "metadata": {}, "source": [ "If we're only interested in visualizing all the key results—including mode frequencies and the cross-Kerr matrix—we can simply call the show_all() method.\n", "\n", "This will automatically display:\n", "\n", "1) the table of mode frequencies,\n", "\n", "2) the dissipation rates (κ),\n", "\n", "3) and the cross-Kerr matrix (χ) in a compact and readable format." ] }, { "cell_type": "code", "execution_count": 13, "id": "93681f9c", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+------+------------+----------+\n", "| Mode | Freq [GHz] | k [MHz] |\n", "+------+------------+----------+\n", "| 1 | 5.77e+00 | 0.00e+00 |\n", "| 2 | 6.53e+00 | 0.00e+00 |\n", "+------+------------+----------+\n", "Chi matrix [MHz]:\n", "+------+----------+----------+\n", "| Mode | 1 | 2 |\n", "+------+----------+----------+\n", "| 1 | 1.99e+02 | 5.07e+00 |\n", "| 2 | 5.07e+00 | 3.24e-02 |\n", "+------+----------+----------+\n" ] } ], "source": [ "circuit.show_all()" ] }, { "cell_type": "markdown", "id": "ca29aea2", "metadata": {}, "source": [ "# Dissipation rate\n", "Typically, quantum circuits are coupled to feedlines terminated with 50 Ω resistors.\n", "This coupling can be either:\n", "\n", "1) Capacitive, by using a lumped capacitor that connects the resonator to the feedline\n", "\n", "2) Primarily inductive, by using CPW couplers.\n", "\n", "QuLTRA allows modeling both types of coupling.\n", "For capacitive coupling, simply add a C component between the resonator node and a 50 Ω resistor (representing the feedline termination).\n", "For CPW coupling, you can instantiate a CPW_coupler component.\n", "This requires:\n", "\n", "1) a list of the 4 nodes the coupler is connected to,\n", "\n", "2) a list of gap widths (in micrometers),\n", "\n", "3) a list of CPW widths involved in the coupling (in micrometers),\n", "\n", "4) the length of the coupler (in meters).\n", "\n", "Two of the coupler’s terminals are then connected to 50 Ω resistors to model the feedline.\n", "\n", "The second case is shown below:\n", "\n" ] }, { "cell_type": "code", "execution_count": 2, "id": "6e5674d8", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+------+------------+-----------+-----------+\n", "| Mode | Freq [GHz] | k [MHz] | Q |\n", "+------+------------+-----------+-----------+\n", "| 1 | 5.77e+00 | -1.37e-02 | -4.22e+05 |\n", "| 2 | 6.49e+00 | -1.55e+00 | -4.18e+03 |\n", "+------+------------+-----------+-----------+\n", "Chi matrix [MHz]:\n", "+------+----------+----------+\n", "| Mode | 1 | 2 |\n", "+------+----------+----------+\n", "| 1 | 1.98e+02 | 5.51e+00 |\n", "| 2 | 5.51e+00 | 3.83e-02 |\n", "+------+----------+----------+\n" ] } ], "source": [ "l_coupler=0.7e-3 #coupler length\n", "coupler_nodes=[3,0,4,5] #coupler nodes\n", "gap=[10,10,10,10] #coupler gaps\n", "width=[15,10,15] #coupler widths\n", "\n", "net1=[qu.C(0,1,Cj),qu.J(0,1,Lj),qu.C(1,2,Cg),qu.CPW(3,2,l-l_coupler),qu.CPW_coupler(coupler_nodes,gap,width,l_coupler),qu.R(0,4,50),qu.R(0,5,50)]\n", "\n", "circuit_with_loss=qu.QCircuit(net1,f_min,f_max)\n", "\n", "circuit_with_loss.show_all()" ] }, { "cell_type": "markdown", "id": "01322e38", "metadata": {}, "source": [ "As shown in the results, in this case the presence of dissipative components leads to a non-zero coupling rate (κ) and therefore to a finite quality factor (Q).\n", "\n", "**Note**: When using a CPW_coupler, the length of the CPW section representing the λ/4 resonator must be adjusted by subtracting the length of the coupler. This ensures the total electrical length remains accurate." ] }, { "cell_type": "markdown", "id": "94bb6cfd", "metadata": {}, "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.9" } }, "nbformat": 4, "nbformat_minor": 5 }