import gdsfactory as gf import math #Start of the code def CreateHalfPad(x, y, w, d): LeftPad = gf.components.rectangle(size = (x, y), layer = (1, 0)) UpperEllipse = gf.components.ellipse(radii = (d, y-w/2), layer = (1, 0)) HalfPad = gf.boolean(LeftPad, UpperEllipse, operation = "A-B", layer = (1, 0)) return HalfPad def CreatePad(pad): pads = gf.Component() UpPad = CreateHalfPad(pad[0], pad[1], pad[2], pad[3]) DownPad = CreateHalfPad(pad[0], pad[1], pad[2], pad[3]) AddedUpPad = pads.add_ref(UpPad) AddedDownPad = pads.add_ref(DownPad) AddedDownPad.mirror() AddedUpPad.rotate(180) AddedUpPad.move([0, pad[0] -50]) TotalPad = gf.boolean(AddedUpPad, AddedDownPad, operation = "xor", layer = (1, 0)) return TotalPad def CreateSNSPD(Ww, Wp, S, Squares, Tr, SameSideConnector): snspd = gf.components.snspd( wire_width=Ww, wire_pitch=Wp, size=(S[0], S[1]), num_squares=Squares, turn_ratio=Tr, # Controls the shape of the 180-degree bends in the meander(Clojure/Clojurescript library). terminals_same_side=SameSideConnector, layer=(1, 0), ) return snspd def CreateNegativeStructure(Pad, SNSPD): Comp_SNSPD = gf.Component() #Temporary building blocks Comp_Pad1 = gf.Component() #Temporary building blocks Comp_Pad2 = gf.Component() #Temporary building blocks SNSPDObj = CreateSNSPD(SNSPD[0], SNSPD[1], SNSPD[2], SNSPD[3], SNSPD[4], SNSPD[5]) SNSPDObjAdd = Comp_SNSPD.add_ref(SNSPDObj) SNSPDObjAdd.move([SNSPD[2][0]/2 + (200-SNSPD[2][0])/4 , Pad[1]]) Pad1 = CreatePad(pad = Pad) Pad2 = CreatePad(pad = Pad) Pad1.move([50, 0]) #Pad 2 correction calculation #if math.floor((SNSPD[2][0])/((SNSPD[1]*2))) % 2 == 0: if True == False: correction = (math.floor((SNSPD[2][1])/((SNSPD[1]*2))) + 1) * (SNSPD[1]*2) else: correction = (round( (SNSPD[2][1])/(SNSPD[1]*2) )) * (SNSPD[1]*2) if SNSPD[5] == False: Pad2.rotate(180) Pad2.move([50 + SNSPD[2][0], Pad[0] - 50 - correction]) else: correction = (round( (SNSPD[2][1] - 1.3*SNSPD[1])/(SNSPD[1]*2 ))) * (SNSPD[1]*2) + SNSPD[1] Pad2.move([50, SNSPDObjAdd.ymin - SNSPDObjAdd.ymax + SNSPD[0]]) Comp_SNSPD.add_ref(Pad1) Comp_SNSPD.add_ref(Pad2) #Comp_Pad2.connect("o1", SNSPDObjAdd.ports["e2"], allow_layer_mismatch = True) ConstructionTemp = gf.boolean(SNSPDObjAdd, Pad1, operation = "xor", layer = (1, 0)) Construction = gf.boolean(ConstructionTemp, Pad2, operation = "xor", layer = (1, 0)) Rect1 = gf.components.rectangle(size = [Pad[0] - Pad[3], 20], layer=(2, 0)) Rect1C = Comp_Pad1.add_ref(Rect1) Rect1C.move([-Pad[0] + 50, -10]) Rect2 = gf.components.rectangle(size = [Pad[0] - Pad[3], 20], layer=(2, 0)) Rect2C = Comp_Pad1.add_ref(Rect2) Rect2C.move([-Pad[0] + 50, Pad[1] * 2 -10]) Rect3 = gf.components.rectangle(size = [20, Pad[1] * 2], layer=(2, 0)) Rect3C = Comp_Pad1.add_ref(Rect3) Rect3C.move([-Pad[0] + 50, 0]) Rect4 = gf.components.rectangle(size = [20, 100], layer=(2, 0)) Rect4C = Comp_Pad1.add_ref(Rect4) Rect4C.move([-110, -10]) Rect5 = gf.components.rectangle(size = [20, 100], layer=(2, 0)) Rect5C = Comp_Pad1.add_ref(Rect5) Rect5C.move([-110, 360]) correct = SNSPDObjAdd.ymin - SNSPDObjAdd.ymax + SNSPD[0] SecondRect1 = gf.components.rectangle(size = [Pad[0] - Pad[3], 20], layer=(2, 0)) SecondRect1C = Comp_Pad1.add_ref(SecondRect1) SecondRect1C.move([-Pad[0] + 50, -10 + correct]) SecondRect2 = gf.components.rectangle(size = [Pad[0] - Pad[3], 20], layer=(2, 0)) SecondRect2C = Comp_Pad1.add_ref(SecondRect2) SecondRect2C.move([-Pad[0] + 50, Pad[1] * 2 -10 + correct]) SecondRect3 = gf.components.rectangle(size = [20, Pad[1] * 2], layer=(2, 0)) SecondRect3C = Comp_Pad1.add_ref(SecondRect3) SecondRect3C.move([-Pad[0] + 50, correct]) SecondRect4 = gf.components.rectangle(size = [20, 100], layer=(2, 0)) SecondRect4C = Comp_Pad1.add_ref(SecondRect4) SecondRect4C.move([-110, -10 + correct]) SecondRect5 = gf.components.rectangle(size = [20, 100], layer=(2, 0)) SecondRect5C = Comp_Pad1.add_ref(SecondRect5) SecondRect5C.move([-110, 360 + correct]) return Construction, Comp_Pad1 def CreatePositiveStructure(Pad, SNSPD): c = gf.Component() #Temporary building blocks SNSPDObj = CreateSNSPD(SNSPD[0], SNSPD[1], SNSPD[2], SNSPD[3], SNSPD[4], SNSPD[5]) SNSPDObjAdd = c.add_ref(SNSPDObj) SNSPDObjAdd.move([SNSPD[2][0]/2 + (200-SNSPD[2][0])/4 , Pad[1]]) Pad1 = CreatePad(pad = Pad) Pad2 = CreatePad(pad = Pad) Pad1.move([50, 0]) #Pad 2 correction calculation #if math.floor((SNSPD[2][0])/((SNSPD[1]*2))) % 2 == 0: if True == False: correction = (math.floor((SNSPD[2][1])/((SNSPD[1]*2))) + 1) * (SNSPD[1]*2) else: correction = (round( (SNSPD[2][1])/(SNSPD[1]*2) )) * (SNSPD[1]*2) Pad2.rotate(180) Pad2.move([50 + SNSPD[2][0], Pad[0] - 50 - correction]) c.add_ref(Pad1) c.add_ref(Pad2) ConstructionTemp = gf.boolean(SNSPDObjAdd, Pad1, operation = "xor", layer = (1, 0)) Construction = gf.boolean(ConstructionTemp, Pad2, operation = "xor", layer = (1, 0)) SNSPD_area = Construction.get_region(layer = (1, 0)) SNSPD_outline = SNSPD_area.sized(200) Final_SNSPD = SNSPD_outline - SNSPD_area return Final_SNSPD c2 = gf.Component() WireWidth = [ 500, 1000, 2000, 4000, 10000 ] DetectorSize = [1000, 1000] FillingFactor = [0.3, 0.4, 0.5, 0.6, 0.7] WirePitch = 3 TurnRatio = 4 Temp = gf.Component() for i in range(len(WireWidth)): for j in range (len(FillingFactor)): SNSPD, Rect = (CreateNegativeStructure(Pad = [500, 225, WireWidth[i] / 1000, 150], SNSPD = [WireWidth[i] / 1000, WireWidth[i] * (1/FillingFactor[j]) / 1000, DetectorSize, None, 4, True])) SNSPD.name = (str(WireWidth[i]) + "nm width " + str(FillingFactor[j]) + " ff") print(SNSPD.name) RectC = Temp.add_ref(Rect) SNSPDNeg = c2.add_ref(SNSPD, name = (str(WireWidth[i]) + "nm width")) SNSPDNeg.move([i* 1600, j*1600]) RectC.move([i* 1600, j*1600]) for i in range(5): t = gf.components.text(str( i+1 ) + " (" + str( FillingFactor[i] ) + "ff)", size = 50) text = Temp.add_ref(t) text.move([-800, i*1600 - 300]) Letters = ["A", "B", "C", "D", "E", "F"] for i in range(5): t = gf.components.text(str( Letters[i]) + " (" + str( WireWidth[i] ) + "nm)", size = 50) text = Temp.add_ref(t) text.move([i*1600 + 400, - 1000]) for i in range(4): for j in range(4): t = gf.components.text(str( Letters[j+1]) + str(i+2), size = 50) text = Temp.add_ref(t) text.move([j*1600 + 2000, i*1600 + 700]) TotalArea = c2.get_region(layer = (1,0)) TotalAreaOutline = TotalArea.sized(600) OnlyOutline = TotalAreaOutline - TotalArea Outline = Temp.add_polygon(OnlyOutline, layer = (1, 0)) Temp.show() Temp.plot() Temp.write_gds("C:/Users/alexa/OneDrive/Documenten/MyLIfeIsThereforMyLifeThinks/SNSPD Layouts/SNSPD_Chip_Aragog/Chip_Aragog.gds", with_metadata=False)