Archimedian Spiral

This is a spiral where the distance between the waveguide is constant and with a linear increase in radius of curvature to keep equal spacing.

../_images/sphx_glr_plot_archimedian_spiral_001.png
import demolib.all as pdk
from ipkiss3 import all as i3
import numpy as np


class _ShapeParallelSpiral(i3.StrongPropertyInitializer):
    radius = i3.PositiveNumberProperty(default=5.0, doc="minimum bend radius")
    clockwise = i3.BoolProperty(default=True, doc="Orientation")
    angle_step = i3.AngleProperty(default=1.0, doc="angular step, in degrees")
    step = i3.PositiveNumberProperty(default=2.0, doc="increase in radius over a full circle")
    straights = i3.Size2Property(default=(0, 0), doc="Horizontal and vertical straight section")


class ShapeParallelSpiralHeart(_ShapeParallelSpiral, i3.Shape):

    def define_points(self, pts):
        N = int(np.ceil(90.0 / self.angle_step)) + 1
        r = self.radius
        st = self.step / 2.0
        hx = 0.5 * self.straights[0]
        hy = 0.5 * self.straights[1]
        if self.clockwise:
            sig = +1
        else:
            sig = -1
        angles = np.linspace(0.0, 0.5 * np.pi, N)

        p1 = np.transpose([r + hx + (r + st) * np.cos(angles),
                           sig * (hy + (r + st) * np.sin(angles))])
        p2 = np.transpose([r - r * np.cos(angles),
                           sig * (hy + st + r * np.sin(angles))])
        p3 = np.transpose([-r + r * np.cos(angles),
                           sig * (-hy + st - r * np.sin(angles))])
        p4 = np.transpose([-r - hx - (r + st) * np.cos(-angles),
                           sig * (-hy + 2 * st - (r + st) * np.sin(angles))])
        p5 = np.transpose([-r - hx - (r + st) * np.cos(-angles),
                           sig * (hy + 2 * st + (r + st) * np.sin(angles))])
        p6 = np.transpose([r + hx + (r + 3 * st) * np.cos(angles),
                           sig * (hy + (r + 3 * st) * np.sin(angles))])

        return np.vstack([p1, np.flipud(p2), p3, np.flipud(p4), p5, np.flipud(p6)])


class ShapeParallelSpiralLoop(_ShapeParallelSpiral, i3.Shape):
    def define_points(self, pts):
        N = int(np.ceil(90.0 / self.angle_step)) + 1
        r = self.radius
        st = self.step / 2.0
        hx = 0.5 * self.straights[0]
        hy = 0.5 * self.straights[1]

        if self.clockwise:
            sig = +1
        else:
            sig = -1
        angles = np.linspace(0.0, 0.5 * np.pi, N)

        p1 = np.transpose([hx + r * np.cos(angles),
                           sig * (-hy - r * np.sin(angles))])
        p2 = np.transpose([- hx - (r + st) * np.cos(angles),
                           sig * (-hy + st - (r + st) * np.sin(angles))])
        p3 = np.transpose([-hx - (r + st) * np.cos(angles),
                           sig * (hy + st + (r + st) * np.sin(angles))])
        p4 = np.transpose([hx + (r + 2 * st) * np.cos(-angles),
                           sig * (hy + (r + 2 * st) * np.sin(angles))])
        return np.vstack([p1, np.flipud(p2), p3, np.flipud(p4)])


class ShapeDoubleParallelSpiral(_ShapeParallelSpiral, i3.Shape):
    n_o_loops = i3.PositiveIntProperty(default=3)

    def define_points(self, pts):
        pts_list = [ShapeParallelSpiralHeart(radius=self.radius,
                                             straights=self.straights,
                                             clockwise=self.clockwise,
                                             step=self.step,
                                             angle_step=self.angle_step).points
                    ]
        straights = (2 * self.radius + self.straights[0], self.straights[1])
        pts_list2 = []
        for i in range(0, self.n_o_loops - 1):
            radius = self.radius + (2 * i + 1.5) * self.step
            pts_list += [ShapeParallelSpiralLoop(radius=radius,
                                                 straights=straights,
                                                 clockwise=self.clockwise,
                                                 step=2 * self.step,
                                                 angle_step=self.angle_step).points
                         ]
            radius = self.radius + (2 * i + 0.5) * self.step
            pts_list2 += [np.flipud(ShapeParallelSpiralLoop(radius=radius,
                                                            straights=straights,
                                                            clockwise=self.clockwise,
                                                            step=2 * self.step,
                                                            angle_step=self.angle_step).points)
                          ]

        pts_list2.reverse()

        return np.vstack(pts_list2 + pts_list)


class ArchimedianSpiral(i3.Waveguide):

    _name_prefix = "ARCHIMEDIAN_SPIRAL"
    n_o_loops = i3.PositiveIntProperty(default=3)

    class Layout(i3.Waveguide.Layout, _ShapeParallelSpiral):

        def _default_shape(self):

            return ShapeDoubleParallelSpiral(n_o_loops=self.n_o_loops,
                                             radius=self.radius,
                                             clockwise=self.clockwise,
                                             angle_step=self.angle_step,
                                             step=self.step,
                                             straights=self.straights
                                             )

cell = ArchimedianSpiral()
lv = cell.Layout(step=5.0,
                 radius=20.0,
                 straights=(0, 0))
lv.visualize(annotate=True)
lv.write_gdsii("archimedian_spiral.gds")