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)