Exemplo n.º 1
0
    def make(self):
        """
        The make function implements the logic that creates the geoemtry
        (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.
        """
        p = self.p  # p for parsed parameters. Access to the parsed options.

        # create the geometry
        caterpillar = [
            draw.Point(p.pos_x - p.radius * i * p.distance, p.pos_y).buffer(
                p.radius,
                resolution=int(p.resolution),
                cap_style=getattr(CAP_STYLE, p.cap_style),
                #join_style = getattr(JOIN_STYLE, p.join_style)
            ) for i in range(int(p.segments))
        ]
        caterpillar = draw.union(caterpillar)

        poly = draw.Polygon([(0, 0), (0.5, 0), (0.25, 0.5)])
        poly = draw.translate(poly, p.pos_x, p.pos_y)
        poly = draw.rotate(poly, angle=65)
        caterpillar = draw.subtract(caterpillar, poly)

        # rect = draw.rectangle(p.radius*0.75, p.radius*0.23,
        #                      xoff=p.pos_x+p.radius*0.3,
        #                      yoff=p.pos_y+p.radius*0.4)
        #caterpillar = draw.subtract(caterpillar, rect)
        # print(caterpillar)

        # add qgeometry
        #self.add_qgeometry('poly', {'mount': rect})
        self.add_qgeometry('poly', {'caterpillar': caterpillar})
Exemplo n.º 2
0
    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
Exemplo n.º 3
0
    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)
Exemplo n.º 4
0
    def make(self):
        """The make function implements the logic that creates the geoemtry
        (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."""
        p = self.p  # p for parsed parameters. Access to the parsed options.

        # create the geometry
        circle = draw.Point(p.pos_x, p.pos_y).buffer(
            p.radius,
            resolution=int(p.resolution),
            cap_style=getattr(CAP_STYLE, p.cap_style),
            #join_style = getattr(JOIN_STYLE, p.join_style)
        )

        # add qgeometry
        self.add_qgeometry('poly', {'circle': circle},
                           subtract=p.subtract,
                           helper=p.helper,
                           layer=p.layer,
                           chip=p.chip)
