最近发现ipkiss中有个非常有用功能IoFibcoupGeneric,用它可以快速地给线路添加光栅耦合器或者端面耦合器,效果如下:
代码如下:
from si_fab import all as pdk
from ipkiss3 import all as i3
class MZI(i3.Circuit):
coupler = i3.ChildCellProperty(doc="The coupler used for the MZI")
phase_shifter = i3.ChildCellProperty(doc="The class used for the phase shifter")
x_separation = i3.PositiveNumberProperty(default=20, doc="The separation between the couplers and the heater")
heater_length = i3.PositiveNumberProperty(default=30, doc="The length of the heater")
def _default_coupler(self):
return pdk.SiDirectionalCouplerSPower(name=self.name + "_coupler")
def _default_phase_shifter(self):
trace_template = pdk.SWG450()
phase_shifter = pdk.HeatedWaveguide(name=self.name + "_phase_shifter", trace_template=trace_template, )
phase_shifter.Layout(shape=[(0, 0), (self.heater_length, 0)])
return phase_shifter
def _default_insts(self):
return {
"coupler_in": self.coupler,
"coupler_out": self.coupler,
"phase_shifter": self.phase_shifter,
}
def _default_specs(self):
return [
i3.Place("coupler_in:in1", (0, 0)),
i3.PlaceRelative(
"phase_shifter:in",
"coupler_in:out1",
(self.x_separation, 0),
),
i3.PlaceRelative(
"coupler_out:in1",
"phase_shifter:out",
(self.x_separation, 0),
),
i3.ConnectManhattan(
"phase_shifter:in",
"coupler_in:out1",
min_straight=0,
),
i3.ConnectManhattan(
"phase_shifter:out",
"coupler_out:in1",
min_straight=0,
),
i3.ConnectManhattan(
"coupler_in:out2",
"coupler_out:in2",
min_straight=0,
),
]
def _default_exposed_ports(self):
return {
"coupler_in:in1": "in1",
"coupler_in:in2": "in2",
"coupler_out:out1": "out1",
"coupler_out:out2": "out2",
"phase_shifter:elec1": "elec1",
"phase_shifter:elec2": "elec2",
}
class Five_MZI(i3.Circuit):
mzi = i3.ChildCellProperty(doc="The coupler used for the MZI")
x_separation = i3.PositiveNumberProperty(default=20, doc="The separation between the couplers and the heater")
heater_length = i3.PositiveNumberProperty(default=30, doc="The length of the heater")
x_st = i3.PositiveNumberProperty(default=400)
y_st = i3.PositiveNumberProperty(default=100)
bend_radius = i3.PositiveNumberProperty(default=50)
def _default_mzi(self):
return MZI(x_separation=self.x_separation, heater_length=self.heater_length)
def _default_insts(self):
return {
"mzi1": self.mzi,
"mzi2": self.mzi,
"mzi3": self.mzi,
"mzi4": self.mzi,
"mzi5": self.mzi,
}
def _default_specs(self):
return [
i3.Place("mzi1:in1", (0, 0)),
i3.PlaceRelative(
"mzi2:in1",
"mzi1:in1",
(0, self.y_st),
),
i3.PlaceRelative(
"mzi3:in1",
"mzi1:in1",
(self.x_st, -self.y_st / 2),
),
i3.PlaceRelative(
"mzi4:in1",
"mzi3:in1",
(0, self.y_st),
),
i3.PlaceRelative(
"mzi5:in1",
"mzi4:in1",
(0, self.y_st),
),
i3.ConnectBend(
"mzi1:out1",
"mzi3:in2",
bend_radius=self.bend_radius
),
i3.ConnectBend(
"mzi1:out2",
"mzi4:in1",
bend_radius=self.bend_radius
),
i3.ConnectBend(
"mzi2:out1",
"mzi4:in2",
bend_radius=self.bend_radius
),
i3.ConnectBend(
"mzi2:out2",
"mzi5:in1",
bend_radius=self.bend_radius
),
]
def _default_exposed_ports(self):
return {
"mzi1:in1": "in1",
"mzi1:in2": "in2",
"mzi2:in1": "in3",
"mzi2:in2": "in4",
"mzi3:out1": "out1",
"mzi3:out2": "out2",
"mzi4:out1": "out3",
"mzi4:out2": "out4",
"mzi5:out1": "out5",
"mzi5:out2": "out6",
}
if __name__ == '__main__':
demo = Five_MZI(x_separation=20, heater_length=40)
demo.Layout().visualize(annotate=False)
from picazzo3.container.iofibcoup import IoFibcoup
iofb = IoFibcoup(contents=demo)
iofb_layout = iofb.Layout()
iofb_layout.visualize(annotate=False)
发现只要
from picazzo3.container.iofibcoup import IoFibcoup
iofb = IoFibcoup(contents=demo)
iofb_layout = iofb.Layout()
iofb_layout.visualize(annotate=False)
这4行代码,就给线路中悬空的端口加上了光栅耦合器,并且能自动匹配光栅耦合器的数量。
如果要调整光栅耦合器的位置或者间距,可以这样,先看代码:
from picazzo3.container.iofibcoup import IoFibcoupGeneric
iofb = IoFibcoupGeneric(contents=demo)
y_space_east = 127
y0_east = -200
y_space_west = 127
y0_west = -100
iofb_layout = iofb.Layout(
south_west=(1000.0, 0.0),
south_east=(2000.0, 0.0),
east_fiber_coupler_transformations=[
i3.HMirror() + i3.Translation((0.0, y0_east)),
i3.HMirror() + i3.Translation((0.0, y0_east + y_space_east - 25)),
i3.HMirror() + i3.Translation((0.0, y0_east + (y_space_east - 25) * 2)),
i3.HMirror() + i3.Translation((0.0, y0_east + (y_space_east - 25) * 3)),
i3.HMirror() + i3.Translation((0.0, y0_east + (y_space_east - 25) * 4)),
i3.HMirror() + i3.Translation((0.0, y0_east + (y_space_east - 25) * 5)),
],
west_fiber_coupler_transformations=[
i3.Translation((0.0, y0_west)),
i3.Translation((0.0, y0_west + y_space_west - 25)),
i3.Translation((0.0, y0_west + (y_space_west - 25) * 2)),
i3.Translation((0.0, y0_west + (y_space_west - 25) * 3)),
],
)
iofb_layout.visualize(annotate=False,legacy=True)
用上面替换原代码中的最后四行后,运行结果为:
通过:
y_space_east = 127
y0_east = -200
y_space_west = 127
y0_west = -100
可以调整东西边最底下光栅的y轴坐标,以及两边光栅的间距。
光栅x轴位置可以通过:
south_west=(1000.0, 0.0),
south_east=(2000.0, 0.0),
调整
那么怎么改变耦合器的类型呢,比如不是接光栅耦合器而是端面耦合器
代码如下:
from si_fab import all as pdk
from ipkiss3 import all as i3
class MZI(i3.Circuit):
coupler = i3.ChildCellProperty(doc="The coupler used for the MZI")
phase_shifter = i3.ChildCellProperty(doc="The class used for the phase shifter")
x_separation = i3.PositiveNumberProperty(default=20, doc="The separation between the couplers and the heater")
heater_length = i3.PositiveNumberProperty(default=30, doc="The length of the heater")
def _default_coupler(self):
return pdk.SiNDirectionalCouplerSPower(name=self.name + "_coupler")
def _default_phase_shifter(self):
trace_template = pdk.SiNWireWaveguideTemplate()
phase_shifter = pdk.HeatedWaveguide(name=self.name + "_phase_shifter", trace_template=trace_template, )
phase_shifter.Layout(shape=[(0, 0), (self.heater_length, 0)])
return phase_shifter
def _default_insts(self):
return {
"coupler_in": self.coupler,
"coupler_out": self.coupler,
"phase_shifter": self.phase_shifter,
}
def _default_specs(self):
return [
i3.Place("coupler_in:in1", (0, 0)),
i3.PlaceRelative(
"phase_shifter:in",
"coupler_in:out1",
(self.x_separation, 0),
),
i3.PlaceRelative(
"coupler_out:in1",
"phase_shifter:out",
(self.x_separation, 0),
),
i3.ConnectManhattan(
"phase_shifter:in",
"coupler_in:out1",
min_straight=0,
),
i3.ConnectManhattan(
"phase_shifter:out",
"coupler_out:in1",
min_straight=0,
),
i3.ConnectManhattan(
"coupler_in:out2",
"coupler_out:in2",
min_straight=0,
),
]
def _default_exposed_ports(self):
return {
"coupler_in:in1": "in1",
"coupler_in:in2": "in2",
"coupler_out:out1": "out1",
"coupler_out:out2": "out2",
"phase_shifter:elec1": "elec1",
"phase_shifter:elec2": "elec2",
}
class Five_MZI(i3.Circuit):
mzi = i3.ChildCellProperty(doc="The coupler used for the MZI")
x_separation = i3.PositiveNumberProperty(default=20, doc="The separation between the couplers and the heater")
heater_length = i3.PositiveNumberProperty(default=30, doc="The length of the heater")
x_st = i3.PositiveNumberProperty(default=400)
y_st = i3.PositiveNumberProperty(default=200)
bend_radius = i3.PositiveNumberProperty(default=50)
def _default_mzi(self):
return MZI(x_separation=self.x_separation, heater_length=self.heater_length)
def _default_insts(self):
return {
"mzi1": self.mzi,
"mzi2": self.mzi,
"mzi3": self.mzi,
"mzi4": self.mzi,
"mzi5": self.mzi,
}
def _default_specs(self):
return [
i3.Place("mzi1:in1", (0, 0)),
i3.PlaceRelative(
"mzi2:in1",
"mzi1:in1",
(0, self.y_st),
),
i3.PlaceRelative(
"mzi3:in1",
"mzi1:in1",
(self.x_st, -self.y_st / 2),
),
i3.PlaceRelative(
"mzi4:in1",
"mzi3:in1",
(0, self.y_st),
),
i3.PlaceRelative(
"mzi5:in1",
"mzi4:in1",
(0, self.y_st),
),
i3.ConnectBend(
"mzi1:out1",
"mzi3:in2",
bend_radius=self.bend_radius
),
i3.ConnectBend(
"mzi1:out2",
"mzi4:in1",
bend_radius=self.bend_radius
),
i3.ConnectBend(
"mzi2:out1",
"mzi4:in2",
bend_radius=self.bend_radius
),
i3.ConnectBend(
"mzi2:out2",
"mzi5:in1",
bend_radius=self.bend_radius
),
]
def _default_exposed_ports(self):
return {
"mzi1:in1": "in1",
"mzi1:in2": "in2",
"mzi2:in1": "in3",
"mzi2:in2": "in4",
"mzi3:out1": "out1",
"mzi3:out2": "out2",
"mzi4:out1": "out3",
"mzi4:out2": "out4",
"mzi5:out1": "out5",
"mzi5:out2": "out6",
}
if __name__ == '__main__':
demo = Five_MZI(x_separation=20, heater_length=40)
from picazzo3.container.iofibcoup import IoFibcoupGeneric
iofb = IoFibcoupGeneric(
contents=demo,
east_trace_templates=[pdk.SiNWireWaveguideTemplate()], # trace template for East fanout
west_trace_templates=[pdk.SiNWireWaveguideTemplate()], # trace_template for West fanout
east_connect_trace_templates=[pdk.SiNWireWaveguideTemplate()], # trace template for wide connections
west_connect_trace_templates=[pdk.SiNWireWaveguideTemplate()], # trace template for wide connections
east_fiber_couplers=[pdk.SiNInvertedTaper()],
west_fiber_couplers=[pdk.SiNInvertedTaper()],
)
y_space_east = 127
y0_east = -200
y_space_west = 127
y0_west = -100
iofb_layout = iofb.Layout(
south_west=(-100.0, 0.0),
south_east=(1200.0, 0.0),
east_fiber_coupler_transformations=[
i3.HMirror() + i3.Translation((0.0, y0_east)),
i3.HMirror() + i3.Translation((0.0, y0_east + y_space_east - 25)),
i3.HMirror() + i3.Translation((0.0, y0_east + (y_space_east - 25) * 2)),
i3.HMirror() + i3.Translation((0.0, y0_east + (y_space_east - 25) * 3)),
i3.HMirror() + i3.Translation((0.0, y0_east + (y_space_east - 25) * 4)),
i3.HMirror() + i3.Translation((0.0, y0_east + (y_space_east - 25) * 5)),
],
west_fiber_coupler_transformations=[
i3.Translation((0.0, y0_west)),
i3.Translation((0.0, y0_west + y_space_west - 25)),
i3.Translation((0.0, y0_west + (y_space_west - 25) * 2)),
i3.Translation((0.0, y0_west + (y_space_west - 25) * 3)),
],
)
iofb_layout.visualize(annotate=False, legacy=True)
首先,将线路中的硅波导替换到了氮化硅波导,这只需要在MZI中替换dc以及trace_template
def _default_coupler(self):
return pdk.SiNDirectionalCouplerSPower(name=self.name + "_coupler")
def _default_phase_shifter(self):
trace_template = pdk.SiNWireWaveguideTemplate()
phase_shifter = pdk.HeatedWaveguide(name=self.name + "_phase_shifter", trace_template=trace_template, )
phase_shifter.Layout(shape=[(0, 0), (self.heater_length, 0)])
return phase_shifter
最后只要设置一下的这些IoFibcoupGeneric属性:
iofb = IoFibcoupGeneric(
contents=demo,
east_trace_templates=[pdk.SiNWireWaveguideTemplate()], # trace template for East fanout
west_trace_templates=[pdk.SiNWireWaveguideTemplate()], # trace_template for West fanout
east_connect_trace_templates=[pdk.SiNWireWaveguideTemplate()], # trace template for wide connections
west_connect_trace_templates=[pdk.SiNWireWaveguideTemplate()], # trace template for wide connections
east_fiber_couplers=[pdk.SiNInvertedTaper()],
west_fiber_couplers=[pdk.SiNInvertedTaper()],
)
就可以自动连上端面耦合器:
耦合器的类型可以通过这两个参数调整:
east_fiber_couplers=[pdk.SiNInvertedTaper()],
west_fiber_couplers=[pdk.SiNInvertedTaper()],