Exemplo n.º 1
0
 def nwell_square(dope='NP', ext=[], topmet=1): # square cell to fill corners
     # ext: extend M1 0:North, 1:East, 2:South, 3:West
     nwell_square = gdspy.Cell('NWELL_SQUARE', True)
     od_shape = gdspy.Rectangle((0,0), (basic.OD_W, basic.OD_W), basic.layer['OD'])
     nwell_square.add(od_shape)
     # Legalization changes
     delta = 0.5*(basic.OD_W-basic.min_w['M1'])
     for i in range(topmet):
         m_layer = 'M' + str(i+1)
         if len(ext) > 0:
             m1_shape = gdspy.Rectangle((0.5*(basic.OD_W-basic.min_w['M1']),0.5*(basic.OD_W-basic.min_w['M1'])), (0.5*(basic.OD_W+basic.min_w['M1']),0.5*(basic.OD_W+basic.min_w['M1'])), basic.layer[m_layer], basic.datatype[m_layer])
             nwell_square.add(m1_shape)
         m1_ext_ns = gdspy.Rectangle((0,0), (basic.min_w['M1'], delta), basic.layer[m_layer], basic.datatype[m_layer])
         m1_ext_ew = gdspy.Rectangle((0,0), (delta, basic.min_w['M1']), basic.layer[m_layer], basic.datatype[m_layer])
         if 0 in ext:
             m1_ext_1 = gdspy.copy(m1_ext_ns, delta, delta+basic.min_w['M1'])
             nwell_square.add(m1_ext_1)
         if 1 in ext:
             m1_ext_2 = gdspy.copy(m1_ext_ew, delta+basic.min_w['M1'], delta)
             nwell_square.add(m1_ext_2)
         if 2 in ext:
             m1_ext_3 = gdspy.copy(m1_ext_ns, delta, 0)
             nwell_square.add(m1_ext_3)
         if 3 in ext:
             m1_ext_4 = gdspy.copy(m1_ext_ew, 0, delta)
             nwell_square.add(m1_ext_4)
     # Removed co for DRC
     #co_en = 0.5 * (basic.OD_W - basic.min_w['CO'])
     #co_shape = gdspy.Rectangle((co_en, co_en), (co_en+basic.min_w['CO'], co_en+basic.min_w['CO']), layer['CO'])
     #nwell_square.add(co_shape)
     np_shape = gdspy.Rectangle((-basic.NP_OD, -basic.NP_OD), (basic.OD_W+basic.NP_OD, basic.OD_W+basic.NP_OD), basic.layer[dope])
     nwell_square.add(np_shape)
     nwell_square.flatten()
     return nwell_square
Exemplo n.º 2
0
def test_copy():
    p = gdspy.Rectangle((0, 0), (1, 1))
    q = gdspy.copy(p, 1, -1)
    assert set(p.polygons[0][:, 0]) == {0, 1}
    assert set(p.polygons[0][:, 1]) == {0, 1}
    assert set(q.polygons[0][:, 0]) == {1, 2}
    assert set(q.polygons[0][:, 1]) == {-1, 0}
    p = gdspy.PolygonSet([[(0, 0), (1, 0), (0, 1)], [(2, 2), (3, 2), (2, 3)]])
    q = gdspy.copy(p, 1, -1)
    assert set(p.polygons[0][:, 0]) == {0, 1}
    assert set(p.polygons[0][:, 1]) == {0, 1}
    assert set(q.polygons[0][:, 0]) == {1, 2}
    assert set(q.polygons[0][:, 1]) == {-1, 0}
    assert set(p.polygons[1][:, 0]) == {2, 3}
    assert set(p.polygons[1][:, 1]) == {2, 3}
    assert set(q.polygons[1][:, 0]) == {3, 4}
    assert set(q.polygons[1][:, 1]) == {1, 2}
    l = gdspy.Label('text', (0, 1))
    m = gdspy.copy(l, -1, 1)
    assert l.position[0] == 0 and l.position[1] == 1
    assert m.position[0] == -1 and m.position[1] == 2
    c = gdspy.CellReference('empty', (0, 1), ignore_missing=True)
    d = gdspy.copy(c, -1, 1)
    assert c.origin == (0, 1)
    assert d.origin == (-1, 2)
    c = gdspy.CellArray('empty', 2, 3, (1, 0), (0, 1), ignore_missing=True)
    d = gdspy.copy(c, -1, 1)
    assert c.origin == (0, 1)
    assert d.origin == (-1, 2)
Exemplo n.º 3
0
def test_copy():
    p = gdspy.Rectangle((0, 0), (1, 1))
    q = gdspy.copy(p, 1, -1)
    assert set(p.polygons[0][:, 0]) == {0, 1}
    assert set(p.polygons[0][:, 1]) == {0, 1}
    assert set(q.polygons[0][:, 0]) == {1, 2}
    assert set(q.polygons[0][:, 1]) == {-1, 0}
    p = gdspy.PolygonSet([[(0, 0), (1, 0), (0, 1)], [(2, 2), (3, 2), (2, 3)]])
    q = gdspy.copy(p, 1, -1)
    assert set(p.polygons[0][:, 0]) == {0, 1}
    assert set(p.polygons[0][:, 1]) == {0, 1}
    assert set(q.polygons[0][:, 0]) == {1, 2}
    assert set(q.polygons[0][:, 1]) == {-1, 0}
    assert set(p.polygons[1][:, 0]) == {2, 3}
    assert set(p.polygons[1][:, 1]) == {2, 3}
    assert set(q.polygons[1][:, 0]) == {3, 4}
    assert set(q.polygons[1][:, 1]) == {1, 2}
    l = gdspy.Label("text", (0, 1))
    m = gdspy.copy(l, -1, 1)
    assert l.position[0] == 0 and l.position[1] == 1
    assert m.position[0] == -1 and m.position[1] == 2
    c = gdspy.CellReference("empty", (0, 1), ignore_missing=True)
    d = gdspy.copy(c, -1, 1)
    assert c.origin == (0, 1)
    assert d.origin == (-1, 2)
    c = gdspy.CellArray("empty", 2, 3, (1, 0), (0, 1), ignore_missing=True)
    d = gdspy.copy(c, -1, 1)
    assert c.origin == (0, 1)
    assert d.origin == (-1, 2)
Exemplo n.º 4
0
def generate_JJ():
    root_width = 5
    root_height = 15
    tip_width = 2
    tip_height = 4
    taper_height=15

    cross_dist = 5
    cross_len = 8
    cross_width = 0.2

    uc_shift = 1
    uc_tip_height = 2.5

    base_layer = 30
    uc_layer = 40

    # base pattern
    base_path = gdspy.Path(root_width, (0, 0))
    base_path.segment(root_height, '+y', layer=base_layer)
    base_path.segment(taper_height, '+y', final_width=tip_width, layer=base_layer)
    base_path.segment(tip_height, '+y', layer=base_layer)

    tip_cir = gdspy.Round((0, root_height+taper_height+tip_height), tip_width/2, initial_angle=0, final_angle=np.pi, layer=base_layer)
    JJ_base1 = gdspy.boolean(base_path, tip_cir, 'or', max_points=0, layer=base_layer)
    JJ_base2 = gdspy.copy(JJ_base1).rotate(np.pi, (0, root_height+taper_height+tip_height)).translate(cross_dist, cross_dist)
    JJ_base = gdspy.boolean(JJ_base1, JJ_base2, 'or', max_points=0, layer=base_layer)

    JJ_cross1 = gdspy.Path(cross_width, (0, root_height+taper_height+tip_height))
    JJ_cross1.segment(cross_len, '+x', layer=base_layer)

    JJ_cross2 = gdspy.Path(cross_width, initial_point=(cross_dist, root_height+taper_height+tip_height+cross_dist))
    JJ_cross2.segment(cross_len, '-y', layer=base_layer)
    JJ_cross = gdspy.boolean(JJ_cross1, JJ_cross2, 'or', max_points=0, layer=base_layer)

    JJ_total = gdspy.boolean(JJ_base, JJ_cross, 'or', max_points=0, layer=base_layer)

    # under cut
    uc_path = gdspy.Path(root_width+2*uc_shift, (0, -uc_shift))
    uc_path.segment(root_height+uc_shift, '+y', layer=uc_layer)
    uc_path.segment(taper_height, '+y', final_width=tip_width+2*uc_shift, layer=uc_layer)
    uc_path.segment(tip_height+tip_width/2+uc_shift, '+y', layer=uc_layer)

    uc_base1 = uc_path
    uc_base2 = gdspy.copy(uc_base1).rotate(np.pi, (0, root_height+taper_height+tip_height)).translate(cross_dist, cross_dist)
    uc_base = gdspy.boolean(uc_base1, uc_base2, 'or', max_points=0, layer=uc_layer)

    uc_tip1 = gdspy.Path(uc_shift, (cross_len - uc_tip_height/2, root_height+taper_height+tip_height))
    uc_tip1.segment(uc_tip_height, '+x', layer=uc_layer)
    uc_tip2 = gdspy.Path(uc_shift, (cross_dist, root_height+taper_height+tip_height+cross_dist-cross_len+uc_tip_height/2))
    uc_tip2.segment(uc_tip_height, '-y', layer=uc_layer)
    uc_tip = gdspy.boolean(uc_tip1, uc_tip2, 'or', max_points=0, layer=uc_layer)

    uc = gdspy.boolean(uc_base, uc_tip, 'or', max_points=0, layer=uc_layer)    

    dx = -cross_dist/2
    dy = -(root_height+taper_height+tip_height+cross_dist/2)

    return [JJ_total.translate(dx, dy), uc.translate(dx, dy)]