Exemplo n.º 5
0
    def make_pocket(self):
        """Makes standard transmon in a pocket."""

        # self.p allows us to directly access parsed values (string -> numbers) form the user option
        p = self.p
        #  pcop = self.p.coupled_pads[name]  # parser on connector options

        # since we will reuse these options, parse them once and define them as variables
        pad_width = p.pad_width
        pad_height = p.pad_height
        pad_gap = p.pad_gap
        coupled_pad_height = p.coupled_pad_height
        coupled_pad_width = p.coupled_pad_width
        coupled_pad_gap = p.coupled_pad_gap

        # make the pads as rectangles (shapely polygons)
        pad = draw.rectangle(pad_width, pad_height)

        pad_top = draw.translate(pad, 0, +(pad_height + pad_gap) / 2.)
        # Here, you make your pads round. Not sharp shape on the left and right sides and also this should be the same for the bottom pad as the top pad.
        circ_left_top = draw.Point(-pad_width / 2., +(pad_height + pad_gap) /
                                   2.).buffer(pad_height / 2,
                                              resolution=16,
                                              cap_style=CAP_STYLE.round)
        circ_right_top = draw.Point(pad_width / 2., +(pad_height + pad_gap) /
                                    2.).buffer(pad_height / 2,
                                               resolution=16,
                                               cap_style=CAP_STYLE.round)
        # In here you create the teeth part and then you union them as one with the pad. Teeth only belong to top pad.
        coupled_pad = draw.rectangle(coupled_pad_width,
                                     coupled_pad_height + pad_height)
        coupler_pad_round = draw.Point(0., (coupled_pad_height + pad_height) /
                                       2).buffer(coupled_pad_width / 2,
                                                 resolution=16,
                                                 cap_style=CAP_STYLE.round)
        coupled_pad = draw.union(coupled_pad, coupler_pad_round)
        coupled_pad_left = draw.translate(
            coupled_pad, -(coupled_pad_width / 2. + coupled_pad_gap / 2.),
            +coupled_pad_height / 2. + pad_height + pad_gap / 2. -
            pad_height / 2)
        coupled_pad_right = draw.translate(
            coupled_pad, (coupled_pad_width / 2. + coupled_pad_gap / 2.),
            +coupled_pad_height / 2. + pad_height + pad_gap / 2. -
            pad_height / 2)
        pad_top_tmp = draw.union([circ_left_top, pad_top, circ_right_top])
        # The coupler pads are only created if low_W=0 and low_H=+1
        for name in self.options.connection_pads:
            if self.options.connection_pads[name][
                    'loc_W'] == 0 and self.options.connection_pads[name][
                        'loc_H'] == +1:
                pad_top_tmp = draw.union([
                    circ_left_top, coupled_pad_left, pad_top, coupled_pad_right,
                    circ_right_top
                ])
        pad_top = pad_top_tmp
        # Round part for the bottom pad. And again you should unite all of them.
        pad_bot = draw.translate(pad, 0, -(pad_height + pad_gap) / 2.)
        circ_left_bot = draw.Point(-pad_width / 2, -(pad_height + pad_gap) /
                                   2.).buffer(pad_height / 2,
                                              resolution=16,
                                              cap_style=CAP_STYLE.round)
        circ_right_bot = draw.Point(pad_width / 2, -(pad_height + pad_gap) /
                                    2.).buffer(pad_height / 2,
                                               resolution=16,
                                               cap_style=CAP_STYLE.round)
        pad_bot = draw.union([pad_bot, circ_left_bot, circ_right_bot])

        rect_jj = draw.LineString([(0, -pad_gap / 2), (0, +pad_gap / 2)])
        # the draw.rectangle representing the josephson junction
        # rect_jj = draw.rectangle(p.inductor_width, pad_gap)

        rect_pk = draw.rectangle(p.pocket_width, p.pocket_height)

        # Rotate and translate all qgeometry as needed.
        # Done with utility functions in Metal 'draw_utility' for easy rotation/translation
        # NOTE: Should modify so rotate/translate accepts qgeometry, would allow for
        # smoother implementation.
        polys = [rect_jj, pad_top, pad_bot, rect_pk]
        polys = draw.rotate(polys, p.orientation, origin=(0, 0))
        polys = draw.translate(polys, p.pos_x, p.pos_y)
        [rect_jj, pad_top, pad_bot, rect_pk] = polys

        # Use the geometry to create Metal qgeometry
        self.add_qgeometry('poly', dict(pad_top=pad_top, pad_bot=pad_bot))
        self.add_qgeometry('poly', dict(rect_pk=rect_pk), subtract=True)
        # self.add_qgeometry('poly', dict(
        #     rect_jj=rect_jj), helper=True)
        self.add_qgeometry('junction',
                           dict(rect_jj=rect_jj),
                           width=p.inductor_width)
    def make(self):
        """Convert self.options into QGeometry."""

        p = self.parse_options()  # Parse the string options into numbers

        # draw the concentric pad regions
        outer_pad = draw.Point(0, 0).buffer(p.rad_o)
        space = draw.Point(0, 0).buffer((p.gap + p.rad_i))
        outer_pad = draw.subtract(outer_pad, space)
        inner_pad = draw.Point(0, 0).buffer(p.rad_i)
        #gap = draw.subtract(space, inner_pad)
        #pads = draw.union(outer_pad, inner_pad)

        # draw the top Josephson Junction
        jj_t = draw.LineString([(0.0, p.rad_i), (0.0, p.rad_i + p.gap)])

        # draw the bottom Josephson Junction
        jj_b = draw.LineString([(0.0, -1.0 * p.rad_i),
                                (0.0, -1.0 * p.rad_i - 1.0 * p.gap)])

        # draw the readout resonator
        qp1a = (-0.5 * p.pocket_w, p.rad_o + p.res_s
                )  # the first (x,y) coordinate is qpin #1
        qp1b = (p.res_ext, p.rad_o + p.res_s
                )  # the second (x,y) coordinate is qpin #1
        rr = draw.LineString([qp1a, qp1b])

        # draw the flux bias line
        a = (0.5 * p.pocket_w, -0.5 * p.fbl_gap)
        b = (0.5 * p.pocket_w - p.fbl_ext, -0.5 * p.fbl_gap)
        c = (p.rad_o + p.fbl_sp + p.fbl_rad, -1.0 * p.fbl_rad)
        d = (p.rad_o + p.fbl_sp + 0.2929 * p.fbl_rad, 0.0 - 0.7071 * p.fbl_rad)
        e = (p.rad_o + p.fbl_sp, 0.0)
        f = (p.rad_o + p.fbl_sp + 0.2929 * p.fbl_rad, 0.0 + 0.7071 * p.fbl_rad)
        g = (p.rad_o + p.fbl_sp + p.fbl_rad, p.fbl_rad)
        h = (0.5 * p.pocket_w - p.fbl_ext, 0.5 * p.fbl_gap)
        i = (0.5 * p.pocket_w, 0.5 * p.fbl_gap)
        fbl = draw.LineString([a, b, c, d, e, f, g, h, i])

        # draw the transmon pocket bounding box
        pocket = draw.rectangle(p.pocket_w, p.pocket_h)

        # Translate and rotate all shapes
        objects = [outer_pad, inner_pad, jj_t, jj_b, pocket, rr, fbl]
        objects = draw.rotate(objects, p.orientation, origin=(0, 0))
        objects = draw.translate(objects, xoff=p.pos_x, yoff=p.pos_y)
        [outer_pad, inner_pad, jj_t, jj_b, pocket, rr, fbl] = objects

        # 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

        # rotate and translate the qpin coordinates
        qp1a = qpin_rotate_translate(qp1a)
        qp1b = qpin_rotate_translate(qp1b)
        a = qpin_rotate_translate(a)
        b = qpin_rotate_translate(b)
        h = qpin_rotate_translate(h)
        i = qpin_rotate_translate(i)

        ##############################################################

        # Use the geometry to create Metal QGeometry
        geom_rr = {'path1': rr}
        geom_fbl = {'path2': fbl}
        geom_outer = {'poly1': outer_pad}
        geom_inner = {'poly2': inner_pad}
        geom_jjt = {'poly4': jj_t}
        geom_jjb = {'poly5': jj_b}
        geom_pocket = {'poly6': pocket}

        self.add_qgeometry('path',
                           geom_rr,
                           layer=1,
                           subtract=False,
                           width=p.cpw_width)
        self.add_qgeometry('path',
                           geom_fbl,
                           layer=1,
                           subtract=False,
                           width=p.cpw_width)
        self.add_qgeometry('poly', geom_outer, layer=1, subtract=False)
        self.add_qgeometry('poly', geom_inner, layer=1, subtract=False)
        self.add_qgeometry('junction',
                           geom_jjt,
                           layer=1,
                           subtract=False,
                           width=p.inductor_width)
        self.add_qgeometry('junction',
                           geom_jjb,
                           layer=1,
                           subtract=False,
                           width=p.inductor_width)
        self.add_qgeometry('poly', geom_pocket, layer=1, subtract=True)

        ###########################################################################

        # Add Qpin connections
        self.add_pin('pin1',
                     points=np.array([qp1b, qp1a]),
                     width=0.01,
                     input_as_norm=True)
        self.add_pin('pin2',
                     points=np.array([b, a]),
                     width=0.01,
                     input_as_norm=True)
        self.add_pin('pin3',
                     points=np.array([h, i]),
                     width=0.01,
                     input_as_norm=True)
