Source code for qiskit_metal.qlibrary.qubits.star_qubit

# -*- 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.
"""This is the StarQubit module."""

from shapely.geometry import CAP_STYLE

from qiskit_metal import Dict, draw  # , QComponent
from qiskit_metal.qlibrary.core import QComponent


[docs] class StarQubit(QComponent): """A single configurable circle with multiple pads. Inherits `BaseQubit` class. Create a circular transmon qubit with up to 4 connectors and one readout. .. image:: StarQubit.png .. meta:: :description: Star Qubit Default Options: * radius: '300um' -- Radius of the circle defining the star shape * center_radius: '100um' -- Measure of how thick the central island is * gap_couplers: '25um' -- Gap between the star and the coupling resonator * gap_readout: '10um' -- Gap between the star and the readout resonator * connector_length: '75um' -- Length of the rectangular part of the connector * trap_offset: '20um' -- Offset between trapezoid coordinates for side wall angle * junc_h: '30um' -- Junction height * cpw_width='0.01', -- Junction width * rotation_cpl1: '0.0' -- Rotation for one of the coupling resonators '36.0', '0.0', * rotation_cpl2: '72.0' -- Rotation for the readout resonator '108.0','72.0', * rotation_rdout: '144.0' -- Rotation for one of the coupling resonators '180.0','144.0', * rotation_cpl3: '216.0' -- Rotation for one of the coupling resonators'252.0','216.0', * rotation_cpl4: '288.0' -- Rotation for one of the coupling resonators '324.0','288.0', * number_of_connectors: '4' -- Total number of coupling resonators * resolution: '16' * cap_style: 'round' -- round, flat, square * subtract: 'False' * helper: 'False' """ component_metadata = Dict( short_name="Star", _qgeometry_table_poly="True", _qgeometry_table_junction="True", ) """Component metadata""" default_options = dict( radius="300um", center_radius="100um", gap_couplers="25um", gap_readout="10um", connector_length="75um", trap_offset="20um", junc_h="100um", cpw_width="0.01", rotation_cpl1="0.0", rotation_cpl2="72.0", rotation_rdout="144.0", rotation_cpl3="216.0", rotation_cpl4="288.0", number_of_connectors="4", resolution="16", cap_style="round", subtract="False", helper="False", ) """Default drawing options"""
[docs] def make(self): """The make function implements the logic that creates the geometry (poly, path, etc.) from the qcomponent.options dictionary of parameters, and the adds them to the design, using qcomponent.add_qgeometry(...), adding in extra needed information, such as layer, subtract, etc. """ self.make_inner_star() self.make_coupling_resonators(4) self.make_readout_resonator() self.make_outer_circle()
[docs] def make_circle(self): """This function creates a circle to be accessed later.""" p = self.p # create a circle circle = draw.Point(0, 0).buffer( p.radius, quad_segs=int(p.resolution), cap_style=getattr(CAP_STYLE, p.cap_style), ) return circle
[docs] def make_pockets(self): """This function creates the pockets.""" p = self.p # Connector pocket width/height pocket_w = p.connector_length pocket_h = p.connector_length * 2 # Connector to the JJ width/height pocket_w1 = p.gap_couplers pocket_h1 = p.center_radius pockets = [pocket_w, pocket_h, pocket_w1, pocket_h1] return pockets
[docs] def make_rotation(self, obj, num): """This function rotates objects.""" p = self.p if num == 1: rotation = [p.rotation_rdout] x = 1 elif num == 2: rotation = [p.rotation_rdout + 180] x = 1 elif num == 3: rotation = [ p.rotation_cpl1 + 180, p.rotation_cpl2 + 180, p.rotation_cpl3 + 180, p.rotation_cpl4 + 180, ] x = 4 elif num == 4: rotation = [ p.rotation_cpl1, p.rotation_cpl2, p.rotation_cpl3, p.rotation_cpl4, ] x = 4 elif num == 5: rotation = [ p.rotation_cpl1, p.rotation_cpl2, p.rotation_rdout, p.rotation_cpl3, p.rotation_cpl4, ] x = 5 obj_array = [0] * x for i in range(x): obj_array[i] = draw.rotate(obj, rotation[i], origin=(0, 0)) return obj_array
[docs] def make_coordinates_trap(self): """This function creates the coordinates for trapezoid""" p = self.p # Coordinates of the trapezoid to subtract from circle coord_y1 = -p.center_radius coord_y2 = -p.radius coord_x1 = -p.center_radius / 2 coord_x2 = p.center_radius / 2 coord_x3 = p.center_radius + p.trap_offset coord_x4 = -(p.center_radius + p.trap_offset) # coordinated for trapezoid to be cut out coords = [ ((coord_x1), (coord_y1)), ((coord_x2), (coord_y1)), ((coord_x3), (coord_y2)), ((coord_x4), (coord_y2)), ] return coords
[docs] def make_resonator_coordinates(self): """This function creates the coordinates for trapezoid""" p = self.p # Coordinates of the polygon defining the coupling resonator (a=x, b=y) coord_a1 = -(p.center_radius + p.gap_couplers) coord_a2 = -p.radius coord_a3 = p.radius coord_b1 = -(p.center_radius / 4) coord_b2 = p.center_radius / 4 coord_b3 = p.center_radius - (p.gap_couplers) coord_b4 = -(p.center_radius - (p.gap_couplers)) coord_b5 = -p.radius coord_b6 = p.radius # Define the coordinates of the polygon to define connectors coords_coupling_resonator = [ ((coord_b1), (coord_a1)), ((coord_b2), (coord_a1)), ((coord_b3), (coord_a2)), ((coord_b6), (coord_a2)), ((coord_b6), (coord_a3)), ((coord_b5), (coord_a3)), ((coord_b5), (coord_a2)), ((coord_b4), (coord_a2)), ] return coords_coupling_resonator
[docs] def make_readout_coordinates(self): """This function creates the coordinates for trapezoid""" p = self.p # Coordinates of the polygon defining the readout resonator (c=x, d=y) coord_c1 = -(p.center_radius + p.gap_readout) coord_c2 = -p.radius coord_c3 = p.radius coord_d1 = -(p.center_radius / 2 - p.gap_readout) coord_d2 = p.center_radius / 2 - p.gap_readout coord_d3 = p.center_radius coord_d4 = -p.center_radius coord_d5 = -p.radius coord_d6 = p.radius # Define the coordinates of the polygon to define readout coords_readout = [ ((coord_d1), (coord_c1)), ((coord_d2), (coord_c1)), ((coord_d3), (coord_c2)), ((coord_d6), (coord_c2)), ((coord_d6), (coord_c3)), ((coord_d5), (coord_c3)), ((coord_d5), (coord_c2)), ((coord_d4), (coord_c2)), ] return coords_readout
[docs] def make_pin_coordinates(self): """This function creates the coordinates for the pins""" p = self.p p_in = (0, p.radius) p_out = (0, 1.25 * (p.radius)) pins = draw.LineString([p_in, p_out]) return pins
[docs] def make_inner_star(self): """This function creates the coordinates for the pins""" p = self.p # Extracting coordinated from the user input values coords = self.make_coordinates_trap() coords1 = self.make_resonator_coordinates() trap_0 = draw.Polygon(coords) traps = self.make_rotation(trap_0, 5) # Define the final structure based on use input if (p.number_of_connectors) == 0: traps = traps[2] elif (p.number_of_connectors) == 1: traps = draw.union(traps[0], traps[2]) elif (p.number_of_connectors) == 2: traps = draw.union(traps[0], traps[1], traps[2]) elif (p.number_of_connectors) == 3: traps = draw.union(traps[0], traps[1], traps[2], traps[3]) elif (p.number_of_connectors) == 4: traps = draw.union(traps[0], traps[1], traps[2], traps[3], traps[4]) # Subtract from circle circle = self.make_circle() total1 = draw.subtract(circle, traps) # create rectangular connectors to junction pockets = self.make_pockets() rect1 = draw.rectangle(pockets[2], pockets[3]) rect1 = draw.translate(rect1, xoff=coords1[0][0] * 1.1, yoff=p.radius) rect1 = draw.rotate(rect1, p.rotation_cpl1, origin=(0, 0)) rect2 = draw.rectangle(pockets[2], pockets[3]) rect2 = draw.translate(rect2, xoff=coords1[1][0] * 1.1, yoff=p.radius) rect2 = draw.rotate(rect2, p.rotation_cpl1, origin=(0, 0)) # junction jjunction = draw.LineString([[0, 0], [0, coords[1][0]]]) jjunction = draw.translate(jjunction, yoff=(1.15 * (p.radius))) jjunction = draw.rotate(jjunction, p.rotation_cpl1, origin=(0, 0)) # Add connection to the junction total = draw.union(total1, rect1, rect2) objects = [total, jjunction] objects = draw.rotate(objects, p.orientation, origin=(0, 0)) objects = draw.translate(objects, p.pos_x, p.pos_y) [total, jjunction] = objects self.add_qgeometry( "poly", {"circle_inner": total}, subtract=p.subtract, helper=p.helper, layer=p.layer, chip=p.chip, ) self.add_qgeometry( "junction", {"poly": jjunction}, subtract=p.subtract, helper=p.helper, layer=p.layer, chip=p.chip, width=p.junc_h, )
[docs] def make_coupling_resonators(self, num): """This function draws the coulping resonators. Adds pins. And adds the drawn geometry to qgeomtery table. """ p = self.p # rotate these trapezoids to form the contacts coords = self.make_coordinates_trap() coords1 = self.make_resonator_coordinates() trap_z = draw.Polygon(coords1) traps_connection = self.make_rotation(trap_z, 4) # Define contacts pockets = self.make_pockets() pocket0 = draw.rectangle(pockets[0], pockets[1]) pocket0 = draw.translate(pocket0, xoff=0, yoff=(coords[3][1])) pockets = self.make_rotation(pocket0, 4) # Define the connectors circle = self.make_circle() contacts = [0] * num for i in range(num): contacts[i] = draw.subtract(circle, traps_connection[i]) contacts[i] = draw.union(contacts[i], pockets[i]) pins = self.make_pin_coordinates() pins_cpl = self.make_rotation(pins, 3) objects = [contacts, pins_cpl] objects = draw.rotate(objects, p.orientation, origin=(0, 0)) objects = draw.translate(objects, p.pos_x, p.pos_y) [contacts, pins_cpl] = objects ################################################################## # Add geometry and Qpin connections if (p.number_of_connectors) >= 1: self.add_qgeometry( "poly", {"contact_cpl1": contacts[0]}, subtract=p.subtract, helper=p.helper, layer=p.layer, chip=p.chip, ) # Add pin connections self.add_pin( "pin_cpl1", pins_cpl[0].coords, width=p.cpw_width, input_as_norm=True ) if (p.number_of_connectors) >= 2: self.add_qgeometry( "poly", {"contact_cpl2": contacts[1]}, subtract=p.subtract, helper=p.helper, layer=p.layer, chip=p.chip, ) # Add pin connections self.add_pin( "pin_cpl2", pins_cpl[1].coords, width=p.cpw_width, input_as_norm=True ) if (p.number_of_connectors) >= 3: self.add_qgeometry( "poly", {"contact_cpl3": contacts[2]}, subtract=p.subtract, helper=p.helper, layer=p.layer, chip=p.chip, ) # Add pin connections self.add_pin( "pin_cpl3", pins_cpl[2].coords, width=p.cpw_width, input_as_norm=True ) if (p.number_of_connectors) >= 4: self.add_qgeometry( "poly", {"contact_cpl4": contacts[3]}, subtract=p.subtract, helper=p.helper, layer=p.layer, chip=p.chip, ) # Add pin connections self.add_pin( "pin_cpl4", pins_cpl[3].coords, width=p.cpw_width, input_as_norm=True )
[docs] def make_readout_resonator(self): """This function draws the readout resonator. Adds pins. And adds the drawn geometry to qgeomtery table. """ p = self.p coords_readout = self.make_readout_coordinates() circle = self.make_circle() pockets = self.make_pockets() coords = self.make_coordinates_trap() # Make the readout resonator with the pocket contact_rdout = draw.Polygon(coords_readout) contact_rdout = draw.subtract(circle, contact_rdout) contact_rdout = self.make_rotation(contact_rdout, 1) # Define contacts pocket0 = draw.rectangle(pockets[0], pockets[1]) pocket0 = draw.translate(pocket0, xoff=0, yoff=(coords[3][1])) pocket0 = self.make_rotation(pocket0, 1) # Join the coupler and contact contact_rdout = draw.union(contact_rdout[0], pocket0[0]) pins = self.make_pin_coordinates() pins_rdout = self.make_rotation(pins, 2) objects = [contact_rdout, pins_rdout] objects = draw.rotate(objects, p.orientation, origin=(0, 0)) objects = draw.translate(objects, p.pos_x, p.pos_y) [contact_rdout, pins_rdout] = objects ################################################################## # Add geometry and Qpin connections self.add_qgeometry( "poly", {"contact_rdout": contact_rdout}, subtract=p.subtract, helper=p.helper, layer=p.layer, chip=p.chip, ) self.add_pin( "pin_rdout", pins_rdout[0].coords, width=p.cpw_width, input_as_norm=True )
[docs] def make_outer_circle(self): """This function draws the outer circle.""" p = self.p coords = self.make_coordinates_trap() circle_outer = draw.Point(0, 0).buffer( p.radius * (1 + (p.connector_length / p.radius)), quad_segs=int(p.resolution), cap_style=getattr(CAP_STYLE, p.cap_style), ) # Connectors for the ground plane pockets = self.make_pockets() pocket_z = draw.rectangle(pockets[0] * 1.4, pockets[1]) pocket_z = draw.translate(pocket_z, xoff=0, yoff=(coords[2][1])) pockets_ground = self.make_rotation(pocket_z, 5) if (p.number_of_connectors) == 0: circle_outer = draw.union(circle_outer, pockets_ground[2]) elif (p.number_of_connectors) == 1: circle_outer = draw.union( circle_outer, pockets_ground[0], pockets_ground[2] ) elif (p.number_of_connectors) == 2: circle_outer = draw.union( circle_outer, pockets_ground[0], pockets_ground[1], pockets_ground[2] ) elif (p.number_of_connectors) == 3: circle_outer = draw.union( circle_outer, pockets_ground[0], pockets_ground[1], pockets_ground[2], pockets_ground[3], ) elif (p.number_of_connectors) == 4: circle_outer = draw.union( circle_outer, pockets_ground[0], pockets_ground[1], pockets_ground[2], pockets_ground[3], pockets_ground[4], ) ################################################################## # Add geometry and Qpin connections objects = [circle_outer] objects = draw.rotate(objects, p.orientation, origin=(0, 0)) objects = draw.translate(objects, p.pos_x, p.pos_y) [circle_outer] = objects self.add_qgeometry( "poly", {"circle_outer": circle_outer}, subtract=True, helper=p.helper, layer=p.layer, chip=p.chip, )