Exemplo n.º 5
0
def test_fillet(target):
    cell = gdspy.Cell("test")
    orig = gdspy.PolygonSet([
        [
            (0, 0),
            (-1, 0),
            (0, -1),
            (0.5, -0.5),
            (1, 0),
            (1, 1),
            (4, -1),
            (1, 3),
            (1, 2),
            (0, 1),
        ],
        [(2, -1), (3, -1), (2.5, -2)],
    ])
    orig.datatypes = [0, 1]
    p = gdspy.copy(orig, 0, 5)
    p.layers = [1, 1]
    p.fillet(0.3, max_points=0)
    cell.add(p)
    p = gdspy.copy(orig, 5, 5)
    p.layers = [2, 2]
    p.fillet([0.3, 0.2, 0.1, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.4, 0.1, 0.2, 0],
             max_points=0)
    cell.add(p)
    p = gdspy.copy(orig, 5, 0)
    p.layers = [3, 3]
    p.fillet(
        [[0.1, 0.1, 0.4, 0, 0.4, 0.1, 0.1, 0.4, 0.4, 0.1], [0.2, 0.2, 0.5]],
        max_points=0,
    )
    cell.add(p)
    p = gdspy.PolygonSet(
        [
            [
                (0, 0),
                (0, 0),
                (-1, 0),
                (0, -1),
                (0.5, -0.5),
                (1, 0),
                (1, 0),
                (1, 1),
                (4, -1),
                (1, 3),
                (1, 2),
                (0, 1),
            ],
            [(2, -1), (3, -1), (2.5, -2), (2, -1)],
        ],
        layer=4,
    )
    p.datatypes = [0, 1]
    p.fillet([0.8, [10.0, 10.0, 20.0, 20.0]], max_points=199, precision=1e-6)
    cell.add(p)
    assertsame(cell, target["PolygonSet_fillet"], tolerance=1e-3)
Exemplo n.º 6
0
def contour2gds(contour0, args):
    """transform contour list to gds """
    contour = [[ele[0] for ele in arr] for arr in contour0]
    if args.sharpen:
        contour = sharpenCorner(contour, args)
    flat_list = [item for sublist in contour for item in sublist]

    x = [arr[0] for arr in flat_list]
    y = [arr[1] for arr in flat_list]
    xlength = max(x) - min(x)
    ylength = max(y) - min(y)

    maxY = max(y)
    contour = [[[ele[0], maxY - ele[1]] for ele in arr] for arr in contour]

    poly_cell = gdspy.Cell('tmp')
    poly = gdspy.PolygonSet(contour, 1)

    nX = args.nX
    nY = args.nY
    xsep = max(xlength, ylength) * args.sep
    ysep = xsep
    for i in range(nX):
        for j in range(nY):
            xpos = (xlength + xsep) * (i + 1)
            ypos = (ylength + ysep) * (j + 1)
            trans = gdspy.copy(poly, xpos, ypos)
            poly_cell.add(trans)

    if args.out_file is not None:
        gdspy.write_gds(args.out_file,
                        unit=args.scale * 1.0e-9,
                        precision=1.0e-9)
Exemplo n.º 7
0
def corners2gds(corners, args):
    polyidx = []
    with open(args.corner_seq, 'r') as f:
        for line in f:
            line = line.strip().split(',')
            tmp = [int(x) for x in line]
            polyidx.append(tmp)
    poly_cell = gdspy.Cell('tmp')
    polyvertice = []
    for i, idx in enumerate(polyidx):
        polyvertice.append(idx2xy(corners, idx))
        # poly=gdspy.Polygon(polyvertice,1)
        # poly_cell.add(poly)
    poly = gdspy.PolygonSet(polyvertice, 1)
    # poly_cell.add(poly)
    xlength = max(corners[:, 0]) - min(corners[:, 0])
    ylength = max(corners[:, 1]) - min(corners[:, 1])
    nX = args.nX
    nY = args.nY
    xsep = max(xlength, ylength) * args.sep
    ysep = xsep
    for i in range(nX):
        for j in range(nY):
            xpos = (xlength + xsep) * (i + 1)
            ypos = (ylength + ysep) * (j + 1)
            trans = gdspy.copy(poly, xpos, ypos)
            poly_cell.add(trans)

    if args.out_file is not None:
        gdspy.write_gds(args.out_file,
                        unit=args.scale * 1.0e-9,
                        precision=1.0e-9)
Exemplo n.º 8
0
 def layer_expansion(self, shift, old_layer, new_layer, N_shifts=8):
     total = None
     polygonset = gdspy.PolygonSet(self.total_cell.get_polygons(
         (old_layer, 0)),
                                   layer=new_layer)
     for i in np.linspace(-np.pi, np.pi, N_shifts, endpoint=False):
         dx, dy = shift * np.cos(i), shift * np.sin(i)
         new_polygonset = gdspy.copy(polygonset, dx, dy)
         #total = gdspy.boolean(total, new_polygonset, 'or', layer=new_layer)
         self.total_cell.add(new_polygonset)
Exemplo n.º 9
0
def bridgeFreeJJ(conf: DefaultConfig):
    sizes = conf.bridgeFreeJJSizes
    layers = conf.bridgeFreeJJLayers
    rectangles = [myRectangle(size, layers[i]) for i, size in enumerate(sizes)]
    dy0 = (sizes[0][1] + sizes[3][1]) / 2
    dx1 = (sizes[0][0] - sizes[1][0]) / 2
    dx2 = (sizes[0][0] - sizes[2][0]) / 2
    rectangles[0].translate(0, dy0)
    rectangles[1].translate(dx1, dy0)
    rectangles[2].translate(dx2, dy0)
    rectangles[0] = cut(rectangles[0], rectangles[1])
    rectangles[1] = cut(rectangles[1], rectangles[2])
    for i in range(3):
        rectangles.append(copy(rectangles[i]).rotate(pi))
    return rectangles
Exemplo n.º 10
0
def contour2gds(contour0, args):
    # print 'contour0',contour0
    contour = [[ele[0] for ele in arr] for arr in contour0]
    # print 'contour1',contour
    if args.sharpen:
        contour = sharpenCorner(contour, args)
    # print 'contour2',contour
    flat_list = [item for sublist in contour for item in sublist]
    # print 'flat_list',flat_list
    x = [arr[0] for arr in flat_list]
    y = [arr[1] for arr in flat_list]
    # print 'x', x
    # print 'y', y
    xlength = max(x) - min(x)
    ylength = max(y) - min(y)

    maxY = max(y)
    # contour=[[[ele[0][0],maxY-ele[0][1]] for ele in arr] for arr in contour0]
    contour = [[[ele[0], maxY - ele[1]] for ele in arr] for arr in contour]

    # for sublist in contour:
    #     for ele in sublist:
    #         ele[1]=maxY-ele[1]

    poly_cell = gdspy.Cell('tmp')
    poly = gdspy.PolygonSet(contour, 1)
    # poly_cell.add(poly)
    # print 'max/min x',max(x),min(x)
    # print 'max/min y',max(y),min(y)
    # print 'length',xlength,ylength
    nX = args.nX
    nY = args.nY
    xsep = max(xlength, ylength) * args.sep
    ysep = xsep
    for i in range(nX):
        for j in range(nY):
            xpos = (xlength + xsep) * (i + 1)
            ypos = (ylength + ysep) * (j + 1)
            trans = gdspy.copy(poly, xpos, ypos)
            poly_cell.add(trans)

    if args.out_file is not None:
        gdspy.write_gds(args.out_file,
                        unit=args.scale * 1.0e-9,
                        precision=1.0e-9)
Exemplo n.º 11
0
def qubitLead(conf: DefaultConfig, test=False):
    sizes = conf.qubitLeadSizes
    if test:
        sizes[2][1] = conf.qubitTestSize
    gaps = conf.qubitLeadGaps
    layers = conf.qubitLeadLayers
    curve = gdspy.Curve(0)
    for i, size in enumerate(sizes):
        w1, h1 = size
        if i == 0:
            dx = dy = w1 / 2
            curve.c(dx, 0, dx, 0, dx, dy).v(h1 - dy)
        else:
            dx, dy = (w1 - sizes[i - 1][0]) / 2, gaps[i - 1]
            curve.c(0, dy / 2, dx, dy / 2, dx, dy).v(h1)
    curve.h(-sizes[-1][0] / 2)
    halfLead = gdspy.Polygon(curve.get_points())
    lead = join([halfLead, copy(halfLead).mirror([0, 1])])
    slice1 = sizes[0][1] + gaps[0]
    slice2 = slice1 + conf.qubitLeadOverlap
    coarseLead = gdspy.slice(lead, slice1, 1, layer=layers)[1]
    fineLead = gdspy.slice(lead, slice2, 1, layer=layers)[0]
    return coarseLead, fineLead
Exemplo n.º 12
0
def poly2gds(polyvertice, corners, args):
    f = open('auto.seq', 'w')
    epsilon = 4
    for vset in polyvertice:
        # print('vset',vset)
        seqList = []
        for v in vset:
            for i, corner in enumerate(corners):
                dist = distance(v, corner)
                if dist <= epsilon:
                    # print('dist',dist)
                    seqList.append(i)
                    continue
        f.write(','.join(str(x) for x in seqList) + '\n')
        # print('seqList',seqList)
    f.close()
    poly_cell = gdspy.Cell('tmp')
    poly = gdspy.PolygonSet(polyvertice, 1)
    # poly_cell.add(poly)
    xlength = max(corners[:, 0]) - min(corners[:, 0])
    ylength = max(corners[:, 1]) - min(corners[:, 1])
    nX = args.nX
    nY = args.nY
    xsep = max(xlength, ylength) * args.sep
    ysep = xsep
    for i in range(nX):
        for j in range(nY):
            xpos = (xlength + xsep) * (i + 1)
            ypos = (ylength + ysep) * (j + 1)
            trans = gdspy.copy(poly, xpos, ypos)
            # print poly
            poly_cell.add(trans)

    if args.out_file is not None:
        gdspy.write_gds(args.out_file,
                        unit=args.scale * 1.0e-9,
                        precision=1.0e-9)
Exemplo n.º 13
0
    [
        (0, 0),
        (-1, 0),
        (0, -1),
        (0.5, -0.5),
        (1, 0),
        (1, 1),
        (4, -1),
        (1, 3),
        (1, 2),
        (0, 1),
    ],
    [(2, -1), (3, -1), (2.5, -2)],
])
orig.datatypes = [0, 1]
p = gdspy.copy(orig, 0, 5)
p.layers = [1, 1]
p.fillet(0.3, max_points=0)
cell.add(p)
p = gdspy.copy(orig, 5, 5)
p.layers = [2, 2]
p.fillet([0.3, 0.2, 0.1, 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.4, 0.1, 0.2, 0],
         max_points=0)
