def gds(self, filename=None, view=False, extra=0, units="nms"): """Writes the geometry to the gds file. Parameters ---------- filename : str, optional Location to save file to. Defaults to None. extra : int, optional Extra straight portion to add to ends of waveguides to make room in simulation (units same as units parameter). Defaults to 0. units : {'microns' or 'nms'}, optional Units to save gds file in. Defaults to microns. view : bool, optional Whether to visually show gds file. Defaults to False. """ # check to make sure the geometry isn't an array if len(self._clean_args(None)[0]) != 1: raise ValueError( "You have changing geometries, making gds doesn't make sense") if units == "nms": scale = 1e-3 elif units == "microns": scale = 1 else: raise ValueError("Invalid units") # scale to proper units sc_radius = self.radius * scale sc_gap = self.gap * scale sc_width = self.width * scale sc_length = self.length * scale # write to GDS pathTop = gdspy.Path( sc_width, (-sc_length / 2, 2 * sc_radius + sc_width / 2 + sc_gap / 2)) pathTop.segment(sc_length, "+x") pathTop.turn(sc_radius, "rr") pathTop.segment(sc_length, "-x") pathTop.turn(sc_radius, "rr") pathBottom = gdspy.Path( sc_width, (-sc_radius - sc_width / 2 - sc_length / 2, -sc_gap / 2 - sc_width / 2), ) pathBottom.segment(2 * (sc_radius + sc_width / 2) + sc_length, "+x") gdspy.current_library = gdspy.GdsLibrary() path_cell = gdspy.Cell("C0") path_cell.add(pathTop) path_cell.add(pathBottom) if view: gdspy.LayoutViewer(cells="C0") if filename is not None: writer = gdspy.GdsWriter(filename, unit=1.0e-6, precision=1.0e-9) writer.write_cell(path_cell) writer.close()
def test_writer_gds(tmpdir): lib = gdspy.GdsLibrary() c1 = gdspy.Cell("gw_rw_gds_1") c1.add(gdspy.Rectangle((0, -1), (1, 2), 2, 4)) c1.add(gdspy.Label("label", (1, -1), "w", 45, 1.5, True, 5, 6)) c2 = gdspy.Cell("gw_rw_gds_2") c2.add(gdspy.Round((0, 0), 1, number_of_points=32, max_points=20)) c3 = gdspy.Cell("gw_rw_gds_3") c3.add(gdspy.CellReference(c1, (0, 1), -90, 2, True)) c4 = gdspy.Cell("gw_rw_gds_4") c4.add(gdspy.CellArray(c2, 2, 3, (1, 4), (-1, -2), 180, 0.5, True)) lib.add((c1, c2, c3, c4)) fname1 = str(tmpdir.join("test1.gds")) writer1 = gdspy.GdsWriter(fname1, name="lib", unit=2e-3, precision=1e-5) for c in lib.cells.values(): writer1.write_cell(c) writer1.close() lib1 = gdspy.GdsLibrary(unit=1e-3) lib1.read_gds( fname1, units="convert", rename={"gw_rw_gds_1": "1"}, layers={2: 4}, datatypes={4: 2}, texttypes={6: 7}, ) assert lib1.name == "lib" assert len(lib1.cells) == 4 assert set(lib1.cells.keys()) == {"1", "gw_rw_gds_2", "gw_rw_gds_3", "gw_rw_gds_4"} c = lib1.cells["1"] assert len(c.polygons) == len(c.labels) == 1 assert c.polygons[0].area() == 12.0 assert c.polygons[0].layers == [4] assert c.polygons[0].datatypes == [2] assert c.labels[0].text == "label" assert c.labels[0].position[0] == 2 and c.labels[0].position[1] == -2 assert c.labels[0].anchor == 4 assert c.labels[0].rotation == 45 assert c.labels[0].magnification == 1.5 assert c.labels[0].x_reflection == True assert c.labels[0].layer == 5 assert c.labels[0].texttype == 7 c = lib1.cells["gw_rw_gds_2"] assert len(c.polygons) == 2 assert isinstance(c.polygons[0], gdspy.Polygon) and isinstance( c.polygons[1], gdspy.Polygon ) c = lib1.cells["gw_rw_gds_3"] assert len(c.references) == 1 assert isinstance(c.references[0], gdspy.CellReference) assert c.references[0].ref_cell == lib1.cells["1"] assert c.references[0].origin[0] == 0 and c.references[0].origin[1] == 2 assert c.references[0].rotation == -90 assert c.references[0].magnification == 2 assert c.references[0].x_reflection == True c = lib1.cells["gw_rw_gds_4"] assert len(c.references) == 1 assert isinstance(c.references[0], gdspy.CellArray) assert c.references[0].ref_cell == lib1.cells["gw_rw_gds_2"] assert c.references[0].origin[0] == -2 and c.references[0].origin[1] == -4 assert c.references[0].rotation == 180 assert c.references[0].magnification == 0.5 assert c.references[0].x_reflection == True assert c.references[0].spacing[0] == 2 and c.references[0].spacing[1] == 8 assert c.references[0].columns == 2 assert c.references[0].rows == 3 fname2 = str(tmpdir.join("test2.gds")) with open(fname2, "wb") as fout: writer2 = gdspy.GdsWriter(fout, name="lib2", unit=2e-3, precision=1e-5) for c in lib.cells.values(): writer2.write_cell(c) writer2.close() with open(fname2, "rb") as fin: lib2 = gdspy.GdsLibrary() lib2.read_gds(fin) assert lib2.name == "lib2" assert len(lib2.cells) == 4
n = 20 # loop counter gap_step = (gap1 - gap0) / (n - 1) #sweep gap parameter alL = 350 #aligment distance to device final_pos = numpy.array([ (2 * r1 + sec_gap + taper_l + taper_ii_l) * 2 + iii_v_l, (n * d) ]) hw = 3.0 #nicr heater width hh = 20.0 #nicr heater height ang = pi / 6.0 # 30° heater sqr = 10.0 httiaucell = gdspy.Cell('Heater_Ti_Au') def nicrheat(layer_num, center, radius, hw, hh, ang, sqr): pos1 = (center[0] - radius * sin(ang), center[1] - radius * cos(ang)) pos2 = (center[0] + radius * sin(ang), center[1] - radius * cos(ang)) nch1 = gdspy.Round(center, radius + hw / 2, radius - hw / 2, initial_angle=-ang - pi / 2.0, final_angle=ang - pi / 2.0, layer=layer_num, max_points=4094, number_of_points=0.1) nch2 = gdspy.Rectangle((pos1[0] + hw, pos1[1]), (pos1[0], pos1[1] - hh),
self.add(path_clad) def __build_ports(self): # Portlist format: # example: example: {'port':(x_position, y_position), 'direction': 'NORTH'} self.portlist["input"] = {"port": (0, 0), "direction": "WEST"} self.portlist["output"] = { "port": (self.length, 0), "direction": "EAST" } if __name__ == "__main__": from . import * top = gdspy.Cell("top") wgt_strip = WaveguideTemplate(bend_radius=50, wg_type="strip", wg_width=0.7) wgt_slot = WaveguideTemplate(bend_radius=50, wg_type="slot", wg_width=0.7, slot=0.2) wg1 = Waveguide([(0, 0), (100, 100)], wgt_strip) tk.add(top, wg1) ycoup = StripSlotYConverter(wgt_strip, wgt_slot, 10.0, 0.2,
# wlow, llow = [39.81, 4051.32] # Low Z section whigh, lhigh = [2, 4051.32] # High Z section rcav, rlow, rhigh = [50, 50, 50] # layers sub_layer = 0 dot_layer = 1 cond_layer = 2 rem_layer = 3 # Start making resonator geometry ############################################################################ # # Setup gds cell and gds object poly_cell = gdspy.Cell('POLYGONS') rs = Shapes(poly_cell) # Substrate coordinate list sub = rs.rect(sub_x, sub_y, wrhead_xoff, wrhead_yoff) substrate = gdspy.Polygon(sub, layer=sub_layer) # Dots layout = LayoutComponents(poly_cell, sub_x, sub_y, layer=dot_layer) dots = layout.antidot_array(wrhead_xoff, wrhead_yoff, 10, 30, 0) coords = lambda x, dx=0: x + dx lcav1, lcav2, arcc = cavlengths(lc, rcav) # xb_strt,yb_strt = [coords(sub_x/2-arcc),coords(sub_y/2)] xb_strt, yb_strt = [ coords(sub_x / 2, wrhead_xoff),
from numpy import * import gdspy import gdslib import os deviceName = '2016Mar29_Resonators' device = gdspy.Cell(deviceName) print(os.getcwd()) # print(os.chdir("C:/Users/Michael/Dropbox/GitHub/PainterQubits/devMichael/AutoCAD/gdspy")) # FREQUENCY DESIGN # [1] Coplanar Waveguide Circuits, Components, and Systems by Rainee Simons c = 3E8 er = 11.9 # Substrate dielectric constant ereff = (1 + er) / 2 # [1] Eq. 2.30 # BOUNDARY DEFINITIONS # Boundary of section of chip containing features device.add(gdspy.Rectangle((0, 0), (10000, 5000), layer=1)) # Boundary of the entire 1 cm chip device.add(gdspy.Rectangle((0, 0), (10000, 10000), layer=2)) # Approximate clip placement area device.add(gdspy.Rectangle((2500, 7000), (7500, 10000), layer=3)) # Stitch for i in range(0, 1250): device.add(gdspy.Rectangle((0, 8 * i), (10000, 8 * i + 4), layer=7)) device.add(gdspy.Rectangle((8 * i, 0), (8 * i + 4, 10000), layer=7)) # FEEDLINE
cavity_cell.add(cav1) cavity_cell.add(cav2) cavity_cell.add(cav3) cavity_cell.add( cav12) # Cell: Cavity; Objects: coupled rings, ring trenching # --------- Taper sections --------------------------- # return (wg_cell, cavity_cell) #waveguidex = draw(-1)[4] #waveguidey = draw(-2)[5] # # combined_cell = gdspy.Cell('COMB1') #combined_cell2=gdspy.Cell('COMB2') #(wv,cc,gratc,nfc,wgx,wgy) = draw(gap0+gap_step*(ii)) #combined_cell.add(gdspy.CellReference(wv,origin=(0,-ii*d))) #combined_cell.add(gdspy.CellReference(wv,origin=(2*wgx + 2*(taper_ii_l)+iii_v_l, wgy-ii*d ),rotation=180, x_reflection=True)) for ii in range(0, n, 1): (wv, cc) = draw(gap0 + gap_step * (ii)) combined_cell.add(gdspy.CellReference(wv, origin=(0, -ii * d))) combined_cell.add(gdspy.CellReference(cc, origin=(0, -ii * d))) ## ------------------------------------------------------------------ ## ## OUTPUT ## ## ------------------------------------------------------------------ ##
def test_robustpath2(target): cell = gdspy.Cell("test") rp = gdspy.RobustPath((0, 0), [0.1, 0.2, 0.1], 0.15, layer=[1, 2, 3]) assert len(rp) == 0 rp.segment((1, 0)) rp.segment((1, 1), 0.1, 0.05) rp.segment((1, 1), [0.2, 0.1, 0.1], -0.05, True) rp.segment((-1, 1), 0.2, [-0.2, 0, 0.3], True) rp.arc(2, 0, 0.5 * numpy.pi) rp.arc(3, 0.7 * numpy.pi, numpy.pi, 0.1, 0) rp.arc(2, 0.4 * numpy.pi, -0.4 * numpy.pi, [0.1, 0.2, 0.1], [0.2, 0, -0.2]) rp.turn(1, -0.3 * numpy.pi) rp.turn(1, "rr", 0.15) rp.turn(0.5, "l", [0.05, 0.1, 0.05], [0.15, 0, -0.15]) assert len(rp) == 10 cell.add(rp) rp = gdspy.RobustPath((-5, 6), 0.8, layer=20, ends="round", tolerance=1e-4) rp.segment((1, 1), 0.1, relative=True) cell.add(rp) rp = gdspy.RobustPath((-5, 6), 0.8, layer=21, ends="extended", tolerance=1e-4) rp.segment((1, 1), 0.1, relative=True) cell.add(rp) rp = gdspy.RobustPath((-5, 6), 0.8, layer=22, ends=(0.1, 0.2), tolerance=1e-4) rp.segment((1, 1), 0.1, relative=True) cell.add(rp) rp = gdspy.RobustPath((-5, 6), 0.8, layer=23, ends="smooth", tolerance=1e-4) rp.segment((1, 1), 0.1, relative=True) cell.add(rp) rp = gdspy.RobustPath((-3, 6), 0.8, layer=10, ends="round", tolerance=1e-5) rp.segment((1, 0), 0.1, relative=True) rp.segment((0, 1), 0.8, relative=True) cell.add(rp) rp = gdspy.RobustPath((-3, 6), 0.8, layer=11, ends="extended", tolerance=1e-5) rp.segment((1, 0), 0.1, relative=True) rp.segment((0, 1), 0.8, relative=True) cell.add(rp) rp = gdspy.RobustPath((-3, 6), 0.8, layer=12, ends="smooth", tolerance=1e-5) rp.segment((1, 0), 0.1, relative=True) rp.segment((0, 1), 0.8, relative=True) cell.add(rp) rp = gdspy.RobustPath((-3, 8), 0.1, layer=13, ends="round", tolerance=1e-5) rp.segment((1, 0), 0.8, relative=True) rp.segment((0, 1), 0.1, relative=True) cell.add(rp) rp = gdspy.RobustPath((-3, 8), 0.1, layer=14, ends=(0.2, 0.2), tolerance=1e-5) rp.segment((1, 0), 0.8, relative=True) rp.segment((0, 1), 0.1, relative=True) cell.add(rp) rp = gdspy.RobustPath((-3, 8), 0.1, layer=15, ends="smooth", tolerance=1e-5) rp.segment((1, 0), 0.8, relative=True) rp.segment((0, 1), 0.1, relative=True) cell.add(rp) rp = gdspy.RobustPath((5, 2), [0.05, 0.1, 0.2], [-0.2, 0, 0.4], layer=[4, 5, 6]) rp.parametric(lambda u: numpy.array((5.5 + 3 * u, 2 + 3 * u**2)), relative=False) rp.segment((0, 1), relative=True) rp.parametric( lambda u: numpy.array((2 * numpy.cos(0.5 * numpy.pi * u) - 2, 3 * numpy .sin(0.5 * numpy.pi * u))), width=[0.2, 0.1, 0.05], offset=[-0.3, 0, 0.3], ) rp.parametric(lambda u: numpy.array((-2 * u, 0)), width=0.1, offset=0.2) rp.bezier([(-3, 0), (-2, -3), (0, -4), (0, -5)], offset=[-0.2, 0, 0.2]) rp.bezier( [(4.5, 0), (1, -1), (1, 5), (3, 2), (5, 2)], width=[0.05, 0.1, 0.2], offset=[-0.2, 0, 0.4], relative=False, ) cell.add(rp) rp = gdspy.RobustPath((2, -1), 0.1, layer=7, tolerance=1e-4, max_points=0) rp.smooth( [(1, 0), (1, -1), (0, -1)], angles=[numpy.pi / 3, None, -2 / 3.0 * numpy.pi, None], cycle=True, ) cell.add(rp) rp = gdspy.RobustPath((2.5, -1.5), 0.1, layer=8) rp.smooth( [(3, -1.5), (4, -2), (5, -1), (6, -2), (7, -1.5), (7.5, -1.5)], relative=False, width=0.2, ) cell.add(rp) assertsame(target["RobustPath2"], cell)
max_val = np.max(np.abs(Ey)) plt.contour(eps_r.T, levels=[(epsr_max+1)/2]) im = plt.imshow(np.real(Ey.T*np.exp(1j*3)), cmap='RdBu', aspect='auto', vmin=-max_val, vmax=max_val) divider = make_axes_locatable(ax) cax = divider.append_axes('right', size='5%', pad=0.05) cbar = plt.colorbar(im, cax=cax, orientation='vertical'); if Get_gds: # create folder if needed if not os.path.exists(foldername): os.makedirs(foldername) # how many periods do you want to convert into a gds file n_periods = 20 eps_new = np.concatenate((np.ones((Nx,2)), np.tile(eps_r, (1,n_periods)), np.ones((Nx,2))), axis=1) # make sure that the gds files are named uniquely try: gds_number = gds_number + 1 except NameError: gds_number = 0 cell = gy.Cell('eps'+str(gds_number)) contour_level = 10 # pick a value between epsr_min and epsr_max for points in find_contours(eps_new, contour_level): cell.add(gy.Polygon(points).fracture()) # write gds file gy.write_gds(foldername+'\\gds_file.gds', [cell.name], unit=dL)
number = 5 # number of Zlow-Zhigh cascades from each side of the resonator w_c = 4 # C finger width h_c = 0 # C finger height w_sep = 4 # C finger separation h_sep = 66 # C finger vertical distance from ground plane fingers to resonator delta_x = 0 # offset for starting point of C fingers c_gap = 2 c_length = 50 ## End of parameters ## #%% creation of basic PBG structure with lambda/2 resonator cell = gdspy.Cell('PGB') k = 0 for i in range(number): Zlow1 = gdspy.Rectangle((0 + k * (l_Zlow + l_Zhigh), 0), (l_Zlow + k * (l_Zlow + l_Zhigh), t_Zlow)) Zhigh1 = gdspy.Rectangle((l_Zlow + k * (l_Zlow + l_Zhigh), (t_Zlow - t_Zhigh) / 2.), (l_Zlow + l_Zhigh + k * (l_Zlow + l_Zhigh), (t_Zlow - t_Zhigh) / 2. + t_Zhigh)) # cell.add(Zlow1) # cell.add(Zhigh1) k = k + 1 res = gdspy.Rectangle((k * (l_Zlow + l_Zhigh), (t_Zlow - t_res) / 2.), (k * (l_Zlow + l_Zhigh) + l_res, (t_Zlow - t_res) / 2. + t_res))
def nanowire_binary(number, width, pitch, length, n, m, is_interrupt, device_shape, pals_length, itr, elec_width, pin_length=60): """ 用于绘制任意大小,并联根数的纳米线版图,python版本:2.7.14,3.3,只画方形器件 长度单位:μm width 单根纳米线宽度 length 纳米线长度,同时是纳米线区域的半径 pitch 纳米线周期宽度 itr 计数纳米线根数 n:并联纳米线根数 m:二级并联根数 pals_length:二级并联长度 elec_width MA6光刻电极宽度 """ length = float(length) width = float(width) pitch = float(pitch) n = int(n) is_interrupt = int(is_interrupt) device_shape = int(device_shape) pals_length = float(pals_length) elec_width = int(elec_width) pin_length = float(pin_length) minedge = 10 maxdiameter = length + 2 * minedge #外围结构为5um,设置纳米线电子束曝光尺寸大小 Cellname = "nanowire" + str(itr) single_cell = gdspy.Cell(Cellname, exclude_from_current=True) mark = itr #gdspy.GdsLibrary.add(single_cell,overwrite_duplication = True) if is_interrupt == 1 and pals_length < pitch - width: print("并联长度过小") return single_cell if length + minedge > maxdiameter: print("纳米线长度设置应小于等于50μm") return single_cell #返回空的cell if is_interrupt == 1 and pals_length > length: print("纳米线并联长度应小于直径") return single_cell #返回空的cell total = int(length / pitch) """ #根据并联纳米线根数和纳米线间距来微调纳米线直径 """ if n < 1 or m < 1: print("纳米线小于1,n应该>=1") return single_cell elif type(n) == float: print('纳米线并联数应为>=1的整数') return single_cell unnece = total % (n * m) #多余的纳米线根数 itr = int(total / n / m) #纳米线周期 if unnece > int(n / 2): total = (itr + 1) * n * m else: total = itr * n * m a = (elec_width - length) / pin_length / 2 if a - int(a) > 0.8: a = int(a) + 2 else: a = int(a) + 1 oldl = length length = total * pitch print("对纳米线" + Cellname + "长度进行了微调:原始值{},微调后值{},".format(oldl, total * pitch)) # length = total*pitch # total1 = total half = total / 2 """ 绘制纳米线核心区域 两步绘制: 计算调整圆的直径,确定圆的刻蚀线终点 1 绘制中心圆区域 2,绘制隔离线 """ #步骤一1 if device_shape == 0: edge = shape.circle(pitch * total, width, pitch, total, half) # iso = shape.circleiso(length,width,n) # equ_area = shape.circle_equ(length,maxdiameter,width,pitch,total,half) elif device_shape == 1: edge = shape.squire(pitch * total, width, pitch, total, half) # iso = shape.squireiso(length,width,n) # equ_area = shape.squire_equ(length,maxdiameter,width,pitch,total,half) # single_cell.add(iso[0]) # single_cell.add(iso[1]) # # #绘制外围等效曝光区 # for i in equ_area: # for j in i: # single_cell.add(gdspy.Rectangle(*j,layer = 1,datatype = 1)) # #纳米线核心区域点阵 startpoint = edge[0] finalpoint = edge[1] i = 0 location = numpy.linspace(0, total, int(total / n) + 1) #二级并联线位置 location1 = numpy.linspace(0, total, int(total / n / m) + 1) #隔离线位置 j = 1.0 #direction max_length = 0 m1 = m while i < len(startpoint) - n * 2: #调整并联单元长度相等 m = 0 while m < n and i < len(startpoint): if i == 0: #保证0点的线存在 startpoint[i] = (startpoint[i - m + 1][0], startpoint[i][1]) finalpoint[i] = (finalpoint[i - m + 1][0], finalpoint[i][1]) startpoint[i] = (startpoint[i - m][0], startpoint[i][1]) finalpoint[i] = (finalpoint[i - m][0], finalpoint[i][1]) m = m + 1 i = i + 1 i = 0 while i < len(startpoint): #计算最大圆直径 if is_interrupt == 1 and n > 1: step = pals_length # single_length = abs(finalpoint[i][0] - startpoint[i][0]) if (int(single_length / step) + 1) * step - length < n * pitch: single_length = int(single_length / step + 1) * step else: single_length = int(single_length / step) * step if numpy.sqrt(single_length**2 / 4 + startpoint[i][1]**2 ) > max_length and device_shape == 0: #圆形的隔离圆大小需要修改 max_length = numpy.sqrt( (single_length**2 / 4 + startpoint[i][1]**2)) startpoint[i] = (-single_length / 2, startpoint[i][1]) finalpoint[i] = (single_length / 2, finalpoint[i][1]) i = i + 1 max_length = 2 * max_length if max_length < pitch * total: max_length = pitch * total #保证外切圆直径为离散值后的最大直径 maxdiameter = max_length + 2 * minedge #调整最大曝光区域 if maxdiameter <= pin_length: maxdiameter = pin_length i = 0 while i < len(startpoint): #i=0,和total对应在x=0位置 if 0 == 1: j = -j else: #每隔30um绘制一个断点 if is_interrupt == 1 and n > 1: step = pals_length # k = 0 if i not in location: while (k + 1) * step < finalpoint[i][0] - startpoint[i][0]: steppoint1 = (startpoint[i][0] + k * step, startpoint[i][1]) steppoint2 = (startpoint[i][0] + (k + 1) * step - width * (n - 1), finalpoint[i][1]) polym = gdspy.Rectangle(steppoint1, steppoint2, layer=1, datatype=1) polym.fillet(pitch - width, points_per_2pi=20) single_cell.add(polym) k = k + 1 else: steppoint1 = (startpoint[i][0] + k * step, startpoint[i][1]) steppoint2 = finalpoint[i] polym = gdspy.Rectangle(steppoint1, steppoint2, layer=1, datatype=1) polym.fillet(pitch - width, points_per_2pi=20) single_cell.add(polym) else: if i not in location: polym = gdspy.Rectangle(startpoint[i], finalpoint[i], layer=1, datatype=1) polym.fillet((pitch - width) / 2, points_per_2pi=20) single_cell.add(polym) if i in location: if i in location1: startpoint[i] = (j * startpoint[i][0], startpoint[i][1]) if device_shape == 0: finalpoint[i] = (j * numpy.sqrt((max_length / 2 + 3)**2 - ((half - i) * pitch)**2), finalpoint[i][1]) elif device_shape == 1: finalpoint[i] = (j * (max_length / 2 + 3), finalpoint[i][1]) j = -j polym = gdspy.Rectangle(startpoint[i], finalpoint[i], layer=1, datatype=1) polym.fillet((pitch - width) / 2, points_per_2pi=20) single_cell.add(polym) i = i + 1 if device_shape == 0: iso = shape.circleiso(max_length, width, n) equ_area = shape.circle_equ(max_length, maxdiameter, width, pitch, total, half) elif device_shape == 1: iso = shape.squireiso(max_length, width, n) equ_area = shape.squire_equ(max_length, maxdiameter, width, pitch, total, half) single_cell.add(iso[0]) single_cell.add(iso[1]) #绘制外围等效曝光区 layer = {'layer': 1, 'datatype': 1} #定义图层 for i in equ_area: for j in i: single_cell.add(gdspy.Rectangle(*j, **layer)) #纳米线核心区域点阵 startpoint = edge[0] finalpoint = edge[1] """ 电极线结构 pitch 纳米线间距,即周期 width:纳米线宽度 length 纳米线长度,电极宽度设置为2um,在并联纳米线总宽宽度>1μm后, 电极宽度调整为(n+4)*width 预曝光区域,宽度设置为5μm 曝光长度设置为length/2+5,pitch与纳米线一致 """ length = max_length #将length改为划出纳米线调整后的最大直径 total = int((maxdiameter / 2 - length / 2 - 1) / pitch) i = 0 m = m1 if n * m * width >= 1: half_elecwidth = (n * m + 4) * width else: half_elecwidth = 1 old = half_elecwidth while i <= total - 1: if i <= int(n * m * width / pitch) + 1: half_elecwidth = max_length / 2 + 3 else: half_elecwidth = old elec1 = gdspy.Rectangle( (half_elecwidth, i * pitch + length / 2), (maxdiameter / 2, i * pitch + length / 2 + pitch - width), **layer) single_cell.add(elec1) elec2 = gdspy.Rectangle( (-half_elecwidth, i * pitch + length / 2), (-maxdiameter / 2, i * pitch + length / 2 + pitch - width), **layer) single_cell.add(elec2) elec3 = gdspy.Rectangle( (-half_elecwidth, (-i - 1) * pitch - length / 2), (-maxdiameter / 2, -i * pitch - length / 2 - (pitch - width)), **layer) single_cell.add(elec3) elec4 = gdspy.Rectangle( (half_elecwidth, (-i - 1) * pitch - length / 2), (maxdiameter / 2, -i * pitch - length / 2 - (pitch - width)), **layer) single_cell.add(elec4) i = i + 1 """ 隔离线,宽度1um,伸出纳米线区域elec_width/2+pin_ength """ # length = oldl #需要原始直径值 if elec_width / 2 > length / 2 + pin_length - 10: a = (elec_width / 2 - length / 2 - pin_length) / pin_length if a - int(a) > 0.9: a = int(a) + 2 else: a = int(a) + 1 halflen = pin_length * (a + 1) + length / 2 else: halflen = length / 2 + pin_length edgelen = maxdiameter / 2 #纳米线区域边界 insulate1 = gdspy.Rectangle((half_elecwidth, edgelen - 1), (halflen, edgelen), **layer) single_cell.add(insulate1) insulate2 = gdspy.Rectangle((-half_elecwidth, edgelen - 1), (-halflen, edgelen), **layer) single_cell.add(insulate2) insulate3 = gdspy.Rectangle((-half_elecwidth, -edgelen + 1), (-halflen, -edgelen), **layer) single_cell.add(insulate3) insulate4 = gdspy.Rectangle((half_elecwidth, -edgelen + 1), (halflen, -edgelen), **layer) single_cell.add(insulate4) insulate5 = gdspy.Rectangle((edgelen - 1, halflen), (edgelen, -halflen), **layer) single_cell.add(insulate5) insulate6 = gdspy.Rectangle((-edgelen + 1, halflen), (-edgelen, -halflen), **layer) single_cell.add(insulate6) """ 绘制拼接场外围尺寸,固定等效曝光区域宽10μm 位置在边界处:pin_length-minedge """ """ length = oldl # oldl=原始length,保证被整场分割而不滑移。允许出现边界处拼接场存在。 layer_useless = {'layer': 3, 'datatype': 3} out = gdspy.Rectangle((-length / 2 - pin_length, -maxdiameter / 2), # 左边 (-length / 2 - pin_length + 1, maxdiameter / 2), **layer_useless ) single_cell.add(out) out = gdspy.Rectangle((length / 2 + pin_length, -maxdiameter / 2), # 右边 (length / 2 + pin_length - 1, maxdiameter / 2), **layer_useless ) single_cell.add(out) out = gdspy.Rectangle((-maxdiameter / 2, length / 2 + pin_length), # 上左 (-half_elecwidth, length / 2 + pin_length - 1), **layer_useless ) single_cell.add(out) out = gdspy.Rectangle((maxdiameter / 2, length / 2 + pin_length), # 上右 (half_elecwidth, length / 2 + pin_length - 1), **layer_useless ) single_cell.add(out) out = gdspy.Rectangle((-maxdiameter / 2, -length / 2 - pin_length), # 下左 (-half_elecwidth, -length / 2 - pin_length + 1), **layer_useless ) single_cell.add(out) out = gdspy.Rectangle((maxdiameter / 2, -length / 2 - pin_length), # 下右 (half_elecwidth, -length / 2 - pin_length + 1), **layer_useless ) single_cell.add(out) """ """ 对准标记 4umX100μm大小十字 位置,-500um,500um """ markers = [1, 9, 41, 73, 81] if mark in markers: cross = gdspy.Rectangle((-450, 498), (-550, 502), **layer) single_cell.add(cross) cross = gdspy.Rectangle((-498, 450), (-502, 550), **layer) single_cell.add(cross) """ 编号 """ text = gdspy.Text(str(number), 20, (1000, 300), **layer) single_cell.add(text) merged = gdspy.fast_boolean(gdspy.Rectangle( (-maxdiameter / 2, -maxdiameter / 2), (maxdiameter / 2, maxdiameter / 2)), gdspy.CellReference(single_cell), 'not', max_points=190) # Offset the path shape by 0.5 and add it to the cell. single_cell.add(merged) return single_cell
def memory_benchmark(): proc = psutil.Process() total = 100000 print(f"\nMemory usage per object for {total} objects.") def print_row(*vals, hsep=False): columns = [20, 16, 16, 9] print( "|", vals[0].ljust(columns[0]), "|", " | ".join(v.center(c) for v, c in zip(vals[1:], columns[1:])), "|", ) if hsep: print( "|", ":" + "-" * (columns[0] - 1), "|", " | ".join(":" + "-" * (c - 2) + ":" for c in columns[1:]), "|", ) print_row( "Object", "Gdspy " + gdspy.__version__, "Gdstk " + gdstk.__version__, "Reduction", hsep=True, ) def mem_test(func): start_mem = proc.memory_info() r = [func(i) for i in range(total)] end_mem = proc.memory_info() return (end_mem.vms - start_mem.vms) / total, r data = [] gdspy_cell = gdspy.Cell("TEMP", exclude_from_current=True) gdstk_cell = gdstk.Cell("TEMP") for obj, gdspy_func, gdstk_func in [ ( "Rectangle", lambda i: gdspy.Rectangle((i, i), (i + 1, i + 1)), lambda i: gdstk.rectangle((i, i), (i + 1, i + 1)), ), ( "Circle (r = 10)", lambda i: gdspy.Round((0, 10 * i), 10), lambda i: gdstk.ellipse((0, 10 * i), 10), ), ( "FlexPath segment", lambda i: gdspy.FlexPath([(i, i + 1), (i + 1, i)], 0.1), lambda i: gdstk.FlexPath([(i, i + 1), (i + 1, i)], 0.1), ), ( "FlexPath arc", lambda i: gdspy.FlexPath([(10 * i, 0)], 0.1).arc(10, 0, numpy.pi), lambda i: gdstk.FlexPath([(10 * i, 0)], 0.1).arc(10, 0, numpy.pi), ), ( "RobustPath segment", lambda i: gdspy.RobustPath((i, i + 1), 0.1).segment((i + 1, i)), lambda i: gdstk.RobustPath((i, i + 1), 0.1).segment((i + 1, i)), ), ( "RobustPath arc", lambda i: gdspy.RobustPath((10 * i, 0), 0.1).arc(10, 0, numpy.pi), lambda i: gdstk.RobustPath((10 * i, 0), 0.1).arc(10, 0, numpy.pi), ), ( "Label", lambda i: gdspy.Label(str(i), (i, i)), lambda i: gdstk.Label(str(i), (i, i)), ), ( "Reference", lambda i: gdspy.CellReference(gdspy_cell, (0, 0)), lambda i: gdstk.Reference(gdstk_cell, (0, 0)), ), ( "Reference (array)", lambda i: gdspy.CellArray(gdspy_cell, (0, 0), 1, 1, (0, 0)), lambda i: gdstk.Reference(gdstk_cell, (0, 0), rows=1, columns=1), ), ( "Cell", lambda i: gdspy.Cell(str(i), exclude_from_current=True), lambda i: gdstk.Cell(str(i)), ), ]: gdspy_mem, gdspy_data = mem_test(gdspy_func) data.append(gdspy_data) gdstk_mem, gdstk_data = mem_test(gdstk_func) data.append(gdstk_data) print_row( obj, prefix_format(gdspy_mem, unit="B", base="bin"), prefix_format(gdstk_mem, unit="B", base="bin"), f"{100 - 100 * gdstk_mem / gdspy_mem:.0f}%", )
def test_mirror(): ps = gdspy.PolygonSet([[(0, 0), (1, 0), (1, 2), (0, 2)]]) ps.mirror((-1, 1), (1, -1)) tgt = gdspy.PolygonSet([[(0, 0), (-2, 0), (-2, -1), (0, -1)]]) assertsame(gdspy.Cell("test").add(ps), gdspy.Cell("TGT").add(tgt))
def test_translate(): ps = gdspy.PolygonSet([[(0, 0), (1, 0), (1, 2), (0, 2)]]) ps.translate(-1, -2) tgt = gdspy.PolygonSet([[(-1, -2), (0, -2), (0, 0), (-1, 0)]]) assertsame(gdspy.Cell("test").add(ps), gdspy.Cell("TGT").add(tgt))
# Boost Software License - Version 1.0. See the accompanying # # LICENSE file or <http://www.boost.org/LICENSE_1_0.txt> # # # ###################################################################### import numpy import gdspy print('Using gdspy module version ' + gdspy.__version__) # ------------------------------------------------------------------ # # POLYGONS # ------------------------------------------------------------------ # # First we need a cell to add the polygons to. poly_cell = gdspy.Cell('POLYGONS') # We define the polygon through its vertices. points = [(0, 0), (2, 2), (2, 6), (-6, 6), (-6, -6), (-4, -4), (-4, 4), (0, 4)] # Create the polygon on layer 1. poly1 = gdspy.Polygon(points, 1) # Add the new polygon to the cell. poly_cell.add(poly1) # Create another polygon from the same set of points, but rotate it # 180 degrees and add it to the cell. poly2 = gdspy.Polygon(points, 1).rotate(numpy.pi) poly_cell.add(poly2)
def gds(self, filename=None, extra=0, units='microns', view=False, sbend_h=0, sbend_v=0): #check to make sure the geometry isn't an array if len(self.clean_args(None)[0]) != 1: raise ValueError( "You have changing geometries, making gds doesn't make sense") if units == 'nms': scale = 1 elif units == 'microns': scale = 10**-3 else: raise ValueError('Invalid units') #scale to proper units sc_zmin = self.zmin * scale sc_zmax = self.zmax * scale sc_width = self.width * scale cL = (sc_zmax - sc_zmin) cH = self.gap(self.zmin) * scale / 2 #make parametric functions paraTop = lambda x: (x * (sc_zmax - sc_zmin) + sc_zmin, scale * self. gap(x * (self.zmax - self.zmin) + self.zmin ) / 2 + sc_width / 2) paraBottom = lambda x: (x * (sc_zmax - sc_zmin) + sc_zmin, -scale * self.gap(x * (self.zmax - self.zmin) + self. zmin) / 2 - sc_width / 2) #dparaTop = lambda x: (sc_zmax-sc_zmin, scale*(self.zmax-self.zmin)*self.dgap(x*(self.zmax-self.zmin)+self.zmin)/2) #dparaBottom = lambda x: (sc_zmax-sc_zmin, -scale*(self.zmax-self.zmin)*self.dgap(x*(self.zmax-self.zmin)+self.zmin)/2) sbend = False if sbend_h != 0 and sbend_v != 0: sbend = True sbendDown = lambda x: (sbend_h * x, -sbend_v / 2 * (1 - np.cos(np.pi * x))) sbendUp = lambda x: (sbend_h * x, sbend_v / 2 * (1 - np.cos(np.pi * x))) dsbendDown = lambda x: (sbend_h, -np.pi * sbend_v / 2 * np.sin(np.pi * x)) dsbendUp = lambda x: (sbend_h, np.pi * sbend_v / 2 * np.sin(np.pi * x)) #write to GDS pathTop = gdspy.Path( sc_width, (sc_zmin - extra - sbend_h, cH + sc_width / 2 + sbend_v)) pathTop.segment(extra, '+x') if sbend: pathTop.parametric(sbendDown, dsbendDown) pathTop.parametric(paraTop, relative=False) if sbend: pathTop.parametric(sbendUp, dsbendUp) pathTop.segment(extra, '+x') pathBottom = gdspy.Path( sc_width, (sc_zmin - extra - sbend_h, -cH - sc_width / 2 - sbend_v)) pathBottom.segment(extra, '+x') if sbend: pathBottom.parametric(sbendUp, dsbendUp) pathBottom.parametric(paraBottom, relative=False) if sbend: pathBottom.parametric(sbendDown, dsbendDown) pathBottom.segment(extra, '+x') gdspy.current_library = gdspy.GdsLibrary() path_cell = gdspy.Cell('C0') path_cell.add(pathTop) path_cell.add(pathBottom) if view: gdspy.LayoutViewer(cells='C0') if filename is not None: writer = gdspy.GdsWriter(filename, unit=1.0e-6, precision=1.0e-9) writer.write_cell(path_cell) writer.close()
def test_hobby1(target): cell = gdspy.Cell("test", True) c = gdspy.Curve(0, 0, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)]) cell.add(gdspy.Polygon(c.get_points(), layer=1)) c = gdspy.Curve(2, 0, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[numpy.pi / 3, None, None, None]) cell.add(gdspy.Polygon(c.get_points(), layer=3)) c = gdspy.Curve(4, 0, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[None, None, None, 2 / 3.0 * numpy.pi]) cell.add(gdspy.Polygon(c.get_points(), layer=5)) c = gdspy.Curve(0, 2, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[numpy.pi / 3, None, None, 3 / 4.0 * numpy.pi]) cell.add(gdspy.Polygon(c.get_points(), layer=7)) c = gdspy.Curve(2, 2, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[None, None, numpy.pi / 2, None]) cell.add(gdspy.Polygon(c.get_points(), layer=9)) c = gdspy.Curve(4, 2, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[None, 0, None, None]) cell.add(gdspy.Polygon(c.get_points(), layer=11)) c = gdspy.Curve(0, 4, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[None, 0, None, -numpy.pi / 2]) cell.add(gdspy.Polygon(c.get_points(), layer=13)) c = gdspy.Curve(2, 4, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[None, 0, -numpy.pi, -numpy.pi / 2]) cell.add(gdspy.Polygon(c.get_points(), layer=15)) c = gdspy.Curve(4, 4, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[-numpy.pi / 4, 0, numpy.pi / 2, -numpy.pi]) cell.add(gdspy.Polygon(c.get_points(), layer=17)) c = gdspy.Curve(0, 0, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=2)) c = gdspy.Curve(2, 0, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[numpy.pi / 3, None, None, None], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=4)) c = gdspy.Curve(4, 0, tolerance=1e-3) c.i( [(1, 0), (1, 1), (0, 1)], angles=[None, None, None, 2 / 3.0 * numpy.pi], cycle=True, ) cell.add(gdspy.Polygon(c.get_points(), layer=6)) c = gdspy.Curve(0, 2, tolerance=1e-3) c.i( [(1, 0), (1, 1), (0, 1)], angles=[numpy.pi / 3, None, None, 3 / 4.0 * numpy.pi], cycle=True, ) cell.add(gdspy.Polygon(c.get_points(), layer=8)) c = gdspy.Curve(2, 2, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[None, None, numpy.pi / 2, None], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=10)) c = gdspy.Curve(4, 2, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[None, 0, None, None], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=12)) c = gdspy.Curve(0, 4, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[None, 0, None, -numpy.pi / 2], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=14)) c = gdspy.Curve(2, 4, tolerance=1e-3) c.i([(1, 0), (1, 1), (0, 1)], angles=[None, 0, -numpy.pi, -numpy.pi / 2], cycle=True) cell.add(gdspy.Polygon(c.get_points(), layer=16)) c = gdspy.Curve(4, 4, tolerance=1e-3) c.i( [(1, 0), (1, 1), (0, 1)], angles=[-numpy.pi / 4, 0, numpy.pi / 2, -numpy.pi], cycle=True, ) cell.add(gdspy.Polygon(c.get_points(), layer=18)) assertsame(target["Hobby1"], cell)
def gds(self, filename=None, view=False, extra=0, units='nms', sbend_h=0, sbend_v=0): #check to make sure the geometry isn't an array if len(self.clean_args(None)[0]) != 1: raise ValueError( "You have changing geometries, making gds doesn't make sense") if units == 'nms': scale = 1 elif units == 'microns': scale = 10**-3 else: raise ValueError('Invalid units') #scale to proper units sc_width = self.width * scale sc_gap = self.gap * scale sc_length = self.length * scale sc_H = self.H * scale sc_V = self.V * scale #make parametric functions sbendDown = lambda x: (sc_H * x, -sc_V / 2 * (1 - np.cos(np.pi * x))) sbendUp = lambda x: (sc_H * x, sc_V / 2 * (1 - np.cos(np.pi * x))) dsbendDown = lambda x: (sc_H, -np.pi * sc_V / 2 * np.sin(np.pi * x)) dsbendUp = lambda x: (sc_H, np.pi * sc_V / 2 * np.sin(np.pi * x)) sbend = False if sbend_h != 0 and sbend_v != 0: sbend = True sbendDownExtra = lambda x: (sbend_h * x, -sbend_v / 2 * (1 - np.cos(np.pi * x))) sbendUpExtra = lambda x: (sbend_h * x, sbend_v / 2 * (1 - np.cos(np.pi * x))) dsbendDownExtra = lambda x: (sbend_h, -np.pi * sbend_v / 2 * np.sin( np.pi * x)) dsbendUpExtra = lambda x: (sbend_h, np.pi * sbend_v / 2 * np.sin(np.pi * x)) #write to GDS pathTop = gdspy.Path(sc_width, (-sc_length / 2 - sc_H - sbend_h - extra, sc_V + sbend_v + sc_width / 2 + sc_gap / 2)) pathTop.segment(extra, '+x') if sbend: pathTop.parametric(sbendDownExtra, dsbendDownExtra) pathTop.parametric(sbendDown, dsbendDown) pathTop.segment(sc_length, '+x') pathTop.parametric(sbendUp, dsbendUp) if sbend: pathTop.parametric(sbendUpExtra, dsbendUpExtra) pathTop.segment(extra, '+x') pathBottom = gdspy.Path(sc_width, (-sc_length / 2 - sc_H - sbend_h - extra, -sc_V - sbend_v - sc_width / 2 - sc_gap / 2)) pathBottom.segment(extra, '+x') if sbend: pathBottom.parametric(sbendUpExtra, dsbendUpExtra) pathBottom.parametric(sbendUp, dsbendUp) pathBottom.segment(sc_length, '+x') pathBottom.parametric(sbendDown, dsbendDown) if sbend: pathBottom.parametric(sbendDownExtra, dsbendDownExtra) pathBottom.segment(extra, '+x') gdspy.current_library = gdspy.GdsLibrary() path_cell = gdspy.Cell('C0') path_cell.add(pathTop) path_cell.add(pathBottom) if view: gdspy.LayoutViewer(cells='C0') if filename is not None: writer = gdspy.GdsWriter(filename, unit=1.0e-6, precision=1.0e-9) writer.write_cell(path_cell) writer.close()
gap_step = (gap1 - gap0) / (n - 1) #sweep gap parameter alL = 350 #aligment distance to device final_pos = numpy.array([ (2 * r1 + sec_gap + taper_l + taper_ii_l) * 2 + iii_v_l, (n * d) ]) hw = 3.0 #nicr heater width hh = 30.0 #nicr heater height ang = pi / 12.0 # 30° heater sqr = 10.0 spec4 = 1 pcavc = (1, 1) nccell = gdspy.Cell('Heater_Ni_Cr') combined_cell = gdspy.Cell('COMB1') def nicrheat(layer_num, center, radius, hw, hh, ang, sqr): pos1 = (center[0] - radius * sin(2.0 * ang), center[1] - radius * cos(2.0 * ang)) pos2 = (center[0] + radius * sin(2.0 * ang), center[1] - radius * cos(2.0 * ang)) nch1 = gdspy.Round(center, radius + hw / 2, radius - hw / 2, initial_angle=-ang - pi / 2.0, final_angle=ang - pi / 2.0, layer=layer_num,
def test_flexpath4(target): cell = gdspy.Cell("test") fp = gdspy.FlexPath( [(0, 0)], [0.1, 0.2, 0.1], 0.15, layer=[1, 2, 3], corners=["natural", "miter", "bevel"], ) fp.segment((1, 0)) fp.segment((1, 1), 0.1, 0.05) fp.segment((1, 1), [0.2, 0.1, 0.1], -0.05, True) fp.segment((-1, 1), 0.2, [-0.2, 0, 0.3], True) fp.arc(2, 0, 0.5 * numpy.pi) fp.arc(3, 0.5 * numpy.pi, numpy.pi, 0.1, 0) fp.arc(1, 0.4 * numpy.pi, -0.4 * numpy.pi, [0.1, 0.2, 0.1], [0.2, 0, -0.2]) fp.turn(1, 0.4 * numpy.pi) fp.turn(1, "ll", 0.15, 0) fp.turn(0.5, "r", [0.1, 0.05, 0.1], [0.15, 0, -0.15]) cell.add(fp) fp = gdspy.FlexPath([(-5, 6)], 0.8, layer=20, ends="round", tolerance=1e-4) fp.segment((1, 1), 0.1, relative=True) cell.add(fp) fp = gdspy.FlexPath([(-5, 6)], 0.8, layer=21, ends="extended", tolerance=1e-4) fp.segment((1, 1), 0.1, relative=True) cell.add(fp) fp = gdspy.FlexPath([(-5, 6)], 0.8, layer=22, ends=(0.1, 0.2), tolerance=1e-4) fp.segment((1, 1), 0.1, relative=True) cell.add(fp) fp = gdspy.FlexPath([(-5, 6)], 0.8, layer=23, ends="smooth", tolerance=1e-4) fp.segment((1, 1), 0.1, relative=True) cell.add(fp) fp = gdspy.FlexPath([(-3, 6)], 0.8, layer=10, corners="round", ends="round", tolerance=1e-5) fp.segment((1, 0), 0.1, relative=True) fp.segment((0, 1), 0.8, relative=True) cell.add(fp) fp = gdspy.FlexPath([(-3, 6)], 0.8, layer=11, corners="smooth", ends="extended", tolerance=1e-5) fp.segment((1, 0), 0.1, relative=True) fp.segment((0, 1), 0.8, relative=True) cell.add(fp) fp = gdspy.FlexPath([(-3, 6)], 0.8, layer=12, corners="smooth", ends="smooth", tolerance=1e-5) fp.segment((1, 0), 0.1, relative=True) fp.segment((0, 1), 0.8, relative=True) cell.add(fp) fp = gdspy.FlexPath([(-3, 8)], 0.1, layer=13, corners="round", ends="round", tolerance=1e-5) fp.segment((1, 0), 0.8, relative=True) fp.segment((0, 1), 0.1, relative=True) cell.add(fp) fp = gdspy.FlexPath([(-3, 8)], 0.1, layer=14, corners="smooth", ends=(0.2, 0.2), tolerance=1e-5) fp.segment((1, 0), 0.8, relative=True) fp.segment((0, 1), 0.1, relative=True) cell.add(fp) fp = gdspy.FlexPath([(-3, 8)], 0.1, layer=15, corners="round", ends="smooth", tolerance=1e-5) fp.segment((1, 0), 0.8, relative=True) fp.segment((0, 1), 0.1, relative=True) cell.add(fp) fp = gdspy.FlexPath([(5, 2)], [0.05, 0.1, 0.2], [-0.2, 0, 0.4], layer=[4, 5, 6]) fp.parametric(lambda u: numpy.array((5.5 + 3 * u, 2 + 3 * u**2)), relative=False) fp.segment((0, 1), relative=True) fp.parametric( lambda u: numpy.array((2 * numpy.cos(0.5 * numpy.pi * u) - 2, 3 * numpy .sin(0.5 * numpy.pi * u))), [0.2, 0.1, 0.05], [-0.3, 0, 0.3], ) fp.parametric(lambda u: numpy.array((-2 * u, 0)), 0.1, 0.2) fp.bezier([(-3, 0), (-2, -3), (0, -4), (0, -5)], offset=[-0.2, 0, 0.2]) fp.bezier( [(5, 0), (1, -1), (1, 5), (3, 2), (5, 2)], [0.05, 0.1, 0.2], [-0.2, 0, 0.4], relative=False, ) cell.add(fp) fp = gdspy.FlexPath([(2, -1)], 0.1, layer=7, tolerance=1e-5, max_points=0) fp.smooth( [(1, 0), (1, -1), (0, -1)], angles=[numpy.pi / 3, None, -2 / 3.0 * numpy.pi, None], cycle=True, ) cell.add(fp) fp = gdspy.FlexPath([(2.5, -1.5)], 0.1, layer=8) fp.smooth( [(3, -1.5), (4, -2), (5, -1), (6, -2), (7, -1.5), (7.5, -1.5)], relative=False, width=0.2, ) cell.add(fp) assertsame(target["FlexPath4"], cell)
def draw(gap): ## ------------------------------------------------------------------ ## ## Define Cells ## ## ------------------------------------------------------------------ ## wg_cell = [] nofill_cell = [] cavity_cell = [] gccell = [] del (wg_cell, nofill_cell, cavity_cell, gccell) ## Cell containing the waveguides wg_cell = gdspy.Cell('WAVEGUIDES' + str((n - 1) * (gap - gap0) / (gap1 - gap0))) ## Cell containing microrings cavity_cell = gdspy.Cell('CAV' + str((n - 1) * (gap - gap0) / (gap1 - gap0))) ## ------------------------------------------------------------------ ## ## Layer Specification ## ## ------------------------------------------------------------------ ## spec = {'layer': 37, 'datatype': 4} # Fully etched SOI: waveguide core spec2 = { 'layer': 37, 'datatype': 5 } # Fully etched SOI: waveguide cladding (trench around core) spec3 = { 'layer': 1158, 'datatype': 0 } # Area not to be filled with dummies (SOI,Poly or metal) ## ------------------------------------------------------------------ ## ## Objects Design ## ## ------------------------------------------------------------------ ## #------ Waveguide+taper -----------------------------------------------# waveguide = gdspy.Path(wg_w, (-sec_gap, 0)) waveguide.segment(2 * r1 + 2 * c_w2, '+x', **spec) #------ Coupled Microrings -----------------------------------------------# r2 = (r1 - wg_w - 3.0 * gap / 2.0) / 2.0 pcavc = (waveguide.x - r1 - c_w2, waveguide.y - gap - 0.5 * wg_w - r1) cav1 = gdspy.Round((pcavc[0], pcavc[1]), r1, r1 - wg_w, max_points=4094, number_of_points=0.1, **spec) cav2 = gdspy.Round((pcavc[0] + r2 + 0.5 * gap, pcavc[1]), r2, r2 - wg_w, max_points=4094, number_of_points=0.1, **spec) cav3 = gdspy.Round((pcavc[0] - r2 - 0.5 * gap, pcavc[1]), r2, r2 - wg_w, max_points=4094, number_of_points=0.1, **spec) #------ Trench Arond waveguides -----------------------------------------------# waveguide2 = gdspy.Path(wg_w2, (-sec_gap, 0)) waveguide2.segment(2 * r1 + 2 * c_w2, '+x', **spec2) #------ Trench Arond coupled rings -----------------------------------------------# cav12 = gdspy.Rectangle((pcavc[0] - r1 - c_w2, pcavc[1] - r1 - c_w2), (pcavc[0] + r1 + c_w2, pcavc[1] + r1 + c_w2), **spec2) #nofillc=gdspy.Rectangle( (waveguide.x-sec_gap-r1-taper_l-r1-wg_w2,waveguide.y-gap-0.5*wg_w-r1*2*(1.5-cos(pi/8.0))-r1-wg_w2),(waveguide.x-sec_gap-r1-taper_l+r1+wg_w2,waveguide.y-gap-0.5*wg_w-r1*2*(1.5-cos(pi/8.0))+r1+wg_w2),**spec3) #nofillw=gdspy.Rectangle( (-bragg_offset,-bragg_nofill/2.0-bragg_nfoffset),(waveguide.x,waveguide.y+bragg_nofill/2.0-bragg_nfoffset),**spec3) ## ------------------------------------------------------------------ ## ## Adding Objects into Cells ## ## ------------------------------------------------------------------ ## wg_cell.add(waveguide) wg_cell.add( waveguide2 ) # Cell: Waveguide; Objects: waveguide+taper, waveguide trenching cavity_cell.add(cav1) cavity_cell.add(cav2) cavity_cell.add(cav3) cavity_cell.add( cav12) # Cell: Cavity; Objects: coupled rings, ring trenching # --------- Taper sections --------------------------- # return (wg_cell, cavity_cell)
chord_angle = 2 * math.asin(flat_size / diameter) center = Vector((diameter / 2, diameter / 2, 0)) # Then, calculate the start and stop angles for an arc initial_angle = -chord_angle / 2 + 3 * math.pi / 2 final_angle = chord_angle / 2 - math.pi / 2 # Find the positions of the start and the end start_vect = Vector((diameter, diameter / 2, 0)) start_vect = gen_rotate_matrix(math.degrees(initial_angle), center) @ start_vect curve = gdspy.Curve(*start_vect.xy, tolerance=10) curve.arc(diameter / 2, initial_angle, final_angle) return gdspy.Polygon(curve.get_points(), layer=layer) if __name__ == "__main__": doc = gdspy.GdsLibrary() mark = elionix_mark(doc) elionix_4block(doc, mark) render_text.render_to_block(doc, "NW200311_0001") arrow_cell = gdspy.Cell("arrow") arrow_cell.add(arrow(Vector((0, 0, 0)))) doc.add(arrow_cell) die_marker(doc, name="die_marker") wire_section(doc, "a") draw_wafer(doc) with open("test.gds", "wb") as f: doc.write_gds(f)
""" import gdspy from Modules.ModuleResonator import TwirledSpiral, Cpw_twirled import numpy as np Centre = (0, 0) L = 0.75e-3 W = 500e-9 I = 10.085e-6 carac = {"layer": 0, "datatype": 3} ab = TwirledSpiral(Centre, L, W, I, [0, 0]) a = gdspy.FlexPath(ab[0], W * 1e6, **carac).rotate(np.pi / 2, (ab[0][0])) b = gdspy.FlexPath(ab[1], W * 1e6, **carac).rotate(np.pi / 2, (ab[0][0])) testcell = gdspy.Cell("testcell") testcell.add(a) testcell.add(b) #Dimensions of one resonator (see in vjws journal 26/02/21 for graphical explanation of formula) Lsize = ab[1][-1][1] - ab[0][-1][1] + W * 1e6 #Height of the resonator Hsize = ab[0][-1][0] - ab[1][-1][0] Hr = Hsize * 1e-6 #height of resonator in SI units Lr = Lsize * 1e-6 #length of resonator in SI units center_first = ab[0][0] Sr = 1e-6 #Generating the ground plane + cpw
def gen_gds(poly_coords: List[np.ndarray], filepath: str, extra_structures: List[np.ndarray] = None, deembed: bool = True) -> None: """Generate GDS given a list of polygon coordinates. Output GDS has units of microns and precision in nanometers. Args: poly_coords: List of polygon coordinates. Elements of list are n x 2 numpy.ndarrays. Assumes coordinates in nanometers. filepath: Name of the filepath to output gds file. extra_structures: List of polygons to be added to the gds that are not part of the levelset function. deembed: Boolean to control if polygon deembeding will occur or not. """ poly_cell = gdspy.Cell("POLYGONS", exclude_from_current=True) test_points = [] gds_polygons = [] # Convert polygon coordinates from nanometers to microns since # output is in microns. poly_coords = [np.array(poly) / NM_PER_UM for poly in poly_coords] for polygon in poly_coords: test_points.append(tuple(polygon[0])) gds_polygons.append(gdspy.Polygon(polygon, 0)) if deembed: containment_mx = [] for polygon in gds_polygons: containment_mx.append(gdspy.inside(test_points, [polygon])) # Subtract by identity matrix since polygon_i trivially contains # polygon_i. containment_mx = np.array(containment_mx) - np.eye(len(gds_polygons)) # overlap_list[i] tells how many polygons are contained in polygon i. overlap_list = np.sum(containment_mx, axis=1) overlap_num = 0 while sum(overlap_list) != 0: overlap_num = overlap_num + 1 # We loop until there are no longer any more polygons of a specific # overlap number before going to the next overlap number. # # The reasoning for this is as we begin to delete polygons, # the overlap number changes and so polygons which were of # overlap_num > 1, may become polygons of overlap_num = 1. # # np.where(overlap_list==overlap_num)[0].size is how we see if # any polygons satisfy the current overlap number. target_polys = np.where(overlap_list == overlap_num)[0] while target_polys.size != 0: # We iterate through each polygon in our polygon list until no # polygon satisfies the current overlap number. for i in target_polys[::-1]: containment_list = np.nonzero(containment_mx[i, :])[0] for j in containment_list[::-1]: # The boolean 'not' operation is performed here. # We replace polygon[i] of the two polygons with the # result of the operation and delete polygon[j]. gds_polygons[i] = gdspy.fast_boolean(gds_polygons[i], gds_polygons[j], 'not', layer=0) gds_polygons[j] = None test_points[j] = None for k in range(len(gds_polygons) - 1, -1, -1): if gds_polygons[k] is None: del gds_polygons[k] del test_points[k] containment_mx = [] for polygon in gds_polygons: containment_mx.append(gdspy.inside(test_points, [polygon])) containment_mx = np.array(containment_mx) - np.eye( len(gds_polygons)) overlap_list = np.sum(containment_mx, axis=1) target_polys = np.where(overlap_list == overlap_num)[0] for polygon in gds_polygons: poly_cell.add(polygon) if extra_structures is not None: for extra_polygon in extra_structures: poly_cell.add(gdspy.Polygon(extra_polygon, 0)) gdspy.write_gds(filepath, cells=[poly_cell], unit=1.0e-6, precision=1.0e-9)
name = (os.path.abspath(os.path.dirname(os.sys.argv[0]))) + os.sep + 'devices' print('Creating layout') ## ------------------------------------------------------------------ ## ## DRAWING ## ## ------------------------------------------------------------------ ## # Layers layer_vector = [ 1 ] # order: disks, bullseye mod a, bullseye mod wRing, idmarks, working area, align marks # Create a cell for the unit element unit_cell1 = gdspy.Cell('testcell') for x in range(0, 19): unit_cell1.add(draw_waveguide(1, (0, 0.01 * x), x, 19)) ## ------------------------------------------------------------------ ## ## OUTPUT ## ## ------------------------------------------------------------------ ## ## Output the layout to a GDSII file (default to all created cells). ## Set the units we used to micrometers and the precision to nanometers. gdspy.gds_print(name + '.gds', unit=1.0e-6, precision=1.0e-9) print('Sample gds file saved: ' + name + '.gds') ## ------------------------------------------------------------------ ## ## VIEWER ##
l.text, font=font, fill=color[(l.layer, l.texttype)]) img = img.resize((width, height), Image.ANTIALIAS) name = 'docs/_static/' + (cell.name if name is None else name) + '.png' print('Saving', name) img.save(name) if __name__ == "__main__": # Polygons # Create a polygon from a list of vertices points = [(0, 0), (2, 2), (2, 6), (-6, 6), (-6, -6), (-4, -4), (-4, 4), (0, 4)] poly = gdspy.Polygon(points) draw(gdspy.Cell('polygons').add(poly)) # Holes # Manually connect the hole to the outer boundary cutout = gdspy.Polygon([(0, 0), (5, 0), (5, 5), (0, 5), (0, 0), (2, 2), (2, 3), (3, 3), (3, 2), (2, 2)]) draw(gdspy.Cell('holes').add(cutout)) # Circles # Circle centered at (0, 0), with radius 2 and tolerance 0.1 circle = gdspy.Round((0, 0), 2, tolerance=0.01) # To create an ellipse, simply pass a list with 2 radii. # Because the tolerance is small (resulting a large number of # vertices), the ellipse is fractured in 2 polygons. ellipse = gdspy.Round((4, 0), [1, 2], tolerance=1e-4)
def test_rw_gds(tmpdir): lib = gdspy.GdsLibrary('lib') c1 = gdspy.Cell('gl_rw_gds_1', True) c1.add(gdspy.Rectangle((0, -1), (1, 2), 2, 4)) c1.add(gdspy.Label('label', (1, -1), 'w', 45, 1.5, True, 5, 6)) c2 = gdspy.Cell('gl_rw_gds_2', True) c2.add(gdspy.Round((0, 0), 1, number_of_points=32, max_points=20)) c3 = gdspy.Cell('gl_rw_gds_3', True) c3.add(gdspy.CellReference(c1, (0, 1), -90, 2, True)) c4 = gdspy.Cell('gl_rw_gds_4', True) c4.add(gdspy.CellArray(c2, 2, 3, (1, 4), (-1, -2), 180, 0.5, True)) lib.add((c1, c2, c3, c4)) fname1 = str(tmpdir.join('test1.gds')) lib.write_gds(fname1, unit=2e-3, precision=1e-5) lib1 = gdspy.GdsLibrary() lib1.read_gds(fname1, 1e-3, {'gl_rw_gds_1': '1'}, {2: 4}, {4: 2}, {6: 7}) assert lib1.name == 'lib' assert len(lib1.cell_dict) == 4 assert set(lib1.cell_dict.keys()) == { '1', 'gl_rw_gds_2', 'gl_rw_gds_3', 'gl_rw_gds_4' } c = lib1.cell_dict['1'] assert len(c.elements) == len(c.labels) == 1 assert c.elements[0].area() == 12.0 assert c.elements[0].layer == 4 assert c.elements[0].datatype == 2 assert c.labels[0].text == 'label' assert c.labels[0].position[0] == 2 and c.labels[0].position[1] == -2 assert c.labels[0].anchor == 4 assert c.labels[0].rotation == 45 assert c.labels[0].magnification == 1.5 assert c.labels[0].x_reflection == True assert c.labels[0].layer == 5 assert c.labels[0].texttype == 7 c = lib1.cell_dict['gl_rw_gds_2'] assert len(c.elements) == 2 assert isinstance(c.elements[0], gdspy.Polygon) \ and isinstance(c.elements[1], gdspy.Polygon) c = lib1.cell_dict['gl_rw_gds_3'] assert len(c.elements) == 1 assert isinstance(c.elements[0], gdspy.CellReference) assert c.elements[0].ref_cell == lib1.cell_dict['1'] assert c.elements[0].origin[0] == 0 and c.elements[0].origin[1] == 2 assert c.elements[0].rotation == -90 assert c.elements[0].magnification == 2 assert c.elements[0].x_reflection == True c = lib1.cell_dict['gl_rw_gds_4'] assert len(c.elements) == 1 assert isinstance(c.elements[0], gdspy.CellArray) assert c.elements[0].ref_cell == lib1.cell_dict['gl_rw_gds_2'] assert c.elements[0].origin[0] == -2 and c.elements[0].origin[1] == -4 assert c.elements[0].rotation == 180 assert c.elements[0].magnification == 0.5 assert c.elements[0].x_reflection == True assert c.elements[0].spacing[0] == 2 and c.elements[0].spacing[1] == 8 assert c.elements[0].columns == 2 assert c.elements[0].rows == 3 fname2 = str(tmpdir.join('test2.gds')) lib.name = 'lib2' with open(fname2, 'wb') as fout: lib.write_gds(fout, unit=2e-3, precision=1e-5) with open(fname2, 'rb') as fin: lib2 = gdspy.GdsLibrary() lib2.read_gds(fin) assert lib2.name == 'lib2' assert len(lib2.cell_dict) == 4
def create_sim_space( gds_fg_name: str, gds_bg_name: str, sim_width: float = 8000, # size of sim_space box_width: float = 4000, # size of our editing structure wg_width: float = 600, buffer_len: float = 1500, # not sure we'll need dx: int = 40, num_pmls: int = 10, visualize: bool = False, ) -> optplan.SimulationSpace: """Creates the simulation space. The simulation space contains information about the boundary conditions, gridding, and design region of the simulation. Args: gds_fg_name: Location to save foreground GDS. gds_bg_name: Location to save background GDS. etch_frac: Etch fraction of the grating. 1.0 indicates a fully-etched grating. box_thickness: Thickness of BOX layer in nm. wg_width: Width of the waveguide. buffer_len: Buffer distance to put between grating and the end of the simulation region. This excludes PMLs. dx: Grid spacing to use. num_pmls: Number of PML layers to use on each side. visualize: If `True`, draws the polygons of the GDS file. Returns: A `SimulationSpace` description. """ # Calculate the simulation size, including PMLs # TODO change the first part of ech dimension to be equal sim_size = [ sim_width + 2 * buffer_len + dx * num_pmls, sim_width + 2 * buffer_len + dx * num_pmls ] # First, we use `gdspy` to draw the waveguides and shapes that we would # like to use. Instead of programmatically generating a GDS file using # `gdspy`, we could also simply provide a GDS file (e.g. drawn using # KLayout). # Declare some constants to represent the different layers. # Not sure if we need layers LAYER = 100 # Create rectangles corresponding to the waveguide, the BOX layer, and the # design region. We extend the rectangles outside the simulation region # by multiplying locations by a factor of 1.1. # We distinguish between the top part of the waveguide (which is etched) # and the bottom part of the waveguide (which is not etched). # TODO define our single waveguide and surface, I don't believe it will be etched. # Switch x and y temporarily to try and get better direction for field - change top to bottom # Add an exit waveguide_top = gdspy.Rectangle((-1.1 * sim_size[0] / 2, -wg_width / 2), (-box_width / 2, wg_width / 2), LAYER) waveguide_bottom = gdspy.Rectangle((box_width / 2, -wg_width / 2), (1.1 * sim_size[0] / 2, wg_width / 2), LAYER) design_region = gdspy.Rectangle( (-box_width / 2, -box_width / 2), (box_width / 2, box_width / 2), # extend region? LAYER) # Generate the foreground and background GDS files. gds_fg = gdspy.Cell("FOREGROUND", exclude_from_current=True) gds_fg.add(waveguide_top) gds_fg.add(waveguide_bottom) gds_fg.add(design_region) # I guess we keep this the same and not include the design_region gds_bg = gdspy.Cell("BACKGROUND", exclude_from_current=True) gds_bg.add(waveguide_top) gds_bg.add(waveguide_bottom) gdspy.write_gds(gds_fg_name, [gds_fg], unit=1e-9, precision=1e-9) gdspy.write_gds(gds_bg_name, [gds_bg], unit=1e-9, precision=1e-9) # The BOX layer/silicon device interface is set at `z = 0`. # # Describe materials in each layer. # 1) Silicon Nitride # Note that the layer numbering in the GDS file is arbitrary. Layer 300 is a dummy # layer; it is used for layers that only have one material (i.e. the # background and foreground indices are identical) so the actual structure # used does not matter. # Will need to define out material, just silicon nitride # Remove the etching stuff # Can define Si3N4 - the material we want to use # Fix: try to make multiple layers, but all the same? air = optplan.Material(index=optplan.ComplexNumber(real=1)) stack = [ optplan.GdsMaterialStackLayer( foreground=air, background=air, gds_layer=[100, 0], extents=[ -10000, -110 ], # will probably need to define a better thickness for our layer ), optplan.GdsMaterialStackLayer( foreground=optplan.Material(mat_name="Si3N4"), background=air, gds_layer=[100, 0], extents=[ -110, 110 ], # will probably need to define a better thickness for our layer ), ] mat_stack = optplan.GdsMaterialStack( # Any region of the simulation that is not specified is filled with # air. background=air, stack=stack, ) # these define the entire region you wish to scan in the z -direction, not sure for us # as we don't require etching or layers # will probably change this as thickness may be wrong # Create a simulation space for both continuous and discrete optimization. # TODO too large a space takes too long to process - may need blue bear simspace = optplan.SimulationSpace( name="simspace", mesh=optplan.UniformMesh(dx=dx), eps_fg=optplan.GdsEps(gds=gds_fg_name, mat_stack=mat_stack), eps_bg=optplan.GdsEps(gds=gds_bg_name, mat_stack=mat_stack), # Note that we explicitly set the simulation region. Anything # in the GDS file outside of the simulation extents will not be drawn. sim_region=optplan.Box3d( center=[0, 0, 0], extents=[6000, 6000, 40], # this is what's messing things up, needs to be 2D ), # changing the size too much creates an error selection_matrix_type="direct_lattice", # or uniform # PMLs are applied on x- and z-axes. No PMLs are applied along y-axis # because it is the axis of translational symmetry. pml_thickness=[num_pmls, num_pmls, num_pmls, num_pmls, 0, 0], # may need to edit this, make z the 0 axis ) if visualize: # To visualize permittivity distribution, we actually have to # construct the simulation space object. import matplotlib.pyplot as plt from spins.invdes.problem_graph.simspace import get_fg_and_bg context = workspace.Workspace() eps_fg, eps_bg = get_fg_and_bg(context.get_object(simspace), label=1070) #edit here def plot(x): plt.imshow(np.abs(x)[:, 0, :].T.squeeze(), origin="lower") plt.figure() plt.subplot(3, 1, 1) plot(eps_fg[2]) plt.title("eps_fg") plt.subplot(3, 1, 2) plot(eps_bg[2]) plt.title("eps_bg") plt.subplot(3, 1, 3) plot(eps_fg[2] - eps_bg[2]) plt.title("design region") plt.show() return simspace
def draw(gap): ## ------------------------------------------------------------------ ## ## Define Cells ## ## ------------------------------------------------------------------ ## wg_cell = [] nofill_cell = [] cavity_cell = [] gccell = [] httiaucell = [] htnicrcell = [] del (wg_cell, nofill_cell, cavity_cell, gccell, httiaucell, htnicrcell) ## Cell containing the waveguides wg_cell = gdspy.Cell('WAVEGUIDES' + str(2 * n * (gap - gap0) / (gap0 + gap1))) ## Cell containing no fill area nofill_cell = gdspy.Cell('NOFILL' + str(2 * n * (gap - gap0) / (gap0 + gap1))) ## Cell containing microrings cavity_cell = gdspy.Cell('CAV' + str(2 * n * (gap - gap0) / (gap0 + gap1))) ## Cell containing bragg couplings gc = gdspy.GdsImport('GC_mod.gds', rename={ 'q': 'COUPLERGRATING' + str(2 * n * (gap - gap0) / (gap0 + gap1)) }, layers={10158: 1158}) gccell = gc.extract('COUPLERGRATING' + str(2 * n * (gap - gap0) / (gap0 + gap1))) ## Aligment Cell am = gdspy.GdsImport('aligment_mark.gds', rename={ 'Alignment_Mark': 'Alignment_Mark' + str(2 * n * (gap - gap0) / (gap0 + gap1)) }) amcell = am.extract('Alignment_Mark' + str(2 * n * (gap - gap0) / (gap0 + gap1))) ## NiCr Heater Cell nccell = gdspy.Cell('Heater_Ni_Cr' + str(2 * n * (gap - gap0) / (gap0 + gap1))) ## ------------------------------------------------------------------ ## ## Layer Specification ## ## ------------------------------------------------------------------ ## spec = {'layer': 37, 'datatype': 4} # Fully etched SOI: waveguide core spec2 = { 'layer': 37, 'datatype': 5 } # Fully etched SOI: waveguide cladding (trench around core) spec3 = { 'layer': 1158, 'datatype': 0 } # Area not to be filled with dummies (SOI,Poly or metal) spec4 = {'layer': 1, 'datatype': 0} # NiCr mask ## ------------------------------------------------------------------ ## ## Objects Design ## ## ------------------------------------------------------------------ ## #------ Waveguide+taper -----------------------------------------------# waveguide = gdspy.Path(wg_w, (-sec_gap, 0)) waveguide.segment(sec_gap, '+x', **spec) waveguide.segment(r1 * (1 - 2 * sin(pi / 8.0)), '+x', **spec) waveguide.turn(r1, -pi / 8.0, max_points=4094, number_of_points=0.1, **spec) waveguide.turn(r1, pi / 8.0, max_points=4094, number_of_points=0.1, **spec) waveguide.turn(r1, pi / 8.0, max_points=4094, number_of_points=0.1, **spec) waveguide.turn(r1, -pi / 8.0, max_points=4094, number_of_points=0.1, **spec) waveguide.segment(r1 * (1 - 2 * sin(pi / 8.0)), '+x', **spec) waveguide.segment(sec_gap, '+x', **spec) waveguide.segment(taper_l, '+x', final_width=taper_w, **spec) #------ No tilling region -----------------------------------------------# nofill = gdspy.Path(nofill_w, (waveguide.x - taper_l, waveguide.y)) nofill.segment(taper_l + taper_ii_l + iii_v_l / 2.0, '+x', **spec3) #------ Coupled Microrings -----------------------------------------------# r2 = (r1 - wg_w - 3.0 * gap / 2.0) / 2.0 pcavc = (waveguide.x - sec_gap - r1 - taper_l, waveguide.y - gap - 0.5 * wg_w - r1 * 2 * (1.5 - cos(pi / 8.0))) cav1 = gdspy.Round((pcavc[0], pcavc[1]), r1, r1 - wg_w, max_points=4094, number_of_points=0.1, **spec) cav2 = gdspy.Round((pcavc[0] + r2 + 0.5 * gap, pcavc[1]), r2, r2 - wg_w, max_points=4094, number_of_points=0.1, **spec) cav3 = gdspy.Round((pcavc[0] - r2 - 0.5 * gap, pcavc[1]), r2, r2 - wg_w, max_points=4094, number_of_points=0.1, **spec) #------ Trench Arond waveguides -----------------------------------------------# waveguide2 = gdspy.Path(wg_w2, (-sec_gap, 0)) waveguide2.segment(sec_gap, '+x', **spec2) waveguide2.segment(r1 * (1 - 2 * sin(pi / 8.0)), '+x', **spec2) waveguide2.turn(r1, -pi / 8.0, max_points=4094, number_of_points=0.1, **spec2) waveguide2.turn(r1, pi / 8.0, max_points=4094, number_of_points=0.1, **spec2) waveguide2.turn(r1, pi / 8.0, max_points=4094, number_of_points=0.1, **spec2) waveguide2.turn(r1, -pi / 8.0, max_points=4094, number_of_points=0.1, **spec2) waveguide2.segment(r1 * (1 - 2 * sin(pi / 8.0)), '+x', **spec2) waveguide2.segment(sec_gap, '+x', **spec2) waveguide2.segment(taper_l, '+x', **spec2) #------ Trench Arond coupled rings -----------------------------------------------# cav12 = gdspy.Rectangle((pcavc[0] - r1 - c_w2, pcavc[1] - r1 - c_w2), (pcavc[0] + r1 + c_w2, pcavc[1] + r1 + c_w2), **spec2) #nofillc=gdspy.Rectangle( (waveguide.x-sec_gap-r1-taper_l-r1-wg_w2,waveguide.y-gap-0.5*wg_w-r1*2*(1.5-cos(pi/8.0))-r1-wg_w2),(waveguide.x-sec_gap-r1-taper_l+r1+wg_w2,waveguide.y-gap-0.5*wg_w-r1*2*(1.5-cos(pi/8.0))+r1+wg_w2),**spec3) #nofillw=gdspy.Rectangle( (-bragg_offset,-bragg_nofill/2.0-bragg_nfoffset),(waveguide.x,waveguide.y+bragg_nofill/2.0-bragg_nfoffset),**spec3) #------ NiCr Heater -----------------------------------------------# nch = nicrheat(spec4['layer'], pcavc, r1, hw, hh, ang, sqr) #nch = gdspy.Rectangle( (pcavc[0]-r1-c_w2,pcavc[1]-r1-c_w2),(pcavc[0]+r1+c_w2,pcavc[1]+r1+c_w2),**spec4) ## ------------------------------------------------------------------ ## ## Adding Objects into Cells ## ## ------------------------------------------------------------------ ## wg_cell.add(waveguide) wg_cell.add( waveguide2 ) # Cell: Waveguide; Objects: waveguide+taper, waveguide trenching nofill_cell.add(nofill) #Cell: No fill; Objects: No tilling region cavity_cell.add(cav1) cavity_cell.add(cav2) cavity_cell.add(cav3) cavity_cell.add( cav12) # Cell: Cavity; Objects: coupled rings, ring trenching nccell.add(nch) waveguidex = waveguide.x waveguidey = waveguide.y # --------- Taper sections --------------------------- # return (wg_cell, cavity_cell, gccell, nofill_cell, waveguidex, waveguidey, amcell, nccell)
i = len(polys) - 1 while i >= 0: if gdspy.inside(poly[:1], [polys[i]], precision=0.1 * tolerance)[0]: p = polys.pop(i) poly = gdspy.boolean([p], [poly], 'xor', precision=0.1 * tolerance, max_points=0).polygons[0] break elif gdspy.inside(polys[i][:1], [poly], precision=0.1 * tolerance)[0]: p = polys.pop(i) poly = gdspy.boolean([p], [poly], 'xor', precision=0.1 * tolerance, max_points=0).polygons[0] i -= 1 xmax = max(xmax, poly[:, 0].max()) polys.append(poly) return polys if __name__ == "__main__": fp = FontProperties(family='serif', style='italic') text = gdspy.PolygonSet(render_text('Text rendering', 10, font_prop=fp), layer=1) gdspy.Cell('TXT').add(text) gdspy.write_gds('fonts.gds') gdspy.LayoutViewer()