Beispiel #1
0
def mzi1x2(
    L0: float = 0.1,
    DL: float = 9.0,
    L2: float = 10.0,
    bend_radius: float = 10.0,
    bend90_factory: Callable = bend_circular,
    straight_heater_factory: Callable = waveguide_heater,
    straight_factory: Callable = waveguide,
    coupler_factory: Callable = mmi1x2,
    with_elec_connections: bool = False,
) -> Component:
    """ Mzi 1x2

    Args:
        L0: vertical length for both and top arms
        DL: bottom arm extra length
        L2: L_top horizontal length
        bend_radius: 10.0
        bend90_factory: bend_circular
        straight_heater_factory: waveguide_heater or waveguide
        straight_factory: waveguide
        coupler_factory: coupler

    .. code::

             __L2__
            |      |
            L0     L0
            |      |
          --|      |--
            |      |
            L0     L0
            |      |
            DL     DL
            |      |
            |__L2__|


             top_arm
        -CP1=       =CP2-
             bot_arm


    .. plot::
      :include-source:

      import pp

      c = pp.c.mzi1x2(L0=0.1, DL=0, L2=10)
      pp.plotgds(c)

    """
    if not with_elec_connections:
        straight_heater_factory = straight_factory

    cpl = pp.call_if_func(coupler_factory)

    arm_defaults = {
        "L_top": L2,
        "bend_radius": bend_radius,
        "bend90_factory": bend90_factory,
        "straight_heater_factory": straight_heater_factory,
        "straight_factory": straight_factory,
        "with_elec_connections": with_elec_connections,
    }

    arm_top = mzi_arm(L0=L0, **arm_defaults)
    arm_bot = mzi_arm(L0=L0 + DL, **arm_defaults)

    components = {
        "CP1": (cpl, "None"),
        "CP2": (cpl, "mirror_y"),
        "arm_top": (arm_top, "None"),
        "arm_bot": (arm_bot, "mirror_x"),
    }

    connections = [
        # Bottom arm
        ("CP1", "E0", "arm_bot", "W0"),
        ("arm_bot", "E0", "CP2", "E0"),
        # Top arm
        ("CP1", "E1", "arm_top", "W0"),
        ("arm_top", "E0", "CP2", "E0"),
    ]

    if with_elec_connections:
        ports_map = {
            "W0": ("CP1", "W0"),
            "E0": ("CP2", "W0"),
            "E_TOP_0": ("arm_top", "E_0"),
            "E_TOP_1": ("arm_top", "E_1"),
            "E_TOP_2": ("arm_top", "E_2"),
            "E_TOP_3": ("arm_top", "E_3"),
            "E_BOT_0": ("arm_bot", "E_0"),
            "E_BOT_1": ("arm_bot", "E_1"),
            "E_BOT_2": ("arm_bot", "E_2"),
            "E_BOT_3": ("arm_bot", "E_3"),
        }

        component = netlist_to_component(components, connections, ports_map)
        # Need to connect common ground and redefine electrical ports

        ports = component.ports
        y_elec = ports["E_TOP_0"].y
        for ls, le in [
            ("E_BOT_0", "E_BOT_1"),
            ("E_TOP_0", "E_TOP_1"),
            ("E_BOT_2", "E_TOP_2"),
        ]:
            component.add_polygon(line(ports[ls], ports[le]),
                                  layer=ports[ls].layer)

        # Add GND
        ("E_BOT_2", "E_TOP_2")
        component.add_port(
            name="GND",
            midpoint=0.5 *
            (ports["E_BOT_2"].midpoint + ports["E_TOP_2"].midpoint),
            orientation=180,
            width=ports["E_BOT_2"].width,
            layer=ports["E_BOT_2"].layer,
        )

        component.ports["E_TOP_3"].orientation = 0
        component.ports["E_BOT_3"].orientation = 0

        # Remove the eletrical ports that we have just used internally
        for lbl in [
                "E_BOT_0", "E_BOT_1", "E_TOP_0", "E_TOP_1", "E_BOT_2",
                "E_TOP_2"
        ]:
            component.ports.pop(lbl)

        # Reroute electrical ports
        _e_ports = select_electrical_ports(component)
        conn, e_ports = route_elec_ports_to_side(_e_ports,
                                                 side="north",
                                                 y=y_elec)

        for c in conn:
            component.add(c)

        for p in e_ports:
            component.ports[p.name] = p

        # Create nice electrical port names
        component.ports["HT1"] = component.ports["E_TOP_3"]
        component.ports.pop("E_TOP_3")

        component.ports["HT2"] = component.ports["E_BOT_3"]
        component.ports.pop("E_BOT_3")

    else:
        ports_map = {"W0": ("CP1", "W0"), "E0": ("CP2", "W0")}
        component = netlist_to_component(components, connections, ports_map)

    return component