cell.add(p)
p = gdspy.copy(orig, 5, 0)
p.layers = [3, 3]
p.fillet([[0.1, 0.1, 0.4, 0, 0.4, 0.1, 0.1, 0.4, 0.4, 0.1], [0.2, 0.2, 0.5]],
         max_points=0)
cell.add(p)
p = gdspy.copy(orig, 0, 0)
p.layers = [4, 4]
Exemplo n.º 14
0
 def copy(self, entity):
     new_polygon = gdspy.copy(self.gds_object_instances[entity.name], 0, 0)
     new_name = gen_name(entity.name)
     self.gds_object_instances[new_name] = new_polygon
     self.cell.add(new_polygon)
Exemplo n.º 15
0
# ------------------------------------------------------------------ #
#      Translation
# ------------------------------------------------------------------ #

trans_cell = gdspy.Cell('TRANS')

# Any geometric object can be translated by providing the distance to
# translate in the x-direction and y-direction:  translate(dx, dy)
rect1 = gdspy.Rectangle((80, 0), (81, 1), 1)
rect1.translate(2, 0)
trans_cell.add(rect1)

# Translatable objects can also be copied & translated in the same way.
rect2 = gdspy.Rectangle((80, 0), (81, 1), 2)
rect3 = gdspy.copy(rect2, 0, 3)
trans_cell.add(rect2)
trans_cell.add(rect3)

# Reference Cells are also translatable, and thus copyable.
ref1 = gdspy.CellReference(poly_cell, (25, 0), rotation=180)
ref2 = gdspy.copy(ref1, 30, 30)
trans_cell.add(ref1)
trans_cell.add(ref2)

# Same goes for Labels & Text
text1 = gdspy.Text('Created with gdspy ' + gdspy.__version__,
                   7, (-7, -35),
                   layer=6)
text2 = gdspy.copy(text1, 0, -20)
label1 = gdspy.Label('Created with gdspy ' + gdspy.__version__, (-7, -36),
Exemplo n.º 16
0
def markers_ebeam_litho(center_coords, chip_side_x, chip_side_y, factor,
                        layer_align):
    """
    Generates "crosshair" markers at the corners of each chip for alignment of the dicing saw and dots following that fo alignment of ebeam
    INPUT: array with center position of the chips, chip dimensions
    OUTPUT: dicing markers elements
    """
    elements = []

    w = 5 * factor  # width of the cross hair on the corner of a chip
    l_x = 100 * factor  # length of the cross hair
    l_y = 100 * factor

    w_d = 20 * factor  # width of ebeam alignment dots
    #    w_g = 10 # width of grid
    d_x = 300 * factor  # period of ebeam alignment dots in x and y direction
    d_y = 300 * factor

    for c in center_coords:
        #        print(c)
        #        print(type(c))
        rv = gdspy.Rectangle(
            (c[0] - chip_side_x / 2 - w / 2, c[1] + chip_side_y / 2 - l_y / 2),
            (c[0] - chip_side_x / 2 + w / 2, c[1] + chip_side_y / 2 + l_y / 2),
            layer=layer_align)
        rh = gdspy.Rectangle(
            (c[0] - chip_side_x / 2 - l_x / 2, c[1] + chip_side_y / 2 - w / 2),
            (c[0] - chip_side_x / 2 + l_x / 2, c[1] + chip_side_y / 2 + w / 2),
            layer=layer_align)
        crosshair = gdspy.boolean(
            rv, rh, 'or',
            layer=layer_align)  #making a cross hair on the edge of a chip

        # rectangle for ebeam in vertical and horizontal direction
        reh = gdspy.Rectangle((c[0] - chip_side_x / 2 - w_d / 2 -
                               (d_x + 50), c[1] + chip_side_y / 2 - w_d / 2),
                              (c[0] - chip_side_x / 2 + w_d / 2 -
                               (d_x + 50), c[1] + chip_side_y / 2 + w_d / 2),
                              layer=layer_align)
        rev = gdspy.Rectangle(
            (c[0] - chip_side_x / 2 - w_d / 2, c[1] + chip_side_y / 2 +
             (d_y + 50) - w_d / 2),
            (c[0] - chip_side_x / 2 + w_d / 2, c[1] + chip_side_y / 2 +
             (d_y + 50) + w_d / 2),
            layer=layer_align)

        # offsetting the horizontal dot to left and right
        offs_x = [0, -d_x, -2 * d_x]
        for j in offs_x:
            elements.append(gdspy.copy(reh, j, 0))

        offs_x = [2 * d_x + 100, 3 * d_x + 100, 4 * d_x + 100]
        for j in offs_x:
            elements.append(gdspy.copy(reh, j, 0))
        # offsetting the vertical dot to top and bottom
        offs_y = [0, -2 * d_y - 100, -3 * d_y - 100, -4 * d_y - 100]
        for j in offs_y:
            elements.append(gdspy.copy(rev, 0, j))

        offs_y = [d_y, 2 * d_y]
        for j in offs_y:
            elements.append(gdspy.copy(rev, 0, j))

        offs_x = [0, chip_side_x]
        offs_y = [0, -chip_side_y]
        for j in offs_x:
            for k in offs_y:
                elements.append(gdspy.copy(crosshair, j, k))

    # array of 27 x 27 square dots of 10um side
    # square ebeam marker for chips number [0,6,last-6,last] last = len(center_coords)


#    positions = [3,9]
#    for j in positions:
#        se = gdspy.Rectangle((center_coords[j][0]+2500-w_g/2,center_coords[j][1]+6000-w_g/2),(center_coords[j][0]+2500+w_g/2,center_coords[j][1]+6000+w_g/2),layer=layer_align)
#        offs_x = [-1053,-966,-880,-795,-711,-628,-546,-465,-385,-306,-228,-151,-75,0,75,151,228,306,385,465,546,628,711,795,880,966,1053]
#        offs_y = [-1053,-966,-880,-795,-711,-628,-546,-465,-385,-306,-228,-151,-75,0,75,151,228,306,385,465,546,628,711,795,880,966,1053]
#        for i in offs_x:
#            for k in offs_y:
#                elements.append(gdspy.copy(se,i,k))
#    positions = [len(center_coords)-11,len(center_coords)-5]
#    for j in positions:
#        se = gdspy.Rectangle((center_coords[j][0]+2500-w_g/2,center_coords[j][1]-6000-w_g/2),(center_coords[j][0]+2500+w_g/2,center_coords[j][1]-6000+w_g/2),layer=layer_align)
#        offs_x = [-1053,-966,-880,-795,-711,-628,-546,-465,-385,-306,-228,-151,-75,0,75,151,228,306,385,465,546,628,711,795,880,966,1053]
#        offs_y = [-1053,-966,-880,-795,-711,-628,-546,-465,-385,-306,-228,-151,-75,0,75,151,228,306,385,465,546,628,711,795,880,966,1053]
#        for i in offs_x:
#            for k in offs_y:
#                elements.append(gdspy.copy(se,i,k))

    markers = gdspy.boolean(elements,
                            None,
                            'or',
                            precision=0.001,
                            max_points=199,
                            layer=layer_align)
    return markers
Exemplo n.º 17
0
            [(input_gap * i, taper_len + bus_len)],
            width=[small_margin, small_margin],
            offset=small_margin + width,
            gdsii_path=True,
        )
        path.segment((0, 600 - bus_len - bend_radius - wg_gap * i), relative=True)
        path.turn(bend_radius, "r")
        path.segment((io_gap - 2 * bend_radius, 0), relative=True)
        path.turn(bend_radius, "l")
        path.segment((0, 300 - bend_radius + wg_gap * i), relative=True)
        c.add(path)
        dx = width / 2 + gap
        c.add(
            gdspy.boolean(
                gdspy.boolean(
                    ring_bus, gdspy.copy(ring_margin, dx, 300), "or", precision=1e-4
                ),
                gdspy.copy(ring_hole, dx, 300),
                "not",
                precision=1e-4,
            ).translate(input_gap * i, 0)
        )
    c.add(gdspy.CellArray(taper, len(ring_gaps), 1, (input_gap, 0), (0, 0)))
    c.add(
        gdspy.CellArray(
            grat, len(ring_gaps), 1, (input_gap, 0), (io_gap, 900 + taper_len)
        )
    )

    # Save to a gds file and check out the output
    lib.write_gds("photonics.gds")
