Esempio n. 1
0
def test_path_length_matching_nb_loops():
    c = pp.Component("path_length_match_sample")

    dy = 2000.0
    xs1 = [-500, -300, -100, -90, -80, -55, -35, 200, 210, 240, 500, 650]

    pitch = 100.0
    N = len(xs1)
    xs2 = [-20 + i * pitch for i in range(N)]

    a1 = 90
    a2 = a1 + 180

    ports1 = [pp.Port(f"top_{i}", (xs1[i], 0), 0.5, a1) for i in range(N)]
    ports2 = [pp.Port(f"bottom_{i}", (xs2[i], dy), 0.5, a2) for i in range(N)]

    routes = pp.routing.connect_bundle_path_length_match(ports1,
                                                         ports2,
                                                         nb_loops=2)
    for route in routes:
        # print(route.parent.length)
        assert np.isclose(route.parent.length, 2681.07963267949)
    c.add(routes)
    c.routes = routes
    return c
Esempio n. 2
0
def import_gds(gdsname: str, rename_ports: bool = False) -> Component:
    """import gds from SIEPIC PDK"""
    c = pp.import_gds(gds / f"{gdsname}.gds")
    c.function_name = gdsname

    n = 0
    for label in c.get_labels():
        if label.text.startswith("opt"):
            n += 1

    for label in c.get_labels():
        if label.text.startswith("opt"):
            port = pp.Port(
                name=label.text,
                midpoint=label.position,
                width=port_width,
                orientation=guess_port_orientaton(
                    position=label.position,
                    name=gdsname,
                    label=label.text,
                    n=n,
                ),
                layer=layer,
            )
            c.add_port(port)

    if rename_ports:
        auto_rename_ports(c)

    return c
Esempio n. 3
0
def big_device(w=400.0, h=400.0, N=16, port_pitch=15.0, layer=pp.LAYER.WG, wg_width=0.5):
    """ big device with N ports on each side """
    component = pp.Component()
    p0 = np.array((0, 0))
    dx = w / 2
    dy = h / 2

    points = [[dx, dy], [dx, -dy], [-dx, -dy], [-dx, dy]]
    component.add_polygon(points, layer=layer)
    port_params = {"layer": layer, "width": wg_width}
    for i in range(N):
        port = pp.Port(
            name="W{}".format(i),
            midpoint=p0 + (-dx, (i - N / 2) * port_pitch),
            orientation=180,
            **port_params
        )
        component.add_port(port)

    for i in range(N):
        port = pp.Port(
            name="E{}".format(i),
            midpoint=p0 + (dx, (i - N / 2) * port_pitch),
            orientation=0,
            **port_params
        )
        component.add_port(port)

    for i in range(N):
        port = pp.Port(
            name="N{}".format(i),
            midpoint=p0 + ((i - N / 2) * port_pitch, dy),
            orientation=90,
            **port_params
        )
        component.add_port(port)

    for i in range(N):
        port = pp.Port(
            name="S{}".format(i),
            midpoint=p0 + ((i - N / 2) * port_pitch, -dy),
            orientation=-90,
            **port_params
        )
        component.add_port(port)
    return component
Esempio n. 4
0
def import_gds(gdsname):
    """ import gds from SIEPIC PDK
    """
    c = pp.import_gds(gds / f"{gdsname}.gds")

    for label in c.get_labels():
        if label.text.startswith("opt"):
            port = pp.Port(
                name=label.text,
                midpoint=label.position,
                width=port_width,
                orientation=position2orientation(label.position),
                layer=layer,
            )
            c.add_port(port)

    return c
Esempio n. 5
0
def flip(port):
    """ Flip a phidl Port """
    return pp.Port(port.name, port.midpoint, port.width, port.orientation + 180)