Exemplo n.º 7
0
    def make_ro(self):
        '''
        Create the head of the readout resonator.
        Contains: the circular patch for coupling,
            the 45 deg line,
            the 45 deg arc,
            a short straight segment (of length w) for smooth subtraction
        '''
        # access to parsed values from the user option
        p = self.p

        # access to chip name
        chip = p.chip

        # local variables
        r = p.readout_radius
        w = p.readout_cpw_width
        g = p.readout_cpw_gap
        turnradius = p.readout_cpw_turnradius
        l_1 = p.readout_l1
        l_2 = p.readout_l2
        l_3 = p.readout_l3
        l_4 = p.readout_l4
        l_5 = p.readout_l5

        # create the coupling patch in term of a circle
        cppatch = draw.Point(0, 0).buffer(r)

        # create the extended arm
        ## useful coordinates
        x_1, y_1 = l_1 * np.cos(np.pi / 4), -l_1 * np.sin(np.pi / 4)
        x_2, y_2 = x_1 + turnradius * (
            1 - np.cos(np.pi / 4)), y_1 - turnradius * np.sin(np.pi / 4)
        coord_init = draw.Point(x_1, y_1)
        coord_center = draw.Point(x_1 - turnradius * np.cos(np.pi / 4),
                                  y_1 - turnradius * np.sin(np.pi / 4))
        x_3, y_3 = x_2, y_2
        x_4, y_4 = x_3, y_3 - l_2
        x_5, y_5 = x_4 + turnradius, y_4
        coord_init1 = draw.Point(x_4, y_4)
        coord_center1 = draw.Point(x_5, y_5)
        x_6, y_6 = x_5, y_5 - turnradius
        x_7, y_7 = x_5 + l_3, y_6
        x_8, y_8 = x_7, y_7 + turnradius
        coord_init2 = draw.Point((x_7, y_7))
        coord_center2 = draw.Point((x_8, y_8))
        x_9, y_9 = x_8, y_8 + turnradius
        x_10, y_10 = x_8 - l_4, y_9
        x_11, y_11 = x_10, y_10 + turnradius
        coord_init3 = draw.Point((x_10, y_10))
        coord_center3 = draw.Point((x_11, y_11))
        arc3 = self.arc(coord_init3, coord_center3, -np.pi)
        x_12, y_12 = x_11, y_11 + turnradius
        x_13, y_13 = x_12 + l_5, y_12
        line12 = draw.LineString([(x_12, y_12), (x_13, y_13)])
        x_14, y_14 = x_13, y_13 + turnradius
        coord_init4 = draw.Point((x_13, y_13))
        coord_center4 = draw.Point((x_14, y_14))
        arc4 = self.arc(coord_init4, coord_center4, np.pi)
        ## line containing the 45deg line, 45 deg arc,
        ## and a short straight segment for smooth subtraction
        cparm_line = draw.shapely.ops.unary_union([
            draw.LineString([(0, 0), coord_init]),
            self.arc(coord_init, coord_center, -np.pi / 4),
            draw.LineString([(x_3, y_3), (x_4, y_4)]),
            self.arc(coord_init1, coord_center1, np.pi / 2),
            draw.LineString([(x_6, y_6), (x_7, y_7)]),
            self.arc(coord_init2, coord_center2, np.pi),
            draw.LineString([(x_9, y_9), (x_10, y_10)]), arc3, line12, arc4,
            draw.translate(line12, 0, 2 * turnradius),
            draw.translate(arc3, 0, 4 * turnradius),
            draw.translate(line12, 0, 4 * turnradius),
            draw.translate(arc4, 0, 4 * turnradius),
            draw.translate(line12, 0, 6 * turnradius),
            draw.translate(arc3, 0, 8 * turnradius),
            draw.translate(line12, 0, 8 * turnradius)
        ])
        cparm = cparm_line.buffer(w / 2, cap_style=2, join_style=1)
        ## fix the gap resulting from buffer
        eps = 1e-3
        cparm = draw.Polygon(cparm.exterior)
        cparm = cparm.buffer(eps, join_style=2).buffer(-eps, join_style=2)

        # create combined objects for the signal line and the etch
        ro = draw.shapely.ops.unary_union([cppatch, cparm])
        ro_etch = ro.buffer(g, cap_style=2, join_style=2)
        x_15, y_15 = x_14, y_14 + 7 * turnradius
        x_16, y_16 = x_15 + g / 2, y_15
        port_line = draw.LineString([(x_15, y_15 + w / 2),
                                     (x_15, y_15 - w / 2)])
        subtract_patch = draw.LineString([(x_16, y_16 - w / 2 - g - eps),
                                          (x_16, y_16 + w / 2 + g + eps)
                                          ]).buffer(g / 2, cap_style=2)
        ro_etch = ro_etch.difference(subtract_patch)

        # rotate and translate
        polys = [ro, ro_etch, port_line]
        polys = draw.rotate(polys, p.orientation, origin=(0, 0))
        polys = draw.translate(polys, p.pos_x, p.pos_y)

        # update each object
        [ro, ro_etch, port_line] = polys

        # generate QGeometry
        self.add_qgeometry('poly', dict(ro=ro), chip=chip, layer=p.layer)
        self.add_qgeometry('poly',
                           dict(ro_etch=ro_etch),
                           chip=chip,
                           layer=p.layer_subtract,
                           subtract=p.subtract)

        # generate pins
        self.add_pin('readout', port_line.coords, width=w, gap=g, chip=chip)