Exemplo n.º 18
0
def teleportation_loop(width,
                       l1,
                       l2,
                       la=1,
                       orientation=0,
                       loop_type='mirror-symmetric',
                       reservoir_enable=False,
                       layer=10,
                       sw_enable=False,
                       sw_layer=20,
                       sw_distance=1,
                       twin_enable=True):
    """
    :param width: nanowire width
    :param l1: length of shorter (bottom) side 
    :param l2: length of slanted side
    :param la: length of protruding arms for contacts
    :param orientation: degrees. 0deg = horizontal
    :param loop_type: {'mirror-symmetric', 'center-symmetric', 'asymmetric'}
    :param reservoir_enable: not used for now
    :param layer: shapes on 1 by default
    :return: gdspy object
    """

    allowed_types = {'mirror-symmetric', 'center-symmetric', 'asymmetric'}
    if loop_type not in allowed_types:
        print('loop_type must be in ' + allowed_types)
        raise ValueError

    l2_proj_x = l2 * math.cos(math.pi / 3)
    l2_proj_y = l2 * math.sin(math.pi / 3)

    if loop_type == 'asymmetric':
        p1 = [(-l2_proj_x - la * math.cos(math.pi / 3),
               l2_proj_y + la * math.sin(math.pi / 3)), (0, 0), (l1, 0),
              (l1 + l2_proj_x, l2_proj_y)]
        p2 = [(-l2_proj_x, l2_proj_y), (l1 + l2_proj_x + la, l2_proj_y)]
    elif loop_type == 'center-symmetric':
        p1 = [(-la, 0), (l1, 0), (l1 + l2_proj_x, l2_proj_y)]
        p2 = [(0, 0), (l2_proj_x, l2_proj_y), (l2_proj_x + l1 + la, l2_proj_y)]
    else:
        p1 = [(-l2_proj_x, l2_proj_y), (0, 0), (l1, 0),
              (l1 + l2_proj_x, l2_proj_y)]
        p2 = [(-l2_proj_x - la, l2_proj_y), (l1 + l2_proj_x + la, l2_proj_y)]

    path1 = gp.FlexPath(p1, width)
    path2 = gp.FlexPath(p2, width)
    loop = gp.fast_boolean(path1, path2, 'or', layer=layer)
    if twin_enable:  # only works on mirro-symmetric types
        loop2 = gp.copy(loop)
        loop2.mirror((l1 + l2_proj_x + 1.5 * la, 0),
                     (l1 + l2_proj_x + 1.5 * la, 1))
        loop = gp.fast_boolean(loop, loop2, 'or', layer=layer)
        loop = gp.fast_boolean(
            loop,
            gp.FlexPath([(l1 + l2_proj_x + la, l2_proj_y),
                         (l1 + l2_proj_x + 3 * la, l2_proj_y)], width),
            'or',
            layer=layer)

    if reservoir_enable:
        reservoir_width = 2
        reservoir_height = 0.5
        if loop_type == 'asymmetric':
            left_coordinates = (
                -l2_proj_x -
                (la + reservoir_width / 2) * math.cos(math.pi / 3),
                l2_proj_y + (la + reservoir_width / 2) * math.sin(math.pi / 3))
            right_coordinates = (l1 + l2_proj_x + la + reservoir_width / 2,
                                 l2_proj_y)
            loop = add_reservoir_to_shape(loop,
                                          reservoir_width,
                                          reservoir_height,
                                          position=left_coordinates,
                                          rotation=-60,
                                          layer=layer)
            loop = add_reservoir_to_shape(loop,
                                          reservoir_width,
                                          reservoir_height,
                                          position=right_coordinates,
                                          layer=layer)
        elif loop_type == 'center-symmetric':
            left_coordinates = (-la - reservoir_width / 2, 0)
            right_coordinates = (l2_proj_x + l1 + la + reservoir_width / 2,
                                 l2_proj_y)
            loop = add_reservoir_to_shape(loop,
                                          reservoir_width,
                                          reservoir_height,
                                          position=left_coordinates,
                                          layer=layer)
            loop = add_reservoir_to_shape(loop,
                                          reservoir_width,
                                          reservoir_height,
                                          position=right_coordinates,
                                          layer=layer)
        else:
            left_coordinates = (-l2_proj_x - la - reservoir_width / 2,
                                l2_proj_y)
            right_coordinates = (l1 + l2_proj_x + la + reservoir_width / 2,
                                 l2_proj_y)
            loop = add_reservoir_to_shape(loop,
                                          reservoir_width,
                                          reservoir_height,
                                          position=left_coordinates,
                                          layer=layer)
            loop = add_reservoir_to_shape(loop,
                                          reservoir_width,
                                          reservoir_height,
                                          position=right_coordinates,
                                          layer=layer)

    wall_polygon = [(0, -sw_distance), (0, -sw_distance - 1),
                    (l1, -sw_distance - 1), (l1, -sw_distance),
                    (l1 + l2_proj_x + la + 2, -sw_distance)]
    wall_polygon += straight_to_zigzag_line(
        [(l1 + l2_proj_x + la + 2, -sw_distance),
         (l1 + l2_proj_x + la + 2, -sw_distance - 2),
         (-l2_proj_x - la - 2, -sw_distance - 2),
         (-l2_proj_x - la - 2, -sw_distance)], 0.3, 30)

    symmetric_wall = gp.Polygon(wall_polygon, layer=sw_layer)
    if twin_enable:
        wall2 = gp.copy(symmetric_wall)
        wall2.mirror((l1 + l2_proj_x + 1.5 * la, 0),
                     (l1 + l2_proj_x + 1.5 * la, 1))
        symmetric_wall = gp.fast_boolean(symmetric_wall,
                                         wall2,
                                         'or',
                                         layer=sw_layer)

    if sw_enable:
        return loop, symmetric_wall  # no 30deg option with SWs
    else:
        return loop.rotate(orientation * math.pi / 180)
Exemplo n.º 19
0
landing_strip_4.translate(-markOffset + mark_size, 0)
landing_strip_5.rotate(-np.pi / 4)
landing_strip_6.rotate(np.pi / 4)
landing_strip_7.rotate(-np.pi / 4)
landing_strip_8.rotate(np.pi / 4)
landing_strip_5.translate(-markOffset + mark_size, mark_size)
landing_strip_6.translate(-markOffset - mark_size, mark_size)
landing_strip_7.translate(-markOffset - mark_size, -mark_size)
landing_strip_8.translate(-markOffset + mark_size, -mark_size)

landing_strips = [
    landing_strip_1, landing_strip_2, landing_strip_3, landing_strip_4,
    landing_strip_5, landing_strip_6, landing_strip_7, landing_strip_8
]
for l in landing_strips:
    l_right = gdspy.copy(l, dx=markOffset * 2)
    l_bottom = gdspy.copy(l)
    l_bottom.layers = [2]
    l_bottom_right = gdspy.copy(l_bottom, dx=markOffset * 2)
    cell.add(l)
    cell.add(l_right)
    cell.add(l_bottom)
    cell.add(l_bottom_right)

radii = np.arange(0.5 * mm, 10 * mm, 0.1 * mm)
landing_circles = [gdspy.Round((0, 0), r, inner_radius=r - 25) for r in radii]
for l in landing_circles:
    l_right = gdspy.copy(l, dx=markOffset)
    l_left = gdspy.copy(l, dx=-markOffset)
    l_bottom_left = gdspy.copy(l_left)
    l_bottom_left.layers = [2 for x in l_bottom_left.layers]
Exemplo n.º 20
0
## ------------------------------------------------------------------ ##
##      Translation
## ------------------------------------------------------------------ ##

trans_cell = gdspy.Cell('TRANS')

## Any geometric object can be translated by providing the distance to
## translate in the x-direction and y-direction:  translate(dx, dy)
rect1 = gdspy.Rectangle( (80,0), (81,1), 1 )
rect1.translate(2, 0)
trans_cell.add(rect1)

## Translatable objects can also be copied & translated in the same way.
rect2 = gdspy.Rectangle( (80,0), (81,1), 2 )
rect3 = gdspy.copy(rect2, 0,3)
trans_cell.add(rect2)
trans_cell.add(rect3)


## Reference Cells are also translatable, and thus copyable.
ref1 = gdspy.CellReference(poly_cell, (25, 0), rotation=180)
ref2 = gdspy.copy(ref1, 30,30)
trans_cell.add(ref1)
trans_cell.add(ref2)



## Same goes for Labels & Text
text1 = gdspy.Text('Created with gsdpy ' + gdspy.__version__, 7,
                        (-7, -35), layer=6) 
# DO NOT Invert layer 2 mask
layer2Mask = gdspy.Rectangle(
    [-fieldSpacing / 2, -fieldSpacing / 2],
    [-fieldSpacing / 2 - fieldSize, -fieldSpacing / 2 - fieldSize])
layer2Cell = gdspy.boolean(layer2Mask, layer2Cell, 'and', layer=4)

# Create copy of layer 0 mask and invert it
layer3Mask = gdspy.Rectangle(
    [fieldSpacing / 2, -fieldSpacing / 2],
    [fieldSpacing / 2 + fieldSize, -fieldSpacing / 2 - fieldSize],
    layer=0)
layer3Reference = gdspy.CellReference(
    layer0Cell, (fieldSize + fieldSpacing, -fieldSize - fieldSpacing))
layer3Cell = gdspy.copy(layer0Cell,
                        dx=fieldSpacing + fieldSize,
                        dy=-fieldSpacing - fieldSize)
layer3Cell = gdspy.boolean(layer3Mask, layer3Cell, 'not', layer=4)

reticle_cell.add(layer0Cell)
reticle_cell.add(layer1Cell)
reticle_cell.add(layer2Cell)

# BARCODE AND BARCODE TEXT
barcodeCell, textCell = ASMLBarcodeGenerator.generateBarcodeAndText(
    'JEPCKMOD2')
reticle_cell.add(barcodeCell)
reticle_cell.add(textCell)

