コード例 #1
0
def test_get_bundle_sort_ports(data_regression: DataRegressionFixture,
                               check: bool = True) -> Component:

    lengths = {}

    c = gf.Component("test_get_bundle_sort_ports")
    ys_right = [0, 10, 20, 40, 50, 80]
    pitch = 127.0
    N = len(ys_right)
    ys_left = [(i - N / 2) * pitch for i in range(N)]

    right_ports = [
        gf.Port(f"R_{i}", (0, ys_right[i]), 0.5, 180) for i in range(N)
    ]
    left_ports = [
        gf.Port(f"L_{i}", (-400, ys_left[i]), 0.5, 0) for i in range(N)
    ]
    left_ports.reverse()
    routes = gf.routing.get_bundle(right_ports, left_ports)

    for i, route in enumerate(routes):
        c.add(route.references)
        lengths[i] = route.length

    if check:
        data_regression.check(lengths)
    return c
コード例 #2
0
ファイル: manhattan.py プロジェクト: simbilod/gdsfactory
def get_route_error(
    points,
    cross_section: Optional[CrossSection] = None,
    layer_path: Layer = LAYER.ERROR_PATH,
    layer_label: Layer = LAYER.TEXT,
    layer_marker: Layer = LAYER.ERROR_MARKER,
    references: Optional[List[ComponentReference]] = None,
) -> Route:
    width = cross_section.info["width"] if cross_section else 10
    warnings.warn(
        f"Route error for points {points}",
        RouteWarning,
    )

    c = Component(f"route_{uuid.uuid4()}"[:16])
    path = gdspy.FlexPath(
        points,
        width=width,
        gdsii_path=True,
        layer=layer_path[0],
        datatype=layer_path[1],
    )
    c.add(path)
    ref = ComponentReference(c)
    port1 = gf.Port(name="p1", midpoint=points[0], width=width)
    port2 = gf.Port(name="p2", midpoint=points[1], width=width)

    point_marker = gf.c.rectangle(size=(width * 2, width * 2),
                                  centered=True,
                                  layer=layer_marker)
    point_markers = [point_marker.ref(position=point)
                     for point in points] + [ref]
    labels = [
        gf.Label(text=str(i),
                 position=point,
                 layer=layer_label[0],
                 texttype=layer_label[1]) for i, point in enumerate(points)
    ]

    references = references or []
    references += point_markers
    return Route(references=references,
                 ports=[port1, port2],
                 length=-1,
                 labels=labels)
コード例 #3
0
def test_path_length_matching() -> Component:
    c = gf.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 = [gf.Port(f"top_{i}", (xs1[i], 0), 0.5, a1) for i in range(N)]
    ports2 = [gf.Port(f"bottom_{i}", (xs2[i], dy), 0.5, a2) for i in range(N)]

    routes = gf.routing.get_bundle_path_length_match(ports1, ports2)
    lengths = [2659.822]
    for route, length in zip(routes, lengths):
        c.add(route.references)
        assert np.isclose(route.length, length), route.length
    return c