Beispiel #2
0
def wg_heater_connector(
    heater_ports: List[Port],
    metal_width: float = 10.0,
    tlm_layers: List[Tuple[int, int]] = [
        LAYER.VIA1,
        LAYER.M1,
        LAYER.VIA2,
        LAYER.M2,
        LAYER.VIA3,
        LAYER.M3,
    ],
) -> Component:
    """
    Connects together a pair of wg heaters and connect to a M3 port
    """

    cmp = Component()
    assert len(heater_ports) == 2
    assert (heater_ports[0].orientation == heater_ports[1].orientation
            ), "both ports should be facing in the same direction"
    angle = heater_ports[0].orientation
    angle = angle % 360
    assert angle in [0, 180], "angle should be 0 or 180, got {}".format(angle)

    dx = 0.0
    dy = 0.0

    angle_to_dps = {0: [(-dx, -dy), (-dx, dy)], 180: [(dx, -dy), (dx, dy)]}
    ports = heater_ports
    hw = heater_ports[0].width

    if angle in [0, 180]:
        ports.sort(key=lambda p: p.y)
    else:
        ports.sort(key=lambda p: p.x)

    _heater_to_metal = tlm(width=0.5, height=0.5, layers=tlm_layers, vias=[])

    tlm_positions = []
    for port, dp in zip(ports, angle_to_dps[angle]):
        # Extend heater
        p = port.midpoint

        # Add via/metal transitions
        tlm_pos = p + dp
        hm = _heater_to_metal.ref(position=tlm_pos)
        tlm_positions += [tlm_pos]
        cmp.add(hm)

    ss = 1 if angle == 0 else -1

    # Connect both sides with top metal
    edge_metal_piece_width = 7.0
    x = ss * edge_metal_piece_width / 2
    top_metal_layer = tlm_layers[-1]
    cmp.add_polygon(
        line(
            tlm_positions[0] + (x, -hw / 2),
            tlm_positions[1] + (x, hw / 2),
            edge_metal_piece_width,
        ),
        layer=top_metal_layer,
    )

    # Add metal port
    cmp.add_port(
        name="0",
        midpoint=0.5 * sum(tlm_positions) +
        (ss * edge_metal_piece_width / 2, 0),
        orientation=angle,
        width=metal_width,
        layer=top_metal_layer,
        port_type="dc",
    )

    return cmp