# Attempt to flip entire mask left-right (required by mla150)
flipped_library = gdspy.GdsLibrary()
Exemplo n.º 22
0
    def render(self):
        self.jj_params['x'] = self.cpw_port.position[0] + np.cos(
            self.orientation) * self.length / 2
        self.jj_params['y'] = self.cpw_port.position[1] + np.abs(np.cos(self.orientation))*self.jj_params['indent']/2 +\
                              np.abs(np.sin(self.orientation))*(np.sin(self.orientation)*self.length+self.jj_params['indent'])/2
        JJ = JJ4q.JJ_1(self.jj_params['x'], self.jj_params['y'],
                       self.jj_params['a1'], self.jj_params['a2'])
        jj = JJ.generate_jj()
        jj = gdspy.boolean(jj,
                           jj,
                           'or',
                           layer=self.layer_configuration.jj_layer)
        angle = self.jj_params['angle']
        jj.rotate(angle, (self.jj_params['x'], self.jj_params['y']))
        indent = 1  # overlap between the JJ's layer and the ground layer
        pad_up = gdspy.Rectangle(
            (self.jj_params['x'] - JJ.contact_pad_a / 2,
             self.jj_params['y'] + indent),
            (self.jj_params['x'] + JJ.contact_pad_a / 2,
             self.jj_params['y'] - JJ.contact_pad_b + indent),
            layer=self.layer_configuration.total_layer)
        pad_down = gdspy.Rectangle(
            (JJ.x_end - JJ.contact_pad_a / 2, JJ.y_end - 1),
            (JJ.x_end + JJ.contact_pad_a / 2,
             JJ.y_end - JJ.contact_pad_b - indent),
            layer=self.layer_configuration.total_layer)

        if np.round(np.sin(self.orientation),
                    3) == 0:  # for horizontal based couplers
            poly1 = gdspy.Polygon(
                [(self.jj_params['x'] - JJ.contact_pad_a / 2,
                  self.jj_params['y'] + indent),
                 (self.jj_params['x'] - JJ.contact_pad_a / 2,
                  self.jj_params['y'] + indent - JJ.contact_pad_b),
                 (self.jj_params['x'] - 3 * JJ.contact_pad_a / 2,
                  self.cpw_port.position[1] - self.w / 2),
                 (self.jj_params['x'] - self.length / 2,
                  self.cpw_port.position[1] - self.w / 2),
                 (self.jj_params['x'] - self.length / 2,
                  self.cpw_port.position[1] + self.w / 2),
                 (self.jj_params['x'] - 3 * JJ.contact_pad_a / 2,
                  self.cpw_port.position[1] + self.w / 2)],
                layer=self.layer_configuration.total_layer)
            poly2 = gdspy.Polygon(
                [(JJ.x_end + JJ.contact_pad_a / 2,
                  JJ.y_end - indent - JJ.contact_pad_b),
                 (JJ.x_end + JJ.contact_pad_a / 2, JJ.y_end - indent),
                 (JJ.x_end + 3 * JJ.contact_pad_a / 2,
                  self.cpw_port.position[1] + self.w / 2),
                 (JJ.x_end + self.length / 2,
                  self.cpw_port.position[1] + self.w / 2),
                 (JJ.x_end + self.length / 2,
                  self.cpw_port.position[1] - self.w / 2),
                 (JJ.x_end + 3 * JJ.contact_pad_a / 2,
                  self.cpw_port.position[1] - self.w / 2)],
                layer=self.layer_configuration.total_layer)
        elif np.round(np.cos(self.orientation), 3) == 0:
            poly1 = gdspy.Rectangle(
                (self.jj_params['x'] - self.w / 2, self.jj_params['y']),
                (self.jj_params['x'] + self.w / 2, self.jj_params['y'] +
                 (self.length - self.jj_params['indent']) / 2),
                layer=self.layer_configuration.total_layer)
            poly2 = gdspy.Rectangle(
                (JJ.x_end + self.w / 2, JJ.y_end - JJ.contact_pad_b),
                (JJ.x_end - self.w / 2, JJ.y_end - JJ.contact_pad_b -
                 (self.length - self.jj_params['indent']) / 2 - indent),
                layer=self.layer_configuration.total_layer)

        ground_x1 = self.cpw_port.position[0] + np.sin(
            self.orientation) * (self.w / 2 + self.g + self.s)
        ground_y1 = self.cpw_port.position[1] + np.cos(
            self.orientation) * (self.w / 2 + self.g + self.s)
        ground_x2 = self.cpw_port.position[0]+np.sin(self.orientation)*(self.w/2+self.s) +\
            np.cos(self.orientation)*self.length
        ground_y2 = self.cpw_port.position[1] + np.cos(self.orientation) * (self.w /2 + self.s) + \
             np.sin(self.orientation) * self.length
        ground1 = gdspy.Rectangle((ground_x1, ground_y1),
                                  (ground_x2, ground_y2),
                                  layer=self.layer_configuration.total_layer)
        ground2 = gdspy.copy(ground1)
        ground2 = ground2.mirror(
            (self.cpw_port.position[0], self.cpw_port.position[1]),
            (self.cpw_port.position[0] +
             np.cos(self.orientation) * self.length,
             self.cpw_port.position[1] +
             np.sin(self.orientation) * self.length))

        line = gdspy.boolean(pad_up,
                             [pad_down, poly1, poly2, ground1, ground2],
                             'or',
                             layer=self.layer_configuration.total_layer)
        line.rotate(angle, (self.jj_params['x'], self.jj_params['y']))
        return {'positive': line, 'JJ': jj}
Exemplo n.º 23
0
def main():

    # load file
    comsol_filename = "fourQ_test_pattern_cell_divide.java"
    parser = cp.comsol_parser()
    parser.load(comsol_filename)
    
    # show info
    #parser.ls_g_params()
    #parser.ls_geom()
    #parser.ls_objs("wp2")

    # change_paramter
    ## parser.g_params['read_D_pad'] = '0.660[mm]'

    # change geometric object
    parser.activate_geom_obj('wp2', ['c15', 'c16', 'c18', 'c17'], False)  # c15-18: positioning via
    parser.activate_geom_obj('wp2', ['c8'], False)  # c8: center via
    #print (parser.get_geom_obj('wp2', 'c15').__dict__)


    ## TiN pattern
    dry_etch_layer = 11
    cell_qc = gdspy.Cell('Qubit_Coplanar')
    poly_q = parser.export('wp1', layer=11, n_points_for_circle=256)
    poly_c = parser.export('wp5', layer=11, n_points_for_circle=128)
    poly_qc = gdspy.boolean(poly_q, poly_c, 'or', max_points=0, layer=dry_etch_layer)  ## disable max_points check


    ## JJ
    cell_JJ = gdspy.Cell('JJ')
    JJ_polys = generate_JJ()
    cell_JJ.add(JJ_polys)

    q_r_outer_hole = 300
    q_r_inner = 95
    q_gap = q_r_inner + (q_r_outer_hole - q_r_inner)/2
    q_dist = 2400

    p_JJ0 = (-q_dist/2+q_gap/np.sqrt(2), q_dist/2-q_gap/np.sqrt(2))
    p_JJ1 = (q_dist/2-q_gap/np.sqrt(2), q_dist/2-q_gap/np.sqrt(2))
    p_JJ2 = (-q_dist/2+q_gap/np.sqrt(2), -q_dist/2+q_gap/np.sqrt(2))
    p_JJ3 = (q_dist/2-q_gap/np.sqrt(2), -q_dist/2+q_gap/np.sqrt(2))
    p_JJ_list = [p_JJ0, p_JJ1, p_JJ2, p_JJ3]

    JJ_list = map(lambda x: gdspy.CellReference(cell_JJ, x), p_JJ_list)
    cell_qc.add(JJ_list)
    

    ## hook for JJ
    gap_for_JJ = 90/np.sqrt(2)
    hook_path_base = gdspy.FlexPath([(0, 0), (0, -4.5), (-3.5, -4.5)], 3, layer=dry_etch_layer)
    hook_path_base.translate(5, gap_for_JJ/2)

    hook_path_list = map(lambda x: gdspy.copy(hook_path_base).translate(*x), p_JJ_list)
    hook_path_union = None
    for path in hook_path_list:
        hook_path_union = gdspy.boolean(hook_path_union, path, 'or', max_points=0, layer=dry_etch_layer)

    #poly_qc_hook = gdspy.boolean(poly_qc, hook_path_union, 'not', max_points=0, layer=dry_etch_layer)
    #cell_qc.add(poly_qc_hook)
    cell_qc.add(hook_path_union)
    cell_qc.add(poly_c)
    cell_qc.add(poly_q)


   ## mask
    mask_layer = 100

    shift = 20

    cell_mask_shifted = gdspy.Cell('Shifted Pattern Mask')

    polyset_shifted = cp.gdspy_shift_size(poly_qc, shift ,layer=mask_layer)
    unit_size = 4000

    rect_fill_lr = gdspy.Path(150, (-unit_size/2, 0))
    rect_fill_lr.segment(unit_size, '+x', layer=mask_layer)
    rect_fill_bt = gdspy.Path(150, (0, -unit_size/2))
    rect_fill_bt.segment(unit_size, '+y', layer=mask_layer)

    rect_list = [gdspy.copy(rect_fill_lr).translate(0, -q_dist/2), gdspy.copy(rect_fill_lr).translate(0, q_dist/2),
                 gdspy.copy(rect_fill_bt).translate(-q_dist/2, 0), gdspy.copy(rect_fill_bt).translate(q_dist/2, 0)]

    rect_union = None
    for rect in rect_list:
        rect_union = gdspy.boolean(rect_union, rect, 'or', max_points=0, layer=mask_layer)

    mask_shifted = gdspy.boolean(polyset_shifted, rect_union, 'or', max_points=0, layer=mask_layer)

    cell_mask_shifted.add(mask_shifted)


    ## Via
    via_layer = 13
    top_Al_layer = 8
    bottom_Al_layer = 9

    cell_via = gdspy.Cell('Via')
    via_poly = parser.export('wp2', layer=via_layer)
    via_poly_Al_t = cp.gdspy_shift_size(via_poly, 35, layer=top_Al_layer)
    via_poly_Al_b = cp.gdspy_shift_size(via_poly, 20, layer=bottom_Al_layer)

    via_poly_Al_t = gdspy.boolean(via_poly_Al_t, mask_shifted, 'not', layer=top_Al_layer)   ## mask the top pattern

    cell_via.add([via_poly, via_poly_Al_t, via_poly_Al_b])

    ### center via
    center_via = gdspy.Round((0, 0), 75, layer=via_layer)
    center_via_Al_t = gdspy.Round((0, 0), 95, layer=top_Al_layer)
    center_via_Al_b = gdspy.Round((0, 0), 95, layer=bottom_Al_layer)
    cell_via.add([center_via, center_via_Al_t, center_via_Al_b])

    ### positioning via
    pos_via_dist = 7400
    pos_via_lt = gdspy.Round((-pos_via_dist/2, pos_via_dist/2), 520, layer=via_layer)
    pos_via_lt_Al_t = gdspy.Round((-pos_via_dist/2, pos_via_dist/2), 620, layer=top_Al_layer)
    pos_via_lt_Al_b = gdspy.Round((-pos_via_dist/2, pos_via_dist/2), 600, layer=bottom_Al_layer)
    pos_via_rb = gdspy.Round((pos_via_dist/2, -pos_via_dist/2), 520, layer=via_layer)
    pos_via_rb_Al_t = gdspy.Round((pos_via_dist/2, -pos_via_dist/2), 620, layer=top_Al_layer)
    pos_via_rb_Al_b = gdspy.Round((pos_via_dist/2, -pos_via_dist/2), 600, layer=bottom_Al_layer)
    cell_via.add([pos_via_lt, pos_via_lt_Al_t, pos_via_lt_Al_b, pos_via_rb, pos_via_rb_Al_t, pos_via_rb_Al_b])

    ### tiling Via
    cell_single_via = gdspy.Cell('single_via')
    via_s = gdspy.Round((0, 0), 75, layer=via_layer)
    via_s_Al_t = gdspy.Round((0, 0), 110, layer=top_Al_layer)
    via_s_Al_b = gdspy.Round((0, 0), 95, layer=bottom_Al_layer)
    cell_single_via.add([via_s, via_s_Al_t, via_s_Al_b])

    tiled_via_list = tile_cell(cell_single_via, (-4500, -4500), (4500, 4500), 500)

    cell_mask_via = gdspy.Cell('Via Mask')

    rect_mask_lr = gdspy.Rectangle((-2300, -400), (2300, 400), layer=mask_layer)
    rect_mask_bt = gdspy.Rectangle((-400, -2300), (400, 2300), layer=mask_layer)
    rect_mask_c =  gdspy.Rectangle((-1200, -1200), (1200, 1200), layer=mask_layer)
    rect_mask_lr1 = gdspy.copy(rect_mask_lr).translate(0, -1200)
    rect_mask_lr2 = gdspy.copy(rect_mask_lr).translate(0, 1200)
    rect_mask_bt1 = gdspy.copy(rect_mask_bt).translate(-1200, 0)
    rect_mask_bt2 = gdspy.copy(rect_mask_bt).translate(1200, 0)
    pos_via_mask_lt = gdspy.Round((-pos_via_dist/2, pos_via_dist/2), 600, layer=mask_layer)
    pos_via_mask_br = gdspy.Round((pos_via_dist/2, -pos_via_dist/2), 600, layer=mask_layer)

    cell_mask_via.add([rect_mask_lr1, rect_mask_lr2, rect_mask_bt1, rect_mask_bt2, rect_mask_c, pos_via_mask_lt, pos_via_mask_br])

    for via_ref in tiled_via_list:
        if np.any(gdspy.inside([via_ref.origin], cell_mask_via.polygons)):
            pass
        else:
            cell_via.add(via_ref)

 
    generate_flux_trap = False

    if generate_flux_trap:
        # Flux trap
        cell_single_flux_trap = gdspy.Cell('single_flux_trap')

        trap_size = np.array([5, 5])
        cell_single_flux_trap.add(gdspy.Rectangle(-trap_size/2, trap_size/2, layer=dry_etch_layer))

        cell_flux_trap = gdspy.Cell('Flux trap')
        flux_trap_list = tile_cell(cell_single_flux_trap, (-2500, -2500), (2500, 2500), 20)

        cell_mask_flux_trap = gdspy.Cell("Mask for flux trap")

        mask_flux_trap_on_via = cp.gdspy_shift_size(via_poly, 40, layer=mask_layer)
        mask_pos_via_lt = gdspy.Round((-pos_via_dist/2, pos_via_dist/2), 630, layer=mask_layer)
        mask_pos_via_rb = gdspy.Round((pos_via_dist/2, -pos_via_dist/2), 630, layer=mask_layer)
        cell_mask_flux_trap.add([mask_shifted, mask_flux_trap_on_via, mask_pos_via_lt, mask_pos_via_rb])


        ###
        for flux_trap_ref in flux_trap_list:
            if np.any(gdspy.inside([flux_trap_ref.origin], cell_mask_flux_trap.polygons)):
                pass
            else:
                cell_flux_trap.add(flux_trap_ref)


    # Top
    total_cell = gdspy.Cell('4Q total pattern')
    total_cell.add(gdspy.CellReference(cell_qc))
    total_cell.add(gdspy.CellReference(cell_via))

    if generate_flux_trap:
        total_cell.add(gdspy.CellReference(cell_flux_trap))

    #gdspy.LayoutViewer()

    gdspy.write_gds("4Q_pattern.gds", unit=1.0e-6, precision=1.0e-9)

    return 0