コード例 #4
0
ファイル: mmi2x2.py プロジェクト: tvt173/gdsfactory
def mmi2x2(width: float = 0.5,
           width_taper: float = 1.0,
           length_taper: float = 10.0,
           length_mmi: float = 5.5,
           width_mmi: float = 2.5,
           gap_mmi: float = 0.25,
           taper: ComponentFactory = taper_function,
           cross_section: CrossSectionFactory = strip,
           **kwargs) -> Component:
    r"""Mmi 2x2.

    Args:
        width: input and output straight width
        width_taper: interface between input straights and mmi region
        length_taper: into the mmi region
        length_mmi: in x direction
        width_mmi: in y direction
        gap_mmi: (width_taper + gap between tapered wg)/2
        taper: taper function
        cross_section:
        **kwargs: cross_section settings


    .. code::

                   length_mmi
                    <------>
                    ________
                   |        |
                __/          \__
            W1  __            __  E1
                  \          /_ _ _ _
                  |         | _ _ _ _| gap_mmi
                __/          \__
            W0  __            __  E0
                  \          /
                   |________|

                 <->
            length_taper

    """
    gf.snap.assert_on_2nm_grid(gap_mmi)
    x = cross_section(**kwargs)
    cladding_offset = x.info["cladding_offset"]
    layers_cladding = x.info["layers_cladding"]
    layer = x.info["layer"]

    component = gf.Component()
    w_mmi = width_mmi
    w_taper = width_taper

    taper = taper(length=length_taper,
                  width1=width,
                  width2=w_taper,
                  cross_section=cross_section,
                  **kwargs)

    a = gap_mmi / 2 + width_taper / 2
    mmi = gf.components.rectangle(
        size=(length_mmi, w_mmi),
        layer=layer,
        centered=True,
    )

    ports = [
        gf.Port("o1",
                orientation=180,
                midpoint=(-length_mmi / 2, -a),
                width=w_taper),
        gf.Port("o2",
                orientation=180,
                midpoint=(-length_mmi / 2, +a),
                width=w_taper),
        gf.Port("o3",
                orientation=0,
                midpoint=(+length_mmi / 2, +a),
                width=w_taper),
        gf.Port("o4",
                orientation=0,
                midpoint=(+length_mmi / 2, -a),
                width=w_taper),
    ]

    mmi_section = component.add_ref(mmi)

    for port in ports:
        taper_ref = component << taper
        taper_ref.connect(port="o2", destination=port)
        component.add_port(name=port.name, port=taper_ref.ports["o1"])
        component.absorb(taper_ref)

    component.absorb(mmi_section)

    layers_cladding = layers_cladding or []
    if layers_cladding:
        add_padding(
            component,
            default=cladding_offset,
            right=0,
            left=0,
            top=cladding_offset,
            bottom=cladding_offset,
            layers=layers_cladding,
        )
    component.auto_rename_ports()
    return component
コード例 #5
0
    xsize = port2.midpoint[0] - port1.midpoint[0]
    size = (xsize, ysize)

    bend = bend_s(size=size, **kwargs)
    bend_ref = bend.ref()
    bend_ref.connect("o1", port1)
    return Route(
        references=[bend_ref], length=bend.info_child["length"], ports=(port1, port2)
    )


if __name__ == "__main__":
    import gdsfactory as gf

    c = gf.Component("test_get_route_sbend")
    pitch = 2.0
    ys_left = [0, 10, 20]
    N = len(ys_left)
    ys_right = [(i - N / 2) * pitch for i in range(N)]

    right_ports = [gf.Port(f"R_{i}", (0, ys_right[i]), 0.5, 180) for i in range(N)]
    left_ports = [gf.Port(f"L_{i}", (-50, ys_left[i]), 0.5, 0) for i in range(N)]
    left_ports.reverse()
    right_ports, left_ports = sort_ports(right_ports, left_ports)

    for p1, p2 in zip(right_ports, left_ports):
        route = get_route_sbend(p1, p2, layer=(2, 0))
        c.add(route.references)

    c.show()
