案例分享:画多端口螺旋线
注:spiral的长度不是真实长度,具体可以参考教程28
代码如下:
from si_fab import all as pdk
import ipkiss3.all as i3
import numpy as np
from scipy.constants import pi
class SpiralCircular(i3.PCell):
core_width = i3.PositiveNumberProperty(doc="Core width of the bend waveguide", default=0.4)
radius = i3.PositiveNumberProperty(doc="Radius of the central bends", default=5.0)
spacing = i3.PositiveNumberProperty(doc="Separation between adjacent waveguides", default=2)
spiral_length = i3.PositiveNumberProperty(doc="Length of the total spiral waveguide", default=1000.0)
layout_properties = i3.NumpyArrayProperty(doc="Calculated layout properties of the spiral.", locked=True)
def _default_layout_properties(self):
r = self.radius
tot_sep = self.spacing + self.core_width
n_o_loops_act = -(2.0 * r / tot_sep) + np.sqrt(
(2.0 * r / tot_sep) ** 2.0 - ((2.0 * r - self.spiral_length / pi) / tot_sep)
)
n_o_loops = np.floor(n_o_loops_act)
theta_nom = self.spiral_length - 2.0 * r * pi * (2.0 * n_o_loops + 1.0) - (n_o_loops ** 2.0) * tot_sep * pi
theta_denom = 4.0 * r + (2.0 * n_o_loops + 1.0) * tot_sep
theta_m = theta_nom / theta_denom
r_out = 2.0 * r + (n_o_loops + 0.5) * tot_sep
dx0 = tot_sep * 0.5 * np.sin(theta_m)
dy0 = r_out * (1.0 - np.cos(theta_m)) + (r_out - 0.5 * tot_sep) * np.cos(theta_m)
return np.array([r, tot_sep, n_o_loops, theta_m, r_out, dx0, dy0])
class Layout(i3.LayoutView):
def _generate_elements(self, elems):
for p in self.ports:
elems += i3.Label(
text=p.name,
layer=i3.TECH.PPLAYER.DOC,
coordinate=p.position,
height=5.0,
)
return elems
def _generate_instances(self, insts):
r = self.layout_properties[0]
tot_sep = self.layout_properties[1]
n_o_loops = self.layout_properties[2]
theta_m = self.layout_properties[3]
r_out = self.layout_properties[4]
dx0 = self.layout_properties[5]
dy0 = self.layout_properties[6]
# spiral waveguide
for index in range(int(n_o_loops + 1)):
sign = 1.0 if index % 2 == 0 else -1.0
if index == 0:
radius1 = r
dy1 = 0.0
radius2 = r
dy2 = 0.0
radius3 = r - 0.8
dy3 = 0.0 - 0.8
radius4 = r + 0.8
dy4 = 0.0 + 0.8
else:
radius1 = 2.0 * r + (2.0 * index - 1.0) * tot_sep * 0.5
dy1 = 2.0 * r + (index - 1.0) * tot_sep
radius2 = 2.0 * r + (2.0 * index - 1.0) * tot_sep * 0.5
dy2 = 2.0 * r + (index - 1.0) * tot_sep
radius3 = 2.0 * r + (2.0 * index - 1.0) * tot_sep * 0.5-0.8
dy3 = 2.0 * r + (index - 1.0) * tot_sep-0.8
radius4 = 2.0 * r + (2.0 * index - 1.0) * tot_sep * 0.5+0.8
dy4 = 2.0 * r + (index - 1.0) * tot_sep+0.8
shape_wg1 = [
(0.0, -sign * dy1),
(sign * radius1, -sign * dy1),
(sign * radius1, -sign * (dy1 - radius1)),
(sign * radius1, -sign * (dy1 - 2.0 * radius1)),
(0.0, -sign * (dy1 - 2.0 * radius1)),
]
shape_wg2 = [
(0.0, sign * dy2),
(-sign * radius2, sign * dy2),
(-sign * radius2, sign * (dy2 - radius2)),
(-sign * radius2, sign * (dy2 - 2.0 * radius2)),
(0.0, sign * (dy2 - 2.0 * radius2)),
]
shape_wg3 = [
(0.0, -sign * dy3),
(sign * radius3, -sign * dy3),
(sign * radius3, -sign * (dy3 - radius3)),
(sign * radius3, -sign * (dy3 - 2.0 * radius3)),
(0.0, -sign * (dy3 - 2.0 * radius3)),
]
shape_wg4 = [
(0.0, sign * dy4),
(-sign * radius4, sign * dy4),
(-sign * radius4, sign * (dy4 - radius4)),
(-sign * radius4, sign * (dy4 - 2.0 * radius4)),
(0.0, sign * (dy4 - 2.0 * radius4)),
]
wg1 = i3.RoundedWaveguide(trace_template=pdk.SWG450())
wg2 = i3.RoundedWaveguide(trace_template=pdk.SWG450())
wg3 = i3.RoundedWaveguide(trace_template=pdk.SWG450())
wg4 = i3.RoundedWaveguide(trace_template=pdk.SWG450())
wg1.Layout(bend_radius=radius1, shape=shape_wg1)
wg2.Layout(bend_radius=radius2, shape=shape_wg2)
wg3.Layout(bend_radius=radius3, shape=shape_wg3)
wg4.Layout(bend_radius=radius4, shape=shape_wg4)
insts += i3.SRef(wg1, flatten=True)
insts += i3.SRef(wg2, flatten=True)
insts += i3.SRef(wg3, flatten=True)
insts += i3.SRef(wg4, flatten=True)
return insts
if __name__ == '__main__':
SpiralCircular().Layout().visualize(legacy=True)