Exemplo n.º 24
0
    def gdsgen_part(self,
                    part_id,
                    layer=1,
                    dbu=0.001,
                    n_points_for_circle=128,
                    input_params={}):
        ##
        if isinstance(n_points_for_circle, float):
            n_points_for_circle = int(n_points_for_circle / dbu)
        ##

        export_obj_ids = []
        export_kl_obj_ids = []
        gds_objs = {}
        kl_objs = {}
        skipped_obj_ids = []

        if part_id in self.two_dim_part_dict:
            part = self.two_dim_part_dict[part_id]
            is_wp = False
        elif part_id in self.two_dim_wp_dict:
            part = self.two_dim_wp_dict[part_id]
            is_wp = True
        else:
            raise Exception('Could not find the corresponding parts or wp.')

        eval_g_params = func_dict.copy()
        eval_g_params.update(self.g_params_evaluated)
        if_skip_flag = False

        for obj_id in part.obj_order:
            local_params = None
            obj = part.objs[obj_id]
            if input_params:
                local_params = part.get_local_params(input_params)
                local_params.update(input_params)
            else:
                local_params = part.get_local_params()
                local_params.update(part.input_params)

            obj.eval_params(eval_g_params, local_params)

            if obj.is_active == False:
                pass

            elif obj.type == 'EndIf':
                if_skip_flag = False

            elif if_skip_flag == True:
                skipped_obj_ids.append(obj.id)

            elif obj.type == 'If':
                if obj.params_evaluated['condition'] == False:
                    if_skip_flag = True
                else:
                    if_skip_flag = False

            elif obj.type == 'Circle':
                r = obj.params_evaluated['r']
                angle_i = 0.
                angle_f = 2 * np.pi
                r_i = 0.

                if 'angle' in obj.params_evaluated:
                    angle_f = obj.params_evaluated['angle'] * np.pi / 180.0

                if 'layer' in obj.params_evaluated:
                    if len(obj.params_evaluated['layer']) > 1:
                        print(
                            'Warning: Circle with more than 1 layer is not supported ({}).'
                            .format(obj.id),
                            file=sys.stderr)
                    r_i = r - obj.params_evaluated['layer'][0]

                gds_obj = gdspy.Round((0, 0),
                                      r,
                                      initial_angle=angle_i,
                                      final_angle=angle_f,
                                      inner_radius=r_i,
                                      number_of_points=n_points_for_circle,
                                      layer=layer)
                if 'rot' in obj.params_evaluated:
                    gds_obj.rotate(obj.params_evaluated['rot'] * np.pi / 180.0)
                if 'pos' in obj.params_evaluated:
                    gds_obj.translate(*obj.params_evaluated['pos'])
                gds_objs[obj_id] = gds_obj
                export_obj_ids.append(obj_id)

            elif obj.type == 'Rectangle':
                size = np.array(obj.params_evaluated['size'])
                if 'base' in obj.params_evaluated and obj.params_evaluated[
                        'base'] == 'center':
                    gds_obj = gdspy.Rectangle(-size / 2.0,
                                              size / 2.0,
                                              layer=layer)
                else:
                    gds_obj = gdspy.Rectangle((0, 0), size, layer=layer)
                if 'rot' in obj.params_evaluated:
                    gds_obj.rotate(obj.params_evaluated['rot'] * np.pi / 180.0)
                if 'pos' in obj.params_evaluated:
                    gds_obj.translate(*obj.params_evaluated['pos'])
                gds_objs[obj_id] = gds_obj
                export_obj_ids.append(obj_id)

            elif obj.type == 'Polygon':
                if 'source' in obj.params_evaluated:
                    if obj.params_evaluated['source'] == 'table':
                        gds_obj = gdspy.Polygon(obj.params_evaluated['table'],
                                                layer=layer)
                        gds_objs[obj_id] = gds_obj
                        export_obj_ids.append(obj_id)
                    else:
                        print('Unsupported source ({0}) in {1}'.format(
                            params_evaluated['source'],
                            obj.id,
                            file=sys.stderr))
                else:
                    print('Source not specified in {}'.format(obj.id),
                          file=sys.stderr)

            elif obj.type == 'Union':
                sel = obj.selections['input']
                union_list = []

                for sel_obj_id_org in sel:
                    if sel_obj_id_org in skipped_obj_ids:
                        sel_obj_id = part.objs[sel_obj_id_org].selections[
                            'input'][0]
                    else:
                        sel_obj_id = sel_obj_id_org

                    union_list.append(sel_obj_id)

                    if sel_obj_id in export_obj_ids:
                        export_obj_ids.remove(sel_obj_id)

                if union_list:
                    union_obj = None
                    for sel_obj_id in union_list:
                        union_obj = gdspy.boolean(union_obj,
                                                  gds_objs[sel_obj_id],
                                                  'or',
                                                  precision=dbu,
                                                  layer=layer)
                    gds_objs[obj_id] = union_obj
                    export_obj_ids.append(obj_id)

            ### from here
            elif obj.type == 'Difference':
                selA = obj.selections['input']
                selB = obj.selections['input2']

                objA_list = []
                objB_list = []

                for sel_obj_id_org in selA:
                    if sel_obj_id_org in skipped_obj_ids:
                        sel_obj_id = part.objs[sel_obj_id_org].selections[
                            'input'][0]
                    else:
                        sel_obj_id = sel_obj_id_org

                    objA_list.append(sel_obj_id)

                    if sel_obj_id in export_obj_ids:
                        export_obj_ids.remove(sel_obj_id)

                for sel_obj_id_org in selB:
                    if sel_obj_id_org in skipped_obj_ids:
                        sel_obj_id = part.objs[sel_obj_id_org].selections[
                            'input'][0]
                    else:
                        sel_obj_id = sel_obj_id_org

                    objB_list.append(sel_obj_id)

                    if sel_obj_id in export_obj_ids:
                        export_obj_ids.remove(sel_obj_id)

                if objA_list:
                    objA = None
                    for sel_obj_id in objA_list:
                        objA = gdspy.boolean(objA,
                                             gds_objs[sel_obj_id],
                                             'or',
                                             precision=dbu,
                                             layer=layer)
                if objB_list:
                    objB = None
                    for sel_obj_id in objB_list:
                        objB = gdspy.boolean(objB,
                                             gds_objs[sel_obj_id],
                                             'or',
                                             precision=dbu,
                                             layer=layer)

                diff_obj = gdspy.boolean(objA,
                                         objB,
                                         'not',
                                         precision=dbu,
                                         layer=layer)
                gds_objs[obj_id] = diff_obj
                export_obj_ids.append(obj_id)

            elif obj.type == 'Move':
                if 'displx' in obj.params_evaluated:
                    displx = obj.params_evaluated['displx']
                else:
                    displx = 0
                if 'disply' in obj.params_evaluated:
                    disply = obj.params_evaluated['disply']
                else:
                    disply = 0
                sel = obj.selections['input']

                # for single slection
                if len(sel) > 1:
                    print(
                        'Warning: {} of more than 1 object is not supported.'.
                        format(obj.type),
                        file=sys.stderr)
                sel_obj_id_org = sel[0]
                if sel_obj_id_org in skipped_obj_ids:
                    sel_obj_id = part.objs[sel_obj_id_org].selections['input'][
                        0]
                else:
                    sel_obj_id = sel_obj_id_org

                sel_obj = gds_objs[sel_obj_id]
                move_obj = gdspy.copy(sel_obj, displx, disply)
                gds_objs[obj_id] = move_obj
                export_obj_ids.append(obj_id)
                if 'keep' in obj.params_evaluated and obj.params_evaluated[
                        'keep'] == True:
                    pass
                elif sel_obj_id in export_obj_ids:
                    export_obj_ids.remove(sel_obj_id)

            elif obj.type == 'Mirror':
                if 'pos' in obj.params_evaluated:
                    pos = np.array(obj.params_evaluated['pos'])
                else:
                    pos = np.array([0., 0.])

                if 'axis' in obj.params_evaluated:
                    axis = np.array(obj.params_evaluated['axis'])
                else:
                    axis = np.array([1., 0.])

                sel = obj.selections['input']

                # for single selection
                if len(sel) > 1:
                    print(
                        'Warning: {} of more than 1 object is not supported.'.
                        format(obj.type),
                        file=sys.stderr)
                sel_obj_id_org = sel[0]
                if sel_obj_id_org in skipped_obj_ids:
                    sel_obj_id = part.objs[sel_obj_id_org].selections['input'][
                        0]
                else:
                    sel_obj_id = sel_obj_id_org

                sel_obj = gds_objs[sel_obj_id]
                mirror_obj = gdspy.copy(sel_obj).mirror(
                    pos, pos + np.array([-axis[1], axis[0]]))
                gds_objs[obj_id] = mirror_obj
                export_obj_ids.append(obj_id)
                if 'keep' in obj.params_evaluated and obj.params_evaluated[
                        'keep'] == True:
                    pass
                elif sel_obj_id in export_obj_ids:
                    export_obj_ids.remove(sel_obj_id)

            elif obj.type == 'Rotate':
                if 'rot' in obj.params_evaluated:
                    if isinstance(
                            obj.params_evaluated['rot'],
                        (list, tuple,
                         np.ndarray)):  # can be ndarray when use range
                        rot = np.array(
                            obj.params_evaluated['rot']
                        ) * np.pi / 180  # rot can be the list of angle
                    else:
                        rot = np.array([obj.params_evaluated['rot']
                                        ]) * np.pi / 180
                else:
                    rot = np.array([0.])

                if 'pos' in obj.params_evaluated:
                    pos = np.round(np.array(obj.params_evaluated['pos']))
                else:
                    pos = np.array([0., 0.])

                sel = obj.selections['input']
                if len(sel) > 1:
                    print(
                        'Warning: {} of more than 1 object is not supported.'.
                        format(obj.type),
                        file=sys.stderr)
                sel_obj_id_org = sel[0]
                if sel_obj_id_org in skipped_obj_ids:
                    sel_obj_id = part.objs[sel_obj_id_org].selections['input'][
                        0]
                else:
                    sel_obj_id = sel_obj_id_org

                sel_obj = gds_objs[sel_obj_id]
                rot_obj = gdspy.copy(sel_obj).rotate(rot[0], center=pos)

                for angle in rot[1:]:
                    rot_obj = gdspy.boolean(rot_obj,
                                            gdspy.copy(sel_obj).rotate(
                                                angle, center=pos),
                                            'or',
                                            precision=dbu,
                                            layer=layer)

                gds_objs[obj_id] = rot_obj
                export_obj_ids.append(obj_id)
                if 'keep' in obj.params_evaluated and obj.params_evaluated[
                        'keep'] == True:
                    pass
                elif sel_obj_id in export_obj_ids:
                    export_obj_ids.remove(sel_obj_id)

            elif obj.type == 'Array':
                if 'type' in obj.params_evaluated and obj.params_evaluated[
                        'type'] == 'linear':
                    linearsize = obj.params_evaluated['linearsize']
                    displ = np.array(obj.params_evaluated['displ'])
                    sel = obj.selections['input']
                    if len(sel) > 1:
                        print(
                            'Warning: {} of more than 1 object is not supported.'
                            .format(obj.type),
                            file=sys.stderr)
                    sel_obj_id_org = sel[0]
                    if sel_obj_id_org in skipped_obj_ids:
                        sel_obj_id = part.objs[sel_obj_id_org].selections[
                            'input'][0]
                    else:
                        sel_obj_id = sel_obj_id_org

                    sel_obj = gds_objs[sel_obj_id]
                    arr_obj = gdspy.copy(sel_obj)

                    for i in range(1, int(linearsize)):
                        displ_i = displ * i
                        arr_obj = gdspy.boolean(
                            arr_obj,
                            gdspy.copy(sel_obj).translate(*displ_i),
                            'or',
                            precision=dbu,
                            layer=layer)

                    if sel_obj_id in export_obj_ids:
                        export_obj_ids.remove(sel_obj_id)
                    gds_objs[obj_id] = arr_obj
                    export_obj_ids.append(obj_id)
                else:
                    fullsize = obj.params_evaluated['fullsize']
                    displ = np.array(obj.params_evaluated['displ'])
                    sel = obj.selections['input']
                    if len(sel) > 1:
                        print(
                            'Warning: {} of more than 1 object is not supported.'
                            .format(obj.type),
                            file=sys.stderr)
                    sel_obj_id_org = sel[0]
                    if sel_obj_id_org in skipped_obj_ids:
                        sel_obj_id = part.objs[sel_obj_id_org].selections[
                            'input'][0]
                    else:
                        sel_obj_id = sel_obj_id_org

                    sel_obj = gds_objs[sel_obj_id]
                    arr_obj = gdspy.copy(sel_obj)

                    for i in range(int(fullsize[0])):
                        for j in range(int(fullsize[1])):
                            if (i, j) is (0, 0):
                                continue
                            displ_ij = np.array([i, j]) * displ
                            arr_obj = gdspy.boolean(
                                arr_obj,
                                gdspy.copy(sel_obj).translate(*displ_ij),
                                'or',
                                precision=dbu,
                                layer=layer)

                    if sel_obj_id in export_obj_ids:
                        export_obj_ids.remove(sel_obj_id)
                    gds_objs[obj_id] = arr_obj
                    export_obj_ids.append(obj_id)

            elif obj.type == 'PartInstance':
                if 'part' in obj.params_evaluated:
                    pi_part_id = obj.params_evaluated['part']
                else:
                    if is_wp == True:
                        pi_part_id = self.default_part_id_wp
                    else:
                        pi_part_id = self.default_part_id

                if isinstance(obj.params_evaluated['inputexpr'][0],
                              list):  # 3.5a
                    pi_params = dict(obj.params_evaluated['inputexpr'])
                else:
                    pi_param_keys = self.two_dim_part_dict[
                        pi_part_id].input_param_names
                    pi_param_vals = obj.params_evaluated['inputexpr']
                    pi_params = dict(zip(pi_param_keys, pi_param_vals))

                pi_objs, pi_export_obj_ids = self.gdsgen_part(
                    pi_part_id,
                    layer=layer,
                    dbu=dbu,
                    n_points_for_circle=n_points_for_circle,
                    input_params=pi_params)

                if len(pi_export_obj_ids) > 1:
                    print(
                        'Warning: PartInstance with more than 1 final objects is not supported ({}).'
                        .format(pi_part_id),
                        file=sys.stderr)
                    print(
                        '         Take union in the definition of Geometry Parts',
                        file=sys.stderr)

                pi_obj = pi_objs[pi_export_obj_ids[0]]
                if 'rot' in obj.params_evaluated:
                    angle = obj.params_evaluated['rot'] * np.pi / 180
                    pi_obj = pi_obj.rotate(angle)
                if 'displ' in obj.params_evaluated:
                    displ = np.array(obj.params_evaluated['displ'])
                    pi_obj = pi_obj.translate(*displ)
                gds_objs[obj_id] = pi_obj
                export_obj_ids.append(obj_id)

            else:
                print('Warning: object({}) was skipped.'.format(obj_id),
                      file=sys.stderr)

        return (gds_objs, export_obj_ids)
