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 draw, Dict  # , 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:: star_qubit.png .. meta:: 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, resolution=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)), resolution=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)