Source code for qiskit_metal.qlibrary.resonators.resonator_lumped

# -*- coding: utf-8 -*-
# This code is part of Qiskit.
#
# (C) Copyright IBM 2017, 2021.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
"""Lumped Resonator, as shown in Phys. Rev. Appl. 10, 034050 (2018)."""

from math import sin, cos
import numpy as np
from qiskit_metal import draw, Dict
from qiskit_metal.qlibrary.core import QComponent


[docs] class ResonatorLumped(QComponent): """ The base ResonatorLumped class Inherits the QComponent class .. TODO: add resonator_lumped.png once asset is available for docs .. meta:: :description: Lumped Resonator Default Options: * pos_x: '0um' -- x-coordinate of the bottom center of the resonator * pos_y: '0um' -- y-coordinate of the bottom center of the resonator * orientation: '0' -- angle of rotation of the resonator * box_width: '5mm' -- the width of the rectangular resonator structure * box_height: '5mm' -- the height of the rectangular resonator structure * perimeter_thicknes: '0.01mm' -- the width of the resonator along the perimeter * res_width: '0.01m' -- the width of the resonator * initial: '0.1m' -- the length of the lower straight resonator segment * n_turns: '10' -- the number of turns in the curved resonator segment * turn_radius: '0.1mm' - the radius of the turns in the curved resonator segment * inner_space: '0.1mm' - the space between the curved resonator * outer_space: '0.1mm' -- the space between rectangular and curved resonator turns * final: '2.5mm' -- the length of the upper straight segment of the resonator * break_width: '0.2mm' -- the width of the "break" in the top of the rectangular resonator * layer: '1' -- the layer of the component """ default_options = Dict( pos_x="0 um", pos_y="0 um", orientation="0", box_width="5mm", box_height="5mm", perimeter_thickness="0.01mm", res_width="0.01mm", initial="0.1mm", n_turns="10", turn_radius="0.1mm", inner_space="0.1mm", outer_space="0.1mm", final="2.5mm", break_width="0.2mm", layer="1", ) ##########################
[docs] def make(self): """Builds the component.""" """Convert self.options into QGeometry.""" p = self.parse_options() # Parse the string options into numbers # draw the perimeter box_out = draw.rectangle(p.box_width, p.box_height, 0.0, 0.0) box_in = draw.rectangle( p.box_width - 2.0 * p.perimeter_thickness, p.box_height - 2.0 * p.perimeter_thickness, 0.0, 0.0, ) perimeter = draw.subtract(box_out, box_in) perimeter = draw.translate(perimeter, xoff=0.0, yoff=0.5 * p.box_height) break_rect = draw.rectangle(p.break_width, p.break_width, 0.0, p.box_height) perimeter = draw.subtract(perimeter, break_rect) # start the resonator initial = draw.LineString( [(0.0, p.perimeter_thickness), (0.0, p.perimeter_thickness + p.initial)] ) # Draw the first quarter turn centerx, centery = -1.0 * p.turn_radius, p.perimeter_thickness + p.initial radius = p.turn_radius start_angle, end_angle = 0, 90 # In degrees numsegments = 1000 # The coordinates of the arc theta = np.radians(np.linspace(start_angle, end_angle, numsegments)) x = centerx + radius * np.cos(theta) y = centery + radius * np.sin(theta) arc = draw.LineString(np.column_stack([x, y])) # Draw the first half-turn (left); this gets repeated centerx2 = -0.5 * p.box_width + p.outer_space + p.turn_radius centery2 = p.perimeter_thickness + p.initial + 2.0 * p.turn_radius radius2 = p.turn_radius start_angle2, end_angle2 = 270, 90 # In degrees numsegments2 = 1000 # The coordinates of the arc theta2 = np.radians(np.linspace(start_angle2, end_angle2, numsegments2)) x2 = centerx2 + radius2 * np.cos(theta2) y2 = centery2 + radius2 * np.sin(theta2) arc_left_1 = draw.LineString(np.column_stack([x2, y2])) # Draw the first half-turn (right); this gets repeated centerx3 = 0.5 * p.box_width - p.outer_space - p.turn_radius centery3 = p.perimeter_thickness + p.initial + 4.0 * p.turn_radius radius3 = p.turn_radius start_angle3, end_angle3 = 90, -90 # In degrees numsegments3 = 1000 # The coordinates of the arc theta3 = np.radians(np.linspace(start_angle3, end_angle3, numsegments3)) x3 = centerx3 + radius3 * np.cos(theta3) y3 = centery3 + radius3 * np.sin(theta3) arc_right_1 = draw.LineString(np.column_stack([x3, y3])) # bottom half-line line1 = draw.LineString( [ ( -1.0 * p.turn_radius - 0.0 * p.res_width, p.perimeter_thickness + p.initial + p.turn_radius, ), ( -0.5 * p.box_width + p.outer_space + p.turn_radius, p.perimeter_thickness + p.initial + p.turn_radius, ), ] ) # bottom full-line (this one gets repeated) line2 = draw.LineString( [ ( -0.5 * p.box_width + p.outer_space + p.turn_radius, p.initial + 3.0 * p.turn_radius + p.res_width, ), ( 0.5 * p.box_width - p.outer_space - p.turn_radius, p.initial + 3.0 * p.turn_radius + p.res_width, ), ] ) # repeat the full fline line3 = draw.translate(line2, 0.0, 2.0 * p.turn_radius) line4 = draw.translate(line3, 0.0, 2.0 * p.turn_radius) line5 = draw.translate(line4, 0.0, 2.0 * p.turn_radius) line6 = draw.translate(line5, 0.0, 2.0 * p.turn_radius) line7 = draw.translate(line6, 0.0, 2.0 * p.turn_radius) line8 = draw.translate(line7, 0.0, 2.0 * p.turn_radius) line9 = draw.translate(line8, 0.0, 2.0 * p.turn_radius) line10 = draw.translate(line9, 0.0, 2.0 * p.turn_radius) line11 = draw.translate(line10, 0.0, 2.0 * p.turn_radius) line12 = draw.translate(line11, 0.0, 2.0 * p.turn_radius) line13 = draw.translate(line12, 0.0, 2.0 * p.turn_radius) line14 = draw.translate(line13, 0.0, 2.0 * p.turn_radius) # hard code the position for now; make it adjustable later line_last = draw.translate( line1, 0.5 * p.box_width - 0.0 * p.turn_radius - p.outer_space, 28 * p.turn_radius, ) # draw the line exiting the rectangle final = draw.LineString( [ (0.0, p.perimeter_thickness + p.initial + 30.0 * p.turn_radius), ( 0.0, p.perimeter_thickness + p.initial + 30.0 * p.turn_radius + p.final, ), ] ) arc_last = draw.rotate( arc, 180, origin=(0.0, p.perimeter_thickness + p.initial + 1.5 * p.turn_radius), ) arc_last = draw.translate(arc_last, 0.0, p.initial + 26 * p.turn_radius) # repeat the left turns arc_left_2 = draw.translate(arc_left_1, 0.0, 4.0 * p.turn_radius) arc_left_3 = draw.translate(arc_left_2, 0.0, 4.0 * p.turn_radius) arc_left_4 = draw.translate(arc_left_3, 0.0, 4.0 * p.turn_radius) arc_left_5 = draw.translate(arc_left_4, 0.0, 4.0 * p.turn_radius) arc_left_6 = draw.translate(arc_left_5, 0.0, 4.0 * p.turn_radius) arc_left_7 = draw.translate(arc_left_6, 0.0, 4.0 * p.turn_radius) # repeat the right turns arc_right_2 = draw.translate(arc_right_1, 0.0, 4.0 * p.turn_radius) arc_right_3 = draw.translate(arc_right_2, 0.0, 4.0 * p.turn_radius) arc_right_4 = draw.translate(arc_right_3, 0.0, 4.0 * p.turn_radius) arc_right_5 = draw.translate(arc_right_4, 0.0, 4.0 * p.turn_radius) arc_right_6 = draw.translate(arc_right_5, 0.0, 4.0 * p.turn_radius) arc_right_7 = draw.translate(arc_right_6, 0.0, 4.0 * p.turn_radius) # Translate and rotate all shapes objects = [ perimeter, initial, arc, arc_left_1, arc_left_2, arc_left_3, arc_left_4, arc_left_5, arc_left_6, arc_left_7, arc_right_1, arc_right_2, arc_right_2, arc_right_3, arc_right_4, arc_right_4, arc_right_5, arc_right_6, arc_right_7, arc_last, final, line1, line2, line3, line4, line5, line6, line7, line8, line9, line10, line11, line12, line13, line14, line_last, ] # first translate so that the origin is at the middle of the loop objects = draw.translate(objects, 0.0, -0.5 * p.box_height) # now translate and rotate according to the values specified in the dictionary objects = draw.rotate(objects, p.orientation, origin=(0, 0)) objects = draw.translate(objects, xoff=p.pos_x, yoff=p.pos_y) [ perimeter, initial, arc, arc_left_1, arc_left_2, arc_left_3, arc_left_4, arc_left_5, arc_left_6, arc_left_7, arc_right_1, arc_right_2, arc_right_2, arc_right_3, arc_right_4, arc_right_4, arc_right_5, arc_right_6, arc_right_7, arc_last, final, line1, line2, line3, line4, line5, line6, line7, line8, line9, line10, line11, line12, line13, line14, line_last, ] = objects # give polys names for qgeometry geom_perimeter = {"poly1": perimeter} geom_initial = {"poly2": initial} geom_arc = {"poly3": arc} geom_arc_left_1 = {"poly4": arc_left_1} geom_arc_left_2 = {"poly4": arc_left_2} geom_arc_left_3 = {"poly4": arc_left_3} geom_arc_left_4 = {"poly4": arc_left_4} geom_arc_left_5 = {"poly4": arc_left_5} geom_arc_left_6 = {"poly4": arc_left_6} geom_arc_left_7 = {"poly4": arc_left_7} geom_arc_right_1 = {"poly4": arc_right_1} geom_arc_right_2 = {"poly4": arc_right_2} geom_arc_right_3 = {"poly4": arc_right_3} geom_arc_right_4 = {"poly4": arc_right_4} geom_arc_right_5 = {"poly4": arc_right_5} geom_arc_right_6 = {"poly4": arc_right_6} geom_arc_right_7 = {"poly4": arc_right_7} geom_arc_last = {"poly4": arc_last} geom_final = {"poly": final} geom_line1 = {"poly5": line1} geom_line2 = {"poly6": line2} geom_line3 = {"poly7": line3} geom_line4 = {"poly8": line4} geom_line5 = {"poly9": line5} geom_line6 = {"poly10": line6} geom_line7 = {"poly11": line7} geom_line8 = {"poly11": line8} geom_line9 = {"poly9": line9} geom_line10 = {"poly10": line10} geom_line11 = {"poly11": line11} geom_line12 = {"poly12": line12} geom_line13 = {"poly13": line13} geom_line14 = {"poly14": line14} geom_line_last = {"poly14": line_last} # add to qgeometry self.add_qgeometry("poly", geom_perimeter, layer=p.layer, subtract=False) self.add_qgeometry( "path", geom_initial, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_arc, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_arc_left_1, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_arc_left_2, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_arc_left_3, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_arc_left_4, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_arc_left_5, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_arc_left_6, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_arc_left_7, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_arc_right_1, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_arc_right_2, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_arc_right_3, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_arc_right_4, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_arc_right_5, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_arc_right_6, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_arc_right_7, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_arc_last, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_line1, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_line2, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_line3, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_line4, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_line5, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_line6, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_line7, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_line8, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_line9, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_line10, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_line11, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_line12, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_line13, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_line14, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_line_last, layer=p.layer, subtract=False, width=p.res_width ) self.add_qgeometry( "path", geom_final, layer=p.layer, subtract=False, width=p.res_width ) ########################## # Add Qpin connections # define a function that both rotates and translates the qpin coordinates def qpin_rotate_translate(x): y = list(x) z = [0.0, 0.0] z[0] = y[0] * cos(p.orientation * 3.14159 / 180) - y[1] * sin( p.orientation * 3.14159 / 180 ) z[1] = y[0] * sin(p.orientation * 3.14159 / 180) + y[1] * cos( p.orientation * 3.14159 / 180 ) z[0] = z[0] + p.pos_x z[1] = z[1] + p.pos_y x = (z[0], z[1]) return x # East pin qp1a = (0.5 * p.box_width - p.perimeter_thickness, 0.0) qp1b = (0.5 * p.box_width, 0.0) qp1a = qpin_rotate_translate(qp1a) qp1b = qpin_rotate_translate(qp1b) self.add_pin( "pin_east", points=np.array([qp1a, qp1b]), width=0.01, input_as_norm=True ) # North-East pin qpa_ne = ( 0.5 * p.box_width - p.perimeter_thickness, 0.5 * p.box_height - p.perimeter_thickness, ) qpb_ne = (0.5 * p.box_width, 0.5 * p.box_height) qpa_ne = qpin_rotate_translate(qpa_ne) qpb_ne = qpin_rotate_translate(qpb_ne) self.add_pin( "pin_ne", points=np.array([qpa_ne, qpb_ne]), width=0.01, input_as_norm=True ) # South-East pin qpa_se = ( 0.5 * p.box_width - p.perimeter_thickness, -0.5 * p.box_height + p.perimeter_thickness, ) qpb_se = (0.5 * p.box_width, -0.5 * p.box_height) qpa_se = qpin_rotate_translate(qpa_se) qpb_se = qpin_rotate_translate(qpb_se) self.add_pin( "pin_se", points=np.array([qpa_se, qpb_se]), width=0.01, input_as_norm=True ) # North-West pin qpa_nw = ( -0.5 * p.box_width + p.perimeter_thickness, 0.5 * p.box_height - p.perimeter_thickness, ) qpb_nw = (-0.5 * p.box_width, 0.5 * p.box_height) qpa_nw = qpin_rotate_translate(qpa_nw) qpb_nw = qpin_rotate_translate(qpb_nw) self.add_pin( "pin_nw", points=np.array([qpa_nw, qpb_nw]), width=0.01, input_as_norm=True ) # West pin qp2a = (-0.5 * p.box_width + p.perimeter_thickness, 0.0) qp2b = (-0.5 * p.box_width, 0.0) qp2a = qpin_rotate_translate(qp2a) qp2b = qpin_rotate_translate(qp2b) self.add_pin( "pin_west", points=np.array([qp2a, qp2b]), width=0.01, input_as_norm=True ) # South-West pin qpa_sw = ( -0.5 * p.box_width + p.perimeter_thickness, -0.5 * p.box_height + p.perimeter_thickness, ) qpb_sw = (-0.5 * p.box_width, -0.5 * p.box_height) qpa_sw = qpin_rotate_translate(qpa_sw) qpb_sw = qpin_rotate_translate(qpb_sw) self.add_pin( "pin_sw", points=np.array([qpa_sw, qpb_sw]), width=0.01, input_as_norm=True ) # South pin qpa_s = (0.0, -0.5 * p.box_height + p.perimeter_thickness) qpb_s = (0.0, -0.5 * p.box_height) qpa_s = qpin_rotate_translate(qpa_s) qpb_s = qpin_rotate_translate(qpb_s) self.add_pin( "pin_s", points=np.array([qpa_s, qpb_s]), width=0.01, input_as_norm=True ) # north pin qpa_n = ( 0.0, -0.5 * p.box_height + p.perimeter_thickness + p.initial + 30.0 * p.turn_radius, ) qpb_n = ( 0.0, -0.5 * p.box_height + p.perimeter_thickness + p.initial + 30.0 * p.turn_radius + p.final, ) qpa_n = qpin_rotate_translate(qpa_n) qpb_n = qpin_rotate_translate(qpb_n) self.add_pin( "pin_n", points=np.array([qpa_n, qpb_n]), width=0.01, input_as_norm=True )