コード例 #6
0
def straight_heater_meander(
    length: float = 300.0,
    spacing: float = 2.0,
    cross_section: gf.types.CrossSectionFactory = gf.cross_section.strip,
    heater_width: float = 2.5,
    extension_length: float = 15.0,
    layer_heater: Optional[Layer] = LAYER.HEATER,
    radius: float = 5.0,
    contact: Optional[ComponentFactory] = contact_heater_m3,
    port_orientation1: int = 180,
    port_orientation2: int = 0,
    heater_taper_length: Optional[float] = 10.0,
    straight_width: float = 0.9,
    taper_length: float = 10,
):
    """Returns a meander based heater
    based on SungWon Chung, Makoto Nakai, and Hossein Hashemi,
    Low-power thermo-optic silicon modulator for large-scale photonic integrated systems
    Opt. Express 27, 13430-13459 (2019)
    https://www.osapublishing.org/oe/abstract.cfm?URI=oe-27-9-13430

    FIXME: only works for 3 rows.

    Args:
        length: total length of the optical path
        spacing: waveguide spacing (center to center)
        cross_section: for waveguide
        heater_width: for heater
        extension_length: of input and output optical ports
        layer_heater: for top heater, if None, it does not add a heater
        radius: for the meander bends
        contact: for the heater to contact metal
        port_orientation1:
        port_orientation2:
        heater_taper_length: minimizes current concentrations from heater to contact
        straight_width: width of the straight section
        taper_length: from the cross_section
    """
    rows = 3
    c = gf.Component()
    p1 = gf.Port(midpoint=(0, 0), orientation=0)
    p2 = gf.Port(midpoint=(0, spacing), orientation=0)
    route = gf.routing.get_route(p1, p2, radius=radius)

    cross_section1 = gf.partial(cross_section, width=straight_width)
    cross_section2 = cross_section

    straight_length = gf.snap.snap_to_grid(
        (length - (rows - 1) * route.length) / rows)
    straight = gf.c.straight(length=straight_length - 2 * taper_length,
                             cross_section=cross_section1)

    taper = gf.partial(
        gf.c.taper_cross_section_linear,
        cross_section1=cross_section1,
        cross_section2=cross_section2,
        length=taper_length,
    )

    straight_with_tapers = gf.c.extend_ports(straight, extension_factory=taper)

    straight_array = c << gf.c.array(
        straight_with_tapers, spacing=(0, spacing), columns=1, rows=rows)

    for row in range(1, rows, 2):
        route = gf.routing.get_route(
            straight_array.ports[f"o2_{row+1}_1"],
            straight_array.ports[f"o2_{row}_1"],
            radius=radius,
            cross_section=cross_section,
        )
        c.add(route.references)

        route = gf.routing.get_route(
            straight_array.ports[f"o1_{row+1}_1"],
            straight_array.ports[f"o1_{row+2}_1"],
            radius=radius,
            cross_section=cross_section,
        )
        c.add(route.references)

    straight1 = c << gf.c.straight(length=extension_length,
                                   cross_section=cross_section)
    straight2 = c << gf.c.straight(length=extension_length,
                                   cross_section=cross_section)
    straight1.connect("o2", straight_array.ports["o1_1_1"])
    straight2.connect("o1", straight_array.ports[f"o2_{rows}_1"])

    c.add_port("o1", port=straight1.ports["o1"])
    c.add_port("o2", port=straight2.ports["o2"])

    if layer_heater:
        heater_cross_section = gf.partial(gf.cross_section.cross_section,
                                          width=heater_width,
                                          layer=layer_heater)

        heater = c << gf.c.straight(
            length=straight_length,
            cross_section=heater_cross_section,
        )
        heater.movey(spacing * (rows // 2))

    if layer_heater and contact:
        contactw = contact()
        contacte = contact()
        dx = contactw.get_ports_xsize() / 2 + heater_taper_length or 0
        contact_west_midpoint = heater.size_info.cw - (dx, 0)
        contact_east_midpoint = heater.size_info.ce + (dx, 0)

        contact_west = c << contactw
        contact_east = c << contacte
        contact_west.move(contact_west_midpoint)
        contact_east.move(contact_east_midpoint)
        c.add_port(
            "e1",
            port=contact_west.get_ports_list(orientation=port_orientation1)[0])
        c.add_port(
            "e2",
            port=contact_east.get_ports_list(orientation=port_orientation2)[0])

        if heater_taper_length:
            taper = gf.c.taper(
                cross_section=heater_cross_section,
                width1=contactw.ports["e1"].width,
                width2=heater_width,
                length=heater_taper_length,
            )
            taper1 = c << taper
            taper2 = c << taper
            taper1.connect("o2", heater.ports["o1"])
            taper2.connect("o2", heater.ports["o2"])

            contact_west.connect("e3", taper1.ports["o1"])
            contact_east.connect("e1", taper2.ports["o1"])
    return c
コード例 #7
0
def spiral_inner_io(N: int = 6,
                    x_straight_inner_right: float = 150.0,
                    x_straight_inner_left: float = 50.0,
                    y_straight_inner_top: float = 50.0,
                    y_straight_inner_bottom: float = 10.0,
                    grating_spacing: float = 127.0,
                    waveguide_spacing: float = 3.0,
                    bend90_function: ComponentFactory = bend_euler,
                    bend180_function: ComponentFactory = bend_euler180,
                    straight: ComponentFactory = straight_function,
                    length: Optional[float] = None,
                    cross_section: CrossSectionFactory = strip,
                    cross_section_bend: Optional[CrossSectionFactory] = None,
                    **kwargs) -> Component:
    """Returns Spiral with ports inside the spiral loop.
    You can add grating couplers inside .

    Args:
        N: number of loops
        x_straight_inner_right:
        x_straight_inner_left:
        y_straight_inner_top:
        y_straight_inner_bottom:
        grating_spacing: defaults to 127 for fiber array
        waveguide_spacing: center to center spacing
        bend90_function
        bend180_function
        straight: straight function
        length: spiral target length (um), overrides x_straight_inner_left
            to match the length by a simple 1D interpolation
        cross_section:
        cross_section_bend: for the bends
        kwargs: cross_section settings

    """
    dx = dy = waveguide_spacing
    x = cross_section(**kwargs)
    width = x.info.get("width")
    layer = x.info.get("layer")
    cross_section_bend = cross_section_bend or cross_section

    if length:
        x_straight_inner_left = get_straight_length(
            length=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,
            waveguide_spacing=waveguide_spacing,
        )

    _bend180 = gf.call_if_func(bend180_function,
                               cross_section=cross_section_bend,
                               **kwargs)
    _bend90 = gf.call_if_func(bend90_function,
                              cross_section=cross_section_bend,
                              **kwargs)

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

    component = Component()

    p1 = gf.Port(
        name="o1",
        midpoint=(0, y_straight_inner_top),
        orientation=270,
        width=width,
        layer=layer,
        cross_section=cross_section_bend,
    )
    p2 = gf.Port(
        name="o2",
        midpoint=(grating_spacing, y_straight_inner_top),
        orientation=270,
        width=width,
        layer=layer,
        cross_section=cross_section_bend,
    )

    component.add_port(name="o1", port=p1)
    component.add_port(name="o2", port=p2)

    # 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,
                               bend=_bend90,
                               straight=straight,
                               cross_section=cross_section,
                               **kwargs)
    component.add(route_west.references)

    # Add loop back
    bend180_ref = _bend180.ref(port_id="o2",
                               position=route_west.ports[1],
                               rotation=90)
    component.add(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,
                               bend=_bend90,
                               straight=straight,
                               cross_section=cross_section,
                               **kwargs)
    component.add(route_east.references)

    length = route_east.length + route_west.length + _bend180.info.length
    component.info.length = snap_to_grid(length + 2 * y_straight_inner_top)
    return component
コード例 #8
0
def mmi1x2(width: float = 0.5,
           width_taper: float = 1.0,
           length_taper: float = 10.0,
           length_mmi: float = 5.5,
           width_mmi: float = 2.5,
           gap_mmi: float = 0.25,
           taper: ComponentFactory = taper_function,
           with_cladding_box: bool = True,
           cross_section: CrossSectionFactory = strip,
           **kwargs) -> Component:
    r"""Mmi 1x2.

    Args:
        width: input and output straight width
        width_taper: interface between input straights and mmi region
        length_taper: into the mmi region
        length_mmi: in x direction
        width_mmi: in y direction
        gap_mmi:  gap between tapered wg
        taper: taper function
        with_cladding_box: to avoid DRC acute angle errors in cladding
        cross_section:
        **kwargs: cross_section settings


    .. code::

               length_mmi
                <------>
                ________
               |        |
               |         \__
               |          __  E1
            __/          /_ _ _ _
         W0 __          | _ _ _ _| gap_mmi
              \          \__
               |          __  E0
               |         /
               |________|

             <->
        length_taper

    """
    gf.snap.assert_on_2nm_grid(gap_mmi)
    x = cross_section(**kwargs)
    cladding_offset = x.info["cladding_offset"]
    layers_cladding = x.info["layers_cladding"]
    layer = x.info["layer"]

    c = Component()
    w_mmi = width_mmi
    w_taper = width_taper

    taper = taper(length=length_taper,
                  width1=width,
                  width2=w_taper,
                  cross_section=cross_section,
                  **kwargs)

    a = gap_mmi / 2 + width_taper / 2
    mmi = c << gf.components.rectangle(
        size=(length_mmi, w_mmi),
        layer=layer,
        centered=True,
    )

    ports = [
        gf.Port("o1",
                orientation=180,
                midpoint=(-length_mmi / 2, 0),
                width=w_taper),
        gf.Port("o2",
                orientation=0,
                midpoint=(+length_mmi / 2, +a),
                width=w_taper),
        gf.Port("o3",
                orientation=0,
                midpoint=(+length_mmi / 2, -a),
                width=w_taper),
    ]

    for port in ports:
        taper_ref = c << taper
        taper_ref.connect(port="o2", destination=port)
        c.add_port(name=port.name, port=taper_ref.ports["o1"])
        c.absorb(taper_ref)

    c.absorb(mmi)

    layers_cladding = layers_cladding or []
    if layers_cladding and with_cladding_box:
        add_padding(
            c,
            default=cladding_offset,
            right=0,
            left=0,
            top=cladding_offset,
            bottom=cladding_offset,
            layers=layers_cladding,
        )
    return c