Beispiel #3
0
def mzi2x2(
    CL_1=20.147,
    L0=60,
    L1=7.38,
    L2=10.0,
    gap=0.234,
    bend_radius=10.0,
    bend90_factory=bend_circular,
    straight_heater_factory=waveguide_heater,
    straight_factory=waveguide,
    coupler_factory=coupler,
    with_elec_connections=True,
):
    """ Mzi 2x2

    Args:
        CL_1: coupler length
        L0: vertical length for both and top arms
        L1: bottom arm extra length
        L2: L_top horizontal length
        gap: 0.235
        bend_radius: 10.0
        bend90_factory: bend_circular
        straight_heater_factory: waveguide_heater or waveguide
        straight_factory: waveguide
        coupler_factory: coupler


    .. code::

         __L2__
        |      |
        L0     L0
        |      |
      ==|      |==
        |      |
        L0     L0
        |      |
        L1     L1
        |      |
        |__L2__|


    .. code::
        
               top_arm
        ==CL_1=       =CL_1===
               bot_arm


    .. plot::
      :include-source:

      import pp

      c = pp.c.mzi2x2(CL_1=10, gap=0.2)
      pp.plotgds(c)

    """

    if callable(coupler_factory):
        cpl = coupler_factory(length=CL_1, gap=gap)
    else:
        cpl = coupler_factory

    arm_defaults = {
        "L_top": L2,
        "bend_radius": bend_radius,
        "bend90_factory": bend90_factory,
        "straight_heater_factory": straight_heater_factory,
        "straight_factory": straight_factory,
        "with_elec_connections": with_elec_connections,
    }

    arm_top = mzi_arm(L0=L0, **arm_defaults)
    arm_bot = mzi_arm(L0=L0, L1=L1, **arm_defaults)

    components = {
        "CP1": (cpl, "None"),
        "CP2": (cpl, "None"),
        "arm_top": (arm_top, "None"),
        "arm_bot": (arm_bot, "mirror_x"),
    }

    connections = [
        ## Top arm
        ("CP1", "E1", "arm_top", "W0"),
        ("arm_top", "E0", "CP2", "W1"),
        ## Bottom arm
        ("CP1", "E0", "arm_bot", "W0"),
        ("arm_bot", "E0", "CP2", "W0"),
    ]

    if with_elec_connections:

        ports_map = {
            "W0": ("CP1", "W0"),
            "W1": ("CP1", "W1"),
            "E0": ("CP2", "E0"),
            "E1": ("CP2", "E1"),
            "E_TOP_0": ("arm_top", "E_0"),
            "E_TOP_1": ("arm_top", "E_1"),
            "E_TOP_2": ("arm_top", "E_2"),
            "E_TOP_3": ("arm_top", "E_3"),
            "E_BOT_0": ("arm_bot", "E_0"),
            "E_BOT_1": ("arm_bot", "E_1"),
            "E_BOT_2": ("arm_bot", "E_2"),
            "E_BOT_3": ("arm_bot", "E_3"),
        }

        component = netlist_to_component(components, connections, ports_map)
        # Need to connect common ground and redefine electrical ports

        ports = component.ports
        y_elec = ports["E_TOP_0"].y
        for ls, le in [
            ("E_BOT_0", "E_BOT_1"),
            ("E_TOP_0", "E_TOP_1"),
            ("E_BOT_2", "E_TOP_2"),
        ]:
            component.add_polygon(line(ports[ls], ports[le]), layer=ports[ls].layer)

        # Add GND
        component.add_port(
            name="GND",
            midpoint=0.5 * (ports["E_BOT_2"].midpoint + ports["E_TOP_2"].midpoint),
            orientation=180,
            width=ports["E_BOT_2"].width,
            layer=ports["E_BOT_2"].layer,
        )

        component.ports["E_TOP_3"].orientation = 0
        component.ports["E_BOT_3"].orientation = 0

        # Remove the eletrical ports that we have just used internally
        for lbl in ["E_BOT_0", "E_BOT_1", "E_TOP_0", "E_TOP_1", "E_BOT_2", "E_TOP_2"]:
            component.ports.pop(lbl)

        # Reroute electrical ports
        _e_ports = select_electrical_ports(component)
        conn, e_ports = route_elec_ports_to_side(_e_ports, side="north", y=y_elec)

        for c in conn:
            component.add(c)

        for p in e_ports:
            component.ports[p.name] = p

        # Create nice electrical port names
        component.ports["HT1"] = component.ports["E_TOP_3"]
        component.ports.pop("E_TOP_3")

        component.ports["HT2"] = component.ports["E_BOT_3"]
        component.ports.pop("E_BOT_3")

        # Make sure each port knows its name
        for k, p in component.ports.items():
            p.name = k

    elif straight_heater_factory == waveguide:
        ports_map = {
            "W0": ("CP1", "W0"),
            "W1": ("CP1", "W1"),
            "E0": ("CP2", "E0"),
            "E1": ("CP2", "E1"),
        }

        component = netlist_to_component(components, connections, ports_map)

    return component