luceda ipkiss教程 28:画圆形螺旋线

案例分享:利用ipkiss画圆形螺旋线
在这里插入图片描述
全部代码如下:

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=0.5)
    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:
                    radius = r
                    dy = 0.0
                else:
                    radius = 2.0 * r + (2.0 * index - 1.0) * tot_sep * 0.5
                    dy = 2.0 * r + (index - 1.0) * tot_sep
                shape_wg1 = [
                    (0.0, -sign * dy),
                    (sign * radius, -sign * dy),
                    (sign * radius, -sign * (dy - radius)),
                    (sign * radius, -sign * (dy - 2.0 * radius)),
                    (0.0, -sign * (dy - 2.0 * radius)),
                ]
                shape_wg2 = [
                    (0.0, sign * dy),
                    (-sign * radius, sign * dy),
                    (-sign * radius, sign * (dy - radius)),
                    (-sign * radius, sign * (dy - 2.0 * radius)),
                    (0.0, sign * (dy - 2.0 * radius)),
                ]
                wg1 = i3.RoundedWaveguide(trace_template=pdk.SWG450())
                wg2 = i3.RoundedWaveguide(trace_template=pdk.SWG450())
                wg1.Layout(bend_radius=radius, shape=shape_wg1)
                wg2.Layout(bend_radius=radius, shape=shape_wg2)
                transf = i3.Rotation(rotation=theta_m * (-180.0 / pi)) + i3.Translation(translation=(dx0, -dy0))
                insts += i3.SRef(wg1, transformation=transf, flatten=True)
                insts += i3.SRef(wg2, transformation=transf, flatten=True)

            # output waveguides
            wg_in = i3.RoundedWaveguide(trace_template=pdk.SWG450())
            wg_out = i3.RoundedWaveguide(trace_template=pdk.SWG450())
            if theta_m <= np.pi / 2.0:
                shape_wg_in = [
                    (0.0, 0.0),
                    (r_out * np.tan(theta_m / 2.0), 0.0),
                    (r_out * np.sin(theta_m), -r_out * (1.0 - np.cos(theta_m))),
                ]
                shape_wg_out = [
                    (2 * dx0, -2 * dy0),
                    (2 * dx0 - r_out * np.tan(theta_m / 2.0), -2 * dy0),
                    (
                        2 * dx0 - r_out * np.sin(theta_m),
                        -2 * dy0 + r_out * (1.0 - np.cos(theta_m)),
                    ),
                ]
            else:
                shape_wg_in = [
                    (0.0, 0.0),
                    (r_out, 0.0),
                    (r_out, -r_out),
                    (r_out, -r_out - r_out * np.tan((theta_m - pi / 2.0) / 2.0)),
                    (r_out * np.sin(theta_m), -r_out * (1.0 - np.cos(theta_m))),
                ]
                shape_wg_out = [
                    (2 * dx0, -2 * dy0),
                    (2 * dx0 - r_out, -2 * dy0),
                    (2 * dx0 - r_out, -2 * dy0 + r_out),
                    (
                        2 * dx0 - r_out,
                        -2 * dy0 + r_out + r_out * np.tan((theta_m - pi / 2.0) / 2.0),
                    ),
                    (
                        2 * dx0 - r_out * np.sin(theta_m),
                        -2 * dy0 + r_out * (1.0 - np.cos(theta_m)),
                    ),
                ]
            wg_in.Layout(bend_radius=r_out, shape=shape_wg_in)
            wg_out.Layout(bend_radius=r_out, shape=shape_wg_out)
            insts += i3.SRef(wg_in, name="wg_in", flatten=True)
            insts += i3.SRef(wg_out, name="wg_out", flatten=True)
            return insts

        def _generate_ports(self, ports):
            ports += i3.expose_ports(
                self.instances,
                {
                    "wg_in:in": "opt1",
                    "wg_out:in": "opt2",
                },
            )
            return ports

    class Netlist(i3.NetlistFromLayout):
        pass

if __name__ == '__main__':
    SpiralCircular().Layout().visualize()




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值