luceda ipkiss教程 59:画圆形螺旋线2

案例分享:画同端口螺旋线
luceda ipkiss教程 59:画圆形螺旋线2_第1张图片
代码如下:

from si_fab import all as pdk
from ipkiss3 import all as i3
import numpy as np


class Spiral(i3.PCell):
    _name_prefix = "Spiral_C"
    width = i3.PositiveNumberProperty(
        doc="Core width of the bend waveguide", default=1.0
    )
    radius = i3.PositiveNumberProperty(
        doc="Horizontal length of the waveguide", default=20.0
    )
    decouple = i3.PositiveNumberProperty(
        doc="Separation between adjacent waveguides", default=2.0
    )
    length = i3.PositiveNumberProperty(
        doc="Length of the total snp.piral waveguide", default=4000.0
    )
    layout_properties = i3.NumpyArrayProperty(
        doc="Calculated layout properties of the snp.piral.", locked=True
    )

    def _default_layout_properties(self):
        r = self.radius
        w = self.width
        tot_sep = self.decouple + w
        b_val = 0.5 + 2.0 * r / tot_sep
        c_val = (4.0 * r + 0.5 * tot_sep - self.length / np.pi) / tot_sep
        n_o_loops_act = -b_val + np.sqrt(b_val**2.0 - c_val)
        n_o_loops = np.floor(n_o_loops_act)
        theta_nom = (
            self.length
            - 4.0 * r * np.pi * (1.0 + n_o_loops)
            - 0.5 * tot_sep * np.pi
            - (n_o_loops + n_o_loops**2.0) * tot_sep * np.pi
        )
        theta_denom = 4.0 * self.radius + (2.0 * n_o_loops + 2.0) * tot_sep
        theta_m = theta_nom / theta_denom
        dy0 = (
            (n_o_loops + 1.0) * tot_sep
            + (2.0 * r + tot_sep * 0.5) * (1.0 - np.cos(theta_m))
            + 2.0 * self.radius * np.cos(theta_m)
        )
        dx0 = tot_sep * 0.5 * np.sin(theta_m)
        radius_in = 2.0 * r + (2.0 * n_o_loops + 3.0) * tot_sep * 0.5
        radius_out = 2.0 * r + (2.0 * n_o_loops + 1.0) * tot_sep * 0.5
        return np.array(
            [r, w, tot_sep, n_o_loops, theta_m, dx0, dy0, radius_in, radius_out]
        )

    class Layout(i3.LayoutView):
        def _generate_instances(self, insts):
            (
                r,
                w,
                tot_sep,
                n_o_loops,
                theta_m,
                dx0,
                dy0,
                radius_in,
                radius_out,
            ) = self.layout_properties

            # snp.piral waveguide
            for index in range(int(n_o_loops + 2)):
                sign = 1.0 if index % 2 == 0 else -1.0
                if index == 0:
                    radius, dy = r, 0.0
                else:
                    radius, dy = (
                        2.0 * r + (2.0 * index - 1.0) * tot_sep * 0.5,
                        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 / np.pi)
                ) + i3.Translation(translation=(dx0, -dy0))
                if index == int(n_o_loops + 1):
                    if n_o_loops % 2 == 0:
                        insts += i3.SRef(wg2, transformation=transf)
                    else:
                        insts += i3.SRef(wg1, transformation=transf)
                else:
                    insts += i3.SRef(wg1, transformation=transf)
                    insts += i3.SRef(wg2, transformation=transf)

            # 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),
                    (radius_in * np.tan(theta_m / 2.0), 0.0),
                    (radius_in * np.sin(theta_m), -radius_in * (1.0 - np.cos(theta_m))),
                ]
                shape_wg_out = [
                    (0.0, -tot_sep),
                    (radius_out * np.tan(theta_m / 2.0), -tot_sep),
                    (
                        radius_out * np.sin(theta_m),
                        -tot_sep - radius_out * (1.0 - np.cos(theta_m)),
                    ),
                ]
            else:
                shape_wg_in = [
                    (0.0, 0.0),
                    (radius_in, 0.0),
                    (radius_in, -radius_in),
                    (
                        radius_in,
                        -radius_in - radius_in * np.tan((theta_m - np.pi / 2.0) / 2.0),
                    ),
                    (radius_in * np.sin(theta_m), -radius_in * (1.0 - np.cos(theta_m))),
                ]
                shape_wg_out = [
                    (0.0, -tot_sep),
                    (radius_out, -tot_sep),
                    (radius_out, -tot_sep - radius_out),
                    (
                        radius_out,
                        -tot_sep
                        - radius_out
                        - radius_out * np.tan((theta_m - np.pi / 2.0) / 2.0),
                    ),
                    (
                        radius_out * np.sin(theta_m),
                        -tot_sep - radius_out * (1.0 - np.cos(theta_m)),
                    ),
                ]

            wg_in.Layout(
                bend_radius=radius_in,
                shape=shape_wg_in,
            )
            wg_out.Layout(
                bend_radius=radius_out,
                shape=shape_wg_out,
            )
            insts += i3.SRef(wg_in, name="wg_in")
            insts += i3.SRef(wg_out, name="wg_out")

            return insts

        def _generate_ports(self, ports):
            w = self.layout_properties[1]
            tot_sep = self.layout_properties[2]
            ports += i3.OpticalPort(
                name="in0",
                position=(0.0, 0.0),
                angle=180.0,
                trace_template=pdk.SWG450(),
            )
            ports += i3.OpticalPort(
                name="out0",
                position=(0.0, -tot_sep),
                angle=180.0,
                trace_template=pdk.SWG450(),
            )
            return ports


if __name__ == "__main__":
    Spiral().Layout().visualize(legacy=True, annotate=True)

你可能感兴趣的:(光子集成线路设计,ipkiss,python,开发语言)