Directional Coupler Bend

Full script

from typing import Tuple, cast
from fnpcell import all as fp
from gpdk.components.bend.bend_circular import BendCircular
from gpdk.components.straight.straight import Straight
from gpdk.technology import get_technology
from gpdk.technology.interfaces import CoreCladdingWaveguideType

@fp.pcell_class()

class DirectionalCouplerBend(fp.PCell):
    coupler_spacing: float = fp.PositiveFloatParam(default=0.7, doc="Spacing between the two waveguide centre lines.").as_field()
    coupler_length: float = fp.PositiveFloatParam(default=6, doc="Length of the directional coupler").as_field()
    bend_radius: float = fp.PositiveFloatParam(required=False, doc="Bend radius for the auto-generated bends").as_field()
    straight_after_bend: float = fp.PositiveFloatParam(default=6, doc="Length of the straight waveguide after the bend").as_field()
    waveguide_type: CoreCladdingWaveguideType = fp.WaveguideTypeParam(type=CoreCladdingWaveguideType, doc="Waveguide parameters").as_field()
    port_names: fp.IPortOptions = fp.PortOptionsParam(count=4, default=["op_0", "op_1", "op_2", "op_3"]).as_field()

    def _default_waveguide_type(self):
        return get_technology().WG.FWG.C.WIRE

    def build(self) -> Tuple[fp.InstanceSet, fp.ElementSet, fp.PortSet]:
        insts, elems, ports = super().build()
        # fmt: off
        coupler_spacing = self.coupler_spacing
        coupler_length = self.coupler_length
        bend_radius = self.bend_radius
        straight_after_bend = self.straight_after_bend
        waveguide_type = self.waveguide_type
        port_names = self.port_names

        if bend_radius is None:
            bend_radius = cast(float, waveguide_type.BEND_CIRCULAR.radius_eff) # type: ignore

        assert (
            coupler_spacing > waveguide_type.core_width
        ), "waveguide core overlap: coupler spacing must be greater than core_width"

        dy = coupler_spacing / 2

        left_straight_after_bend = Straight(name="lafterbend", length=straight_after_bend, waveguide_type=waveguide_type)
        right_straight_after_bend = Straight(name="rafterbend", length=straight_after_bend, waveguide_type=waveguide_type)
        left_bend = BendCircular(name="lbend", degrees=90, radius=bend_radius, waveguide_type=waveguide_type)
        right_bend = BendCircular(name="rbend", degrees=90, radius=bend_radius, waveguide_type=waveguide_type)
        straight_coupler = Straight(name="coupler", length=coupler_length, anchor=fp.Anchor.CENTER, waveguide_type=waveguide_type, transform=fp.translate(0, -dy))

        bottom_half = fp.Connected(
            name="bottom",
            joints=[
                straight_coupler["op_0"] <= left_bend["op_0"],
                left_bend["op_1"] <= left_straight_after_bend["op_1"],
                #
                straight_coupler["op_1"] <= right_bend["op_1"],
                right_bend["op_0"] <= right_straight_after_bend["op_0"],
            ],
            ports=[
                left_straight_after_bend["op_0"],
                right_straight_after_bend["op_1"],
            ],
        )
        insts += bottom_half
        top_half = bottom_half.rotated(degrees=180)
        insts += top_half
        ports += top_half["op_1"].with_name(port_names[0])
        ports += bottom_half["op_0"].with_name(port_names[1]),
        ports += bottom_half["op_1"].with_name(port_names[2]),
        ports += top_half["op_0"].with_name(port_names[3]),

        # fmt: on
        return insts, elems, ports

if __name__ == "__main__":
    from pathlib import Path
    gds_file = Path(__file__).parent / "local" / Path(__file__).with_suffix(".gds").name
    library = fp.Library()
    TECH = get_technology()
    # library += DirectionalCouplerBend()
    # library += DirectionalCouplerBend(name="f", coupler_spacing=0.7, coupler_length=6, bend_radius=10, straight_after_bend=6, waveguide_type=TECH.WG.FWG.C.WIRE)
    library += DirectionalCouplerBend(name="s", coupler_spacing=1.7, coupler_length=10, bend_radius=10, straight_after_bend=6, waveguide_type=TECH.WG.SWG.C.WIRE)

    fp.export_gds(library, file=gds_file)
    fp.plot(library)

Parameter description

In the main function, add a DirectionalCouplerBend to the library

library += DirectionalCouplerBend(name="s", coupler_spacing=1.7, coupler_length=10, bend_radius=10, straight_after_bend=6, waveguide_type=TECH.WG.SWG.C.WIRE)

name is the name of the device, here named s, coupler_space, coupler_length, bend_radius and straight_after_bend are marked in the figure below, which is convenient to quickly understand which part of the device is controlled by each parameter.

../_images/5.1.png