Esempio n. 6
0
def spiral_inner_io(
    N: int = 6,
    x_straight_inner_right: float = 150.0,
    x_straight_inner_left: float = 150.0,
    y_straight_inner_top: float = 50.0,
    y_straight_inner_bottom: float = 10.0,
    grating_spacing: float = 127.0,
    dx: float = 3.0,
    dy: float = 3.0,
    bend90_function: Callable = bend_circular,
    bend180_function: Callable = bend_circular180,
    bend_radius: float = 50.0,
    wg_width: float = 0.5,
    wg_width_grating_coupler: float = 0.5,
    straight_factory: Callable = waveguide,
    taper: Optional[Callable] = None,
    length: Optional[float] = None,
) -> Component:
    """Spiral with ports inside the spiral circle.

    Args:
        N: number of loops
        x_straight_inner_right:
        x_straight_inner_left:
        y_straight_inner_top:
        y_straight_inner_bottom:
        grating_spacing:
        dx: center to center x-spacing
        dy: center to center y-spacing
        bend90_function
        bend180_function
        bend_radius
        wg_width
        straight_factory
        taper:
        length: cm

    .. plot::
      :include-source:

      import pp
      from pp.components.spiral_inner_io import spiral_inner_io

      c = spiral_inner_io()
      pp.plotgds(c)
    """
    if length:
        if bend180_function == bend_circular180:
            y_straight_inner_top = get_straight_length(
                length_cm=length,
                spiral_function=spiral_inner_io,
                N=N,
                x_straight_inner_right=x_straight_inner_right,
                x_straight_inner_left=x_straight_inner_left,
                y_straight_inner_top=y_straight_inner_top,
                y_straight_inner_bottom=y_straight_inner_bottom,
                grating_spacing=grating_spacing,
                dx=dx,
                dy=dy,
                straight_factory=waveguide,
                bend90_function=bend_euler90,
                bend180_function=bend_euler180,
                wg_width=wg_width,
            )
        else:
            y_straight_inner_top = get_straight_length(
                length_cm=length,
                spiral_function=spiral_inner_io_euler,
                N=N,
                x_straight_inner_right=x_straight_inner_right,
                x_straight_inner_left=x_straight_inner_left,
                y_straight_inner_top=y_straight_inner_top,
                y_straight_inner_bottom=y_straight_inner_bottom,
                grating_spacing=grating_spacing,
                dx=dx,
                dy=dy,
                wg_width=wg_width,
            )

    _bend180 = pp.call_if_func(bend180_function, radius=bend_radius, width=wg_width)
    _bend90 = pp.call_if_func(bend90_function, radius=bend_radius, width=wg_width)

    rx, ry = get_bend_port_distances(_bend90)
    _, rx180 = get_bend_port_distances(_bend180)  # rx180, second arg since we rotate

    component = pp.Component()
    # gc_port_lbl = "W0"
    # gc1 = _gc.ref(port_id=gc_port_lbl, position=(0, 0), rotation=-90)
    # gc2 = _gc.ref(port_id=gc_port_lbl, position=(grating_spacing, 0), rotation=-90)
    # component.add([gc1, gc2])

    p1 = pp.Port(
        name="S0",
        midpoint=(0, y_straight_inner_top),
        orientation=270,
        width=wg_width,
        layer=pp.LAYER.WG,
    )
    p2 = pp.Port(
        name="S1",
        midpoint=(grating_spacing, y_straight_inner_top),
        orientation=270,
        width=wg_width,
        layer=pp.LAYER.WG,
    )
    taper = pp.c.taper(
        width1=wg_width_grating_coupler,
        width2=_bend180.ports["W0"].width,
        length=TAPER_LENGTH + y_straight_inner_top - 15 - 35,
    )
    taper_ref1 = component.add_ref(taper)
    taper_ref1.connect("2", p1)

    taper_ref2 = component.add_ref(taper)
    taper_ref2.connect("2", p2)

    component.absorb(taper_ref1)
    component.absorb(taper_ref2)

    component.add_port(name="S0", port=taper_ref1.ports["1"])
    component.add_port(name="S1", port=taper_ref2.ports["1"])

    # Create manhattan path going from west grating to westest port of bend 180
    _pt = np.array(p1.position)
    pts_w = [_pt]

    for i in range(N):
        y1 = y_straight_inner_top + ry + (2 * i + 1) * dy
        x2 = grating_spacing + 2 * rx + x_straight_inner_right + (2 * i + 1) * dx
        y3 = -y_straight_inner_bottom - ry - (2 * i + 3) * dy
        x4 = -x_straight_inner_left - (2 * i + 1) * dx
        if i == N - 1:
            x4 = x4 - rx180 + dx

        _pt1 = np.array([_pt[0], y1])
        _pt2 = np.array([x2, _pt1[1]])
        _pt3 = np.array([_pt2[0], y3])
        _pt4 = np.array([x4, _pt3[1]])
        _pt5 = np.array([_pt4[0], 0])
        _pt = _pt5

        pts_w += [_pt1, _pt2, _pt3, _pt4, _pt5]

    route_west = round_corners(
        pts_w, bend90=_bend90, straight_factory=straight_factory, taper=taper
    )
    component.add(route_west["references"])

    # Add loop back
    bend180_ref = _bend180.ref(
        port_id="W1", position=route_west["ports"]["output"], rotation=90
    )
    component.add(bend180_ref)
    component.absorb(bend180_ref)

    # Create manhattan path going from east grating to eastest port of bend 180
    _pt = np.array(p2.position)
    pts_e = [_pt]

    for i in range(N):
        y1 = y_straight_inner_top + ry + (2 * i) * dy
        x2 = grating_spacing + 2 * rx + x_straight_inner_right + 2 * i * dx
        y3 = -y_straight_inner_bottom - ry - (2 * i + 2) * dy
        x4 = -x_straight_inner_left - (2 * i) * dx

        _pt1 = np.array([_pt[0], y1])
        _pt2 = np.array([x2, _pt1[1]])
        _pt3 = np.array([_pt2[0], y3])
        _pt4 = np.array([x4, _pt3[1]])
        _pt5 = np.array([_pt4[0], 0])
        _pt = _pt5

        pts_e += [_pt1, _pt2, _pt3, _pt4, _pt5]

    route_east = round_corners(
        pts_e, bend90=_bend90, straight_factory=straight_factory, taper=taper
    )
    component.add(route_east["references"])

    length = (
        route_east["settings"]["length"]
        + route_west["settings"]["length"]
        + bend180_ref.info["length"]
    )
    component.length = pp.drc.snap_to_1nm_grid(length + 2 * y_straight_inner_top)
    return component