Exemplo n.º 25
0
def loop_with_sw(width,
                 l1,
                 l2,
                 d1,
                 d2,
                 la=1,
                 loop_type='high-angle-60deg',
                 layer=10,
                 sw_layer=20,
                 twin_enable=True):
    """
    The above function got too complicated so started a separate loop generating function for those with smart walls
    :param width: nanowire width
    :param l1: length of shorter (bottom) side 
    :param l2: length of slanted side
    :param d1: distance between top arm and the two side SWs
    :param d2: distance between top arm and the island boundary
    :param la: length of protruding arms for contacts. Check the geometries again if you change this value to anything but the default 1um.
    :param loop_type: {'high-angle', 'grazing-angle'}
    :param layer: shapes on 10 by default
    :param sw_layer: SWs on 20 by default
    :param twin_enable: mirror the structure overall and connect with a 3um segment in the middle
    :return: two gdspy objects: first one containing the wire, the second the SWs
    """

    allowed_types = {
        'high-angle-symmetric', 'high-angle-60deg', 'high-angle-90deg',
        'grazing-angle'
    }
    if loop_type not in allowed_types:
        print('loop_type must be in ' + allowed_types)
        raise ValueError

    # convenience variables
    if loop_type == 'high-angle-90deg':
        l2_proj_x = 0
        l2_proj_y = l2
        island_boundary_horizontal_offset = 0.2
        # islands need to stay inside arm and some distance away from the joints. This is automatically guaranteed in 60deg configurations
    else:
        l2_proj_x = l2 * math.cos(math.pi / 3)
        l2_proj_y = l2 * math.sin(math.pi / 3)
        island_boundary_horizontal_offset = 0.1

    # drawing a unit loop
    if loop_type == 'high-angle-60deg':  # this one is special: only twinned structures for now
        la_proj_x = la * math.cos(math.pi / 3)
        la_proj_y = la * math.sin(math.pi / 3)
        ld = 5  # distance between two units
        p1 = [(l2_proj_x + la_proj_x, l2_proj_y + la_proj_y), (0, 0), (l1, 0),
              (l1 + l2_proj_x, l2_proj_y)]
        p2 = [(l1 + l2_proj_x + ld, l2_proj_y), (l1 + ld, 0), (2 * l1 + ld, 0),
              (2 * l1 + l2_proj_x + ld + la_proj_x, l2_proj_y + la_proj_y)]
        p3 = [(l2_proj_x, l2_proj_y), (2 * l1 + l2_proj_x + ld, l2_proj_y)]
        path1 = gp.FlexPath(p1, width)
        path2 = gp.FlexPath(p2, width)
        path3 = gp.FlexPath(p3, width)
        loop = gp.boolean(gp.boolean(path1, path2, 'or', layer=layer),
                          path3,
                          'or',
                          layer=layer)
    else:  # 'high-angle-symmetric', 'high-angle-90deg', 'grazing-angle'
        p1 = [(-l2_proj_x, l2_proj_y), (0, 0), (l1, 0),
              (l1 + l2_proj_x, l2_proj_y)]
        p2 = [(-l2_proj_x - la, l2_proj_y), (l1 + l2_proj_x + la, l2_proj_y)]
        path1 = gp.FlexPath(p1, width)
        path2 = gp.FlexPath(p2, width)
        loop = gp.boolean(path1, path2, 'or', layer=layer)

    # attach smart walls
    if loop_type in {'high-angle-symmetric', 'high-angle-90deg'}:
        left_wall = [(-1, l2_proj_y - d2), (0, l2_proj_y - d2),
                     (-math.cos(math.pi / 6), l2_proj_y - d2 - 0.8)]
        left_wall += straight_to_zigzag_line(
            [(-math.cos(math.pi / 6), l2_proj_y - d2 - 0.8),
             (-3, l2_proj_y - d2 - 0.8), (-3, l2_proj_y - d2),
             (-1, l2_proj_y - d2)], 0.2, 30)
        left_wall = gp.Polygon(left_wall, layer=sw_layer)
        left_wall.translate(island_boundary_horizontal_offset, 0)

        right_wall = [(-1, l2_proj_y - d2), (0, l2_proj_y - d2),
                      (-math.cos(math.pi / 6), l2_proj_y - d2 - 0.8)]
        right_wall += straight_to_zigzag_line(
            [(-math.cos(math.pi / 6), l2_proj_y - d2 - 0.8),
             (-2, l2_proj_y - d2 - 0.8), (-2, l2_proj_y - d2),
             (-1, l2_proj_y - d2)], 0.2, 30)
        right_wall = gp.Polygon(right_wall, layer=sw_layer)
        right_wall.mirror((l1 / 2, 0), (l1 / 2, 1))
        right_wall.translate(-island_boundary_horizontal_offset, 0)

        middel_wall = gp.Polygon(
            [(-0.2 + island_boundary_horizontal_offset, l2_proj_y - d1),
             (l1 + 0.2 - island_boundary_horizontal_offset, l2_proj_y - d1),
             (l1 + 1, l2_proj_y - d1 - 1), (-1, l2_proj_y - d1 - 1)],
            layer=sw_layer)

        symmetric_wall = gp.boolean(left_wall,
                                    right_wall,
                                    'or',
                                    layer=sw_layer)
        symmetric_wall = gp.boolean(symmetric_wall,
                                    middel_wall,
                                    'or',
                                    layer=sw_layer)
    elif loop_type == 'high-angle-60deg':
        left_wall = [(2 * l2_proj_x - 0.5, l2_proj_y - d2),
                     (2 * l2_proj_x, l2_proj_y - d2),
                     (2 * l2_proj_x - 0.5, l2_proj_y - d2 - 0.5)]
        left_wall += straight_to_zigzag_line(
            [(2 * l2_proj_x - 0.5, l2_proj_y - d2), (-2, l2_proj_y - d2),
             (-2, l2_proj_y - d2 - 1),
             (2 * l2_proj_x - 0.5, l2_proj_y - d2 - 0.5)], 0.2, 30)
        left_wall = gp.Polygon(left_wall, layer=sw_layer)

        right_wall = [(l1 + 0.5, l2_proj_y - d2), (l1, l2_proj_y - d2),
                      (l1 + 0.5, l2_proj_y - d2 - 0.5)]
        right_wall += straight_to_zigzag_line(
            [(l1 + 0.5, l2_proj_y - d2),
             (l1 - 2 * l2_proj_x + 2.5, l2_proj_y - d2),
             (l1 - 2 * l2_proj_x + 2, l2_proj_y - d2 - 1),
             (l1 + 0.5, l2_proj_y - d2 - 0.5)], 0.2, 30)
        right_wall = gp.Polygon(right_wall, layer=sw_layer)

        middel_wall = gp.Polygon(
            [(2 * l2_proj_x - 0.2, l2_proj_y - d1), (l1 + 0.2, l2_proj_y - d1),
             (l1 + 1.5, l2_proj_y - d1 - 3**0.5),
             (2 * l2_proj_x - 1.5, l2_proj_y - d1 - 3**0.5)],
            layer=sw_layer)

        symmetric_wall = gp.boolean(left_wall,
                                    right_wall,
                                    'or',
                                    layer=sw_layer)
        symmetric_wall = gp.boolean(symmetric_wall,
                                    middel_wall,
                                    'or',
                                    layer=sw_layer)

        twin_wall = gp.copy(symmetric_wall)
        twin_wall.mirror((l2_proj_x + l1 + 0.5 * ld, 0),
                         (l2_proj_x + l1 + 0.5 * ld, 1))
        symmetric_wall = gp.boolean(symmetric_wall,
                                    twin_wall,
                                    'or',
                                    layer=sw_layer)

    else:  # loop-type: 'grazing-angle'
        loop.mirror((0, l2_proj_y / 2), (1, l2_proj_y / 2))
        left_wall = [(0, -d1), (-1, -d1 - math.sqrt(3)),
                     (-3, -d1 - math.sqrt(3)), (-4, -d1)]
        left_wall = gp.Polygon(left_wall, layer=sw_layer)
        right_wall = gp.copy(left_wall)
        right_wall.mirror((l1 / 2, 0), (l1 / 2, 1))
        symmetric_wall = gp.boolean(left_wall,
                                    right_wall,
                                    'or',
                                    layer=sw_layer)

    # make twin structures to facilitate growth
    if twin_enable and loop_type != 'high-angle-60deg':  # only works on mirror-symmetric types
        loop2 = gp.copy(loop)
        loop2.mirror((l1 + l2_proj_x + 2.5 * la, 0),
                     (l1 + l2_proj_x + 2.5 * la, 1))
        loop = gp.boolean(loop, loop2, 'or', layer=layer)
        if loop_type in {'high-angle-symmetric', 'high-angle-90deg'}:
            loop = gp.boolean(
                loop,
                gp.FlexPath([(l1 + l2_proj_x + la, l2_proj_y),
                             (l1 + l2_proj_x + 4 * la, l2_proj_y)], width),
                'or',
                layer=layer)
        else:  # 'grazing-angle'
            loop = gp.boolean(loop,
                              gp.FlexPath([(l1 + l2_proj_x + la, 0),
                                           (l1 + l2_proj_x + 4 * la, 0)],
                                          width),
                              'or',
                              layer=layer)

        wall2 = gp.copy(symmetric_wall)
        wall2.mirror((l1 + l2_proj_x + 2.5 * la, 0),
                     (l1 + l2_proj_x + 2.5 * la, 1))
        symmetric_wall = gp.boolean(symmetric_wall,
                                    wall2,
                                    'or',
                                    layer=sw_layer)

    shadow = _add_shadow(symmetric_wall)
    return (
        loop, symmetric_wall,
        shadow) if symmetric_wall != None else loop  # no 30deg option with SWs
Exemplo n.º 26
0
            width=[small_margin, small_margin],
            offset=small_margin + width,
            gdsii_path=True,
        )
        path.segment((0, 600 - bus_len - bend_radius - wg_gap * i),
                     relative=True)
        path.turn(bend_radius, "r")
        path.segment((io_gap - 2 * bend_radius, 0), relative=True)
        path.turn(bend_radius, "l")
        path.segment((0, 300 - bend_radius + wg_gap * i), relative=True)
        c.add(path)
        dx = width / 2 + gap
        c.add(
            gdspy.boolean(
                gdspy.boolean(ring_bus,
                              gdspy.copy(ring_margin, dx, 300),
                              "or",
                              precision=1e-4),
                gdspy.copy(ring_hole, dx, 300),
                "not",
                precision=1e-4,
            ).translate(input_gap * i, 0))
    c.add(gdspy.CellArray(taper, len(ring_gaps), 1, (input_gap, 0), (0, 0)))
    c.add(
        gdspy.CellArray(grat, len(ring_gaps), 1, (input_gap, 0),
                        (io_gap, 900 + taper_len)))

    # Save to a gds file and check out the output
    lib.write_gds("photonics.gds")
    gdspy.LayoutViewer(lib)