Routing optical and RF ports#

Optical and high speed RF ports have an orientation that routes need to follow to avoid sharp turns that produce reflections.

[1]:
import gdsfactory as gf

gf.config.set_plot_options(show_subports=False)
gf.CONF.plotter = "matplotlib"
2022-06-28 17:01:10.856 | INFO     | gdsfactory.config:<module>:52 - Load '/home/runner/work/gdsfactory/gdsfactory/gdsfactory' 5.11.4
[2]:
c = gf.Component()
mmi1 = c << gf.components.mmi1x2()
mmi2 = c << gf.components.mmi1x2()
mmi2.move((100, 50))
c
/home/runner/work/gdsfactory/gdsfactory/gdsfactory/component.py:1054: UserWarning: Component 'Unnamed_53f9bf8b' contains 1 Unnamed cells
  warnings.warn(
../_images/notebooks_04_routing_2_1.png
[2]:
Unnamed_53f9bf8b: uid 0, ports [], aliases [], 0 polygons, 2 references

get_route#

get_route returns a Manhattan route between 2 ports

[3]:
gf.routing.get_route?
[4]:
c = gf.Component("sample_connect")
mmi1 = c << gf.components.mmi1x2()
mmi2 = c << gf.components.mmi1x2()
mmi2.move((100, 50))
route = gf.routing.get_route(mmi1.ports["o2"], mmi2.ports["o1"])
c.add(route.references)
c
../_images/notebooks_04_routing_5_0.png
[4]:
sample_connect: uid 5, ports [], aliases [], 0 polygons, 7 references
[5]:
route
[5]:
Route(references=[ComponentReference (parent Component "bend_euler", ports ['o1', 'o2'], origin [69.99   0.625], rotation 0, x_reflection False), ComponentReference (parent Component "bend_euler", ports ['o1', 'o2'], origin [79.99 40.  ], rotation 90.0, x_reflection True), ComponentReference (parent Component "straight_89bf0bf0", ports ['o1', 'o2'], origin [15.5    0.625], rotation 0, x_reflection False), ComponentReference (parent Component "straight_7e83a799", ports ['o1', 'o2'], origin [79.99  10.625], rotation 90.0, x_reflection False), ComponentReference (parent Component "straight_77b336e2", ports ['o1', 'o2'], origin [89.99 50.  ], rotation 0, x_reflection False)], labels=None, ports=(Port (name o1, midpoint [15.5    0.625], width 0.5, orientation 180, layer (1, 0), port_type optical), Port (name o2, midpoint [90. 50.], width 0.5, orientation 0.0, layer (1, 0), port_type optical)), length=117.149)

Problem: get_route with obstacles

sometimes there are obstacles that connect strip does not see!

[6]:
c = gf.Component("sample_problem")
mmi1 = c << gf.components.mmi1x2()
mmi2 = c << gf.components.mmi1x2()
mmi2.move((110, 50))
x = c << gf.components.cross(length=20)
x.move((135, 20))
route = gf.routing.get_route(mmi1.ports["o2"], mmi2.ports["o2"])
c.add(route.references)
c
../_images/notebooks_04_routing_8_0.png
[6]:
sample_problem: uid 15, ports [], aliases [], 0 polygons, 8 references

Solutions:

  • specify the route waypoints

  • specify the route steps

[7]:
c = gf.Component("sample_avoid_obstacle")
mmi1 = c << gf.components.mmi1x2()
mmi2 = c << gf.components.mmi1x2()
mmi2.move((110, 50))
x = c << gf.components.cross(length=20)
x.move((135, 20))

x0 = mmi1.ports["o3"].x
y0 = mmi1.ports["o3"].y


x2 = mmi2.ports["o3"].x
y2 = mmi2.ports["o3"].y

route = gf.routing.get_route_from_waypoints(
    [(x0, y0), (x2 + 40, y0), (x2 + 40, y2), (x2, y2)]
)
c.add(route.references)
c
../_images/notebooks_04_routing_10_0.png
[7]:
sample_avoid_obstacle: uid 23, ports [], aliases [], 0 polygons, 8 references
[8]:
route.length
[8]:
233.274
[9]:
route.ports
[9]:
(Port (name o1, midpoint [15.5   -0.625], width 0.5, orientation 180, layer (1, 0), port_type optical),
 Port (name o2, midpoint [125.5    49.375], width 0.5, orientation 180.0, layer (1, 0), port_type optical))
[10]:
route.references
[10]:
[ComponentReference (parent Component "bend_euler_44e21782", ports ['o1', 'o2'], origin [155.5    -0.625], rotation 0, x_reflection False),
 ComponentReference (parent Component "bend_euler_44e21782", ports ['o1', 'o2'], origin [165.5    39.375], rotation 90, x_reflection False),
 ComponentReference (parent Component "straight_1d269684", ports ['o1', 'o2'], origin [15.5   -0.625], rotation 0, x_reflection False),
 ComponentReference (parent Component "straight_a1aa286a", ports ['o1', 'o2'], origin [165.5     9.375], rotation 90.0, x_reflection False),
 ComponentReference (parent Component "straight_a1aa286a", ports ['o1', 'o2'], origin [155.5    49.375], rotation 180.0, x_reflection False)]

Lets say that we want to extrude the waveguide using a different waveguide crosssection, for example using a different layer

[11]:
import gdsfactory as gf

c = gf.Component("sample_connect")
mmi1 = c << gf.components.mmi1x2()
mmi2 = c << gf.components.mmi1x2()
mmi2.move((100, 50))
route = gf.routing.get_route(
    mmi1.ports["o3"], mmi2.ports["o1"], cross_section=gf.cross_section.metal1
)
c.add(route.references)
c
../_images/notebooks_04_routing_15_0.png
[11]:
sample_connect: uid 29, ports [], aliases [], 0 polygons, 7 references

auto_widen#

To reduce loss and phase errors you can also auto-widen waveguide routes straight sections that are longer than a certain length.

[12]:
import gdsfactory as gf

c = gf.Component("sample_connect")
mmi1 = c << gf.components.mmi1x2()
mmi2 = c << gf.components.mmi1x2()
mmi2.move((200, 50))

route = gf.routing.get_route(
    mmi1.ports["o3"],
    mmi2.ports["o1"],
    cross_section=gf.cross_section.strip,
    auto_widen=True,
    width_wide=2,
    auto_widen_minimum_length=100,
)
c.add(route.references)
c
../_images/notebooks_04_routing_17_0.png
[12]:
sample_connect: uid 39, ports [], aliases [], 0 polygons, 9 references

get_route_from_waypoints#

Sometimes you need to set up a route with custom waypoints. get_route_from_waypoints is a manual version of get_route

[13]:
import gdsfactory as gf

c = gf.Component("waypoints_sample")

w = gf.components.straight()
left = c << w
right = c << w
right.move((100, 80))

obstacle = gf.components.rectangle(size=(100, 10))
obstacle1 = c << obstacle
obstacle2 = c << obstacle
obstacle1.ymin = 40
obstacle2.xmin = 25


p0x, p0y = left.ports["o2"].midpoint
p1x, p1y = right.ports["o2"].midpoint
o = 10  # vertical offset to overcome bottom obstacle
ytop = 20


routes = gf.routing.get_route_from_waypoints(
    [
        (p0x, p0y),
        (p0x + o, p0y),
        (p0x + o, ytop),
        (p1x + o, ytop),
        (p1x + o, p1y),
        (p1x, p1y),
    ],
)
c.add(routes.references)
c
../_images/notebooks_04_routing_19_0.png
[13]:
waypoints_sample: uid 49, ports [], aliases [], 0 polygons, 10 references

get_route_from_steps#

As you can see waypoints can only change one point (x or y) at a time, making the waypoint definition a bit redundant.

You can also use a get_route_from_steps which is a more concise route definition, that supports defining only the new steps x or y together with increments dx or dy

get_route_from_steps is a manual version of get_route and a more concise and convenient version of get_route_from_waypoints

[14]:
import gdsfactory as gf

c = gf.Component("get_route_from_steps")
w = gf.components.straight()
left = c << w
right = c << w
right.move((100, 80))

obstacle = gf.components.rectangle(size=(100, 10))
obstacle1 = c << obstacle
obstacle2 = c << obstacle
obstacle1.ymin = 40
obstacle2.xmin = 25

port1 = left.ports["o2"]
port2 = right.ports["o2"]

routes = gf.routing.get_route_from_steps(
    port1=port1,
    port2=port2,
    steps=[
        {"x": 20, "y": 0},
        {"x": 20, "y": 20},
        {"x": 120, "y": 20},
        {"x": 120, "y": 80},
    ],
)
c.add(routes.references)
c
../_images/notebooks_04_routing_21_0.png
[14]:
get_route_from_steps: uid 60, ports [], aliases [], 0 polygons, 10 references
[15]:
import gdsfactory as gf

c = gf.Component("get_route_from_steps_shorter_syntax")
w = gf.components.straight()
left = c << w
right = c << w
right.move((100, 80))

obstacle = gf.components.rectangle(size=(100, 10))
obstacle1 = c << obstacle
obstacle2 = c << obstacle
obstacle1.ymin = 40
obstacle2.xmin = 25

port1 = left.ports["o2"]
port2 = right.ports["o2"]

routes = gf.routing.get_route_from_steps(
    port1=port1,
    port2=port2,
    steps=[
        {"x": 20},
        {"y": 20},
        {"x": 120},
        {"y": 80},
    ],
)
c.add(routes.references)
c
../_images/notebooks_04_routing_22_0.png
[15]:
get_route_from_steps_shorter_syntax: uid 61, ports [], aliases [], 0 polygons, 10 references

get_bundle#

Problem

See the route collisions When connecting groups of ports using get_route manhattan single-route router

[16]:
import gdsfactory as gf

xs_top = [0, 10, 20, 40, 50, 80]
pitch = 127
N = len(xs_top)
xs_bottom = [(i - N / 2) * pitch for i in range(N)]
layer = (1, 0)

top_ports = [
    gf.Port(f"top_{i}", (xs_top[i], 0), 0.5, 270, layer=layer) for i in range(N)
]

bottom_ports = [
    gf.Port(f"bottom_{i}", (xs_bottom[i], -100), 0.5, 90, layer=layer) for i in range(N)
]

c = gf.Component(name="connect_bundle")

for p1, p2 in zip(top_ports, bottom_ports):
    route = gf.routing.get_route(p1, p2)
    c.add(route.references)

c
../_images/notebooks_04_routing_24_0.png
[16]:
connect_bundle: uid 62, ports [], aliases [], 0 polygons, 30 references

solution

get_bundle provides you with river routing capabilities, that you can use to route bundles of ports without collisions

[17]:
c = gf.Component(name="connect_bundle")
routes = gf.routing.get_bundle(top_ports, bottom_ports)
for route in routes:
    c.add(route.references)

c
../_images/notebooks_04_routing_26_0.png
[17]:
connect_bundle: uid 77, ports [], aliases [], 0 polygons, 30 references
[18]:
import gdsfactory as gf

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)]
layer = (1, 0)

right_ports = [
    gf.Port(f"R_{i}", (0, ys_right[i]), width=0.5, orientation=180, layer=layer)
    for i in range(N)
]
left_ports = [
    gf.Port(
        f"L_{i}".format(i), (-200, ys_left[i]), width=0.5, orientation=0, layer=layer
    )
    for i in range(N)
]

# you can also mess up the port order and it will sort them by default
left_ports.reverse()

c = gf.Component(name="connect_bundle2")
routes = gf.routing.get_bundle(
    left_ports, right_ports, sort_ports=True, start_straight_length=100
)
for route in routes:
    c.add(route.references)
c
../_images/notebooks_04_routing_27_0.png
[18]:
connect_bundle2: uid 98, ports [], aliases [], 0 polygons, 30 references
[19]:
xs_top = [0, 10, 20, 40, 50, 80]
pitch = 127.0
N = len(xs_top)
xs_bottom = [(i - N / 2) * pitch for i in range(N)]
layer = (1, 0)

top_ports = [
    gf.Port(
        f"top_{i}", midpoint=(xs_top[i], 0), width=0.5, orientation=270, layer=layer
    )
    for i in range(N)
]

bot_ports = [
    gf.Port(
        f"bot_{i}",
        midpoint=(xs_bottom[i], -300),
        width=0.5,
        orientation=90,
        layer=layer,
    )
    for i in range(N)
]

c = gf.Component(name="connect_bundle")
routes = gf.routing.get_bundle(
    top_ports, bot_ports, separation=5.0, end_straight_length=100
)
for route in routes:
    c.add(route.references)

c
../_images/notebooks_04_routing_28_0.png
[19]:
connect_bundle: uid 107, ports [], aliases [], 0 polygons, 30 references

get_bundle can also route bundles through corners

[20]:
import gdsfactory as gf
from gdsfactory.cell import cell
from gdsfactory.component import Component
from gdsfactory.port import Port


@cell
def test_connect_corner(N=6, config="A"):
    d = 10.0
    sep = 5.0
    top_cell = gf.Component(name="connect_corner")
    layer = (1, 0)

    if config in ["A", "B"]:
        a = 100.0
        ports_A_TR = [
            Port(
                f"A_TR_{i}",
                midpoint=(d, a / 2 + i * sep),
                width=0.5,
                orientation=0,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_A_TL = [
            Port(
                f"A_TL_{i}",
                midpoint=(-d, a / 2 + i * sep),
                width=0.5,
                orientation=180,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_A_BR = [
            Port(
                f"A_BR_{i}",
                midpoint=(d, -a / 2 - i * sep),
                width=0.5,
                orientation=0,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_A_BL = [
            Port(
                f"A_BL_{i}",
                midpoint=(-d, -a / 2 - i * sep),
                width=0.5,
                orientation=180,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_A = [ports_A_TR, ports_A_TL, ports_A_BR, ports_A_BL]

        ports_B_TR = [
            Port(
                f"B_TR_{i}",
                midpoint=(a / 2 + i * sep, d),
                width=0.5,
                orientation=90,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_B_TL = [
            Port(
                f"B_TL_{i}",
                midpoint=(-a / 2 - i * sep, d),
                width=0.5,
                orientation=90,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_B_BR = [
            Port(
                f"B_BR_{i}",
                midpoint=(a / 2 + i * sep, -d),
                width=0.5,
                orientation=270,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_B_BL = [
            Port(
                f"B_BL_{i}",
                midpoint=(-a / 2 - i * sep, -d),
                width=0.5,
                orientation=270,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_B = [ports_B_TR, ports_B_TL, ports_B_BR, ports_B_BL]

    elif config in ["C", "D"]:
        a = N * sep + 2 * d
        ports_A_TR = [
            Port(
                f"A_TR_{i}",
                midpoint=(a, d + i * sep),
                width=0.5,
                orientation=0,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_A_TL = [
            Port(
                f"A_TL_{i}",
                midpoint=(-a, d + i * sep),
                width=0.5,
                orientation=180,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_A_BR = [
            Port(
                f"A_BR_{i}",
                midpoint=(a, -d - i * sep),
                width=0.5,
                orientation=0,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_A_BL = [
            Port(
                f"A_BL_{i}",
                midpoint=(-a, -d - i * sep),
                width=0.5,
                orientation=180,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_A = [ports_A_TR, ports_A_TL, ports_A_BR, ports_A_BL]

        ports_B_TR = [
            Port(
                f"B_TR_{i}",
                midpoint=(d + i * sep, a),
                width=0.5,
                orientation=90,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_B_TL = [
            Port(
                f"B_TL_{i}",
                midpoint=(-d - i * sep, a),
                width=0.5,
                orientation=90,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_B_BR = [
            Port(
                f"B_BR_{i}",
                midpoint=(d + i * sep, -a),
                width=0.5,
                orientation=270,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_B_BL = [
            Port(
                f"B_BL_{i}",
                midpoint=(-d - i * sep, -a),
                width=0.5,
                orientation=270,
                layer=layer,
            )
            for i in range(N)
        ]

        ports_B = [ports_B_TR, ports_B_TL, ports_B_BR, ports_B_BL]

    if config in ["A", "C"]:
        for ports1, ports2 in zip(ports_A, ports_B):
            routes = gf.routing.get_bundle(ports1, ports2, layer=(2, 0), radius=5)
            for route in routes:
                top_cell.add(route.references)

    elif config in ["B", "D"]:
        for ports1, ports2 in zip(ports_A, ports_B):
            routes = gf.routing.get_bundle(ports2, ports1, layer=(2, 0), radius=5)
            for route in routes:
                top_cell.add(route.references)

    return top_cell


c = test_connect_corner(config="A")
c
../_images/notebooks_04_routing_30_0.png
[20]:
test_connect_corner: uid 122, ports [], aliases [], 0 polygons, 72 references
[21]:
c = test_connect_corner(config="C")
c
../_images/notebooks_04_routing_31_0.png
[21]:
test_connect_corner_configC: uid 137, ports [], aliases [], 0 polygons, 168 references
[22]:
@cell
def test_connect_bundle_udirect(dy=200, angle=270, layer=(1, 0)):

    xs1 = [-100, -90, -80, -55, -35, 24, 0] + [200, 210, 240]

    axis = "X" if angle in [0, 180] else "Y"

    pitch = 10.0
    N = len(xs1)
    xs2 = [70 + i * pitch for i in range(N)]

    if axis == "X":
        ports1 = [
            Port(f"top_{i}", (0, xs1[i]), 0.5, angle, layer=layer) for i in range(N)
        ]

        ports2 = [
            Port(f"bottom_{i}", (dy, xs2[i]), 0.5, angle, layer=layer) for i in range(N)
        ]

    else:
        ports1 = [
            Port(f"top_{i}", (xs1[i], 0), 0.5, angle, layer=layer) for i in range(N)
        ]

        ports2 = [
            Port(f"bottom_{i}", (xs2[i], dy), 0.5, angle, layer=layer) for i in range(N)
        ]

    top_cell = Component(name="connect_bundle_udirect")
    routes = gf.routing.get_bundle(ports1, ports2, radius=10.0)
    for route in routes:
        top_cell.add(route.references)

    return top_cell


c = test_connect_bundle_udirect()
c
../_images/notebooks_04_routing_32_0.png
[22]:
test_connect_bundle_udirect: uid 154, ports [], aliases [], 0 polygons, 50 references
[23]:
@cell
def test_connect_bundle_u_indirect(dy=-200, angle=180, layer=(1, 0)):
    xs1 = [-100, -90, -80, -55, -35] + [200, 210, 240]
    axis = "X" if angle in [0, 180] else "Y"
    pitch = 10.0
    N = len(xs1)
    xs2 = [50 + i * pitch for i in range(N)]

    a1 = angle
    a2 = a1 + 180

    if axis == "X":
        ports1 = [Port(f"top_{i}", (0, xs1[i]), 0.5, a1, layer=layer) for i in range(N)]

        ports2 = [
            Port(f"bot_{i}", (dy, xs2[i]), 0.5, a2, layer=layer) for i in range(N)
        ]

    else:
        ports1 = [Port(f"top_{i}", (xs1[i], 0), 0.5, a1, layer=layer) for i in range(N)]

        ports2 = [
            Port(f"bot_{i}", (xs2[i], dy), 0.5, a2, layer=layer) for i in range(N)
        ]

    top_cell = Component("connect_bundle_u_indirect")
    routes = gf.routing.get_bundle(
        ports1,
        ports2,
        bend=gf.components.bend_euler,
        radius=5,
    )
    for route in routes:
        top_cell.add(route.references)

    return top_cell


c = test_connect_bundle_u_indirect(angle=0)
c
../_images/notebooks_04_routing_33_0.png
[23]:
test_connect_bundle_u_i_d289aeae: uid 197, ports [], aliases [], 0 polygons, 72 references
[24]:
import gdsfactory as gf


@gf.cell
def test_north_to_south(layer=(1, 0)):
    dy = 200.0
    xs1 = [-500, -300, -100, -90, -80, -55, -35, 200, 210, 240, 500, 650]

    pitch = 10.0
    N = len(xs1)
    xs2 = [-20 + i * pitch for i in range(N // 2)]
    xs2 += [400 + i * pitch for i in range(N // 2)]

    a1 = 90
    a2 = a1 + 180

    ports1 = [gf.Port(f"top_{i}", (xs1[i], 0), 0.5, a1, layer=layer) for i in range(N)]

    ports2 = [gf.Port(f"bot_{i}", (xs2[i], dy), 0.5, a2, layer=layer) for i in range(N)]

    c = gf.Component()
    routes = gf.routing.get_bundle(ports1, ports2, auto_widen=False)
    for route in routes:
        c.add(route.references)

    return c


c = test_north_to_south()
c
../_images/notebooks_04_routing_34_0.png
[24]:
test_north_to_south: uid 254, ports [], aliases [], 0 polygons, 60 references
[25]:
def demo_connect_bundle():
    """combines all the connect_bundle tests"""
    y = 400.0
    x = 500
    y0 = 900
    dy = 200.0
    c = gf.Component("connect_bundle")
    for j, s in enumerate([-1, 1]):
        for i, angle in enumerate([0, 90, 180, 270]):
            ci = test_connect_bundle_u_indirect(dy=s * dy, angle=angle)
            ref = ci.ref(position=(i * x, j * y))
            c.add(ref)

            ci = test_connect_bundle_udirect(dy=s * dy, angle=angle)
            ref = ci.ref(position=(i * x, j * y + y0))
            c.add(ref)

    for i, config in enumerate(["A", "B", "C", "D"]):
        ci = test_connect_corner(config=config)
        ref = ci.ref(position=(i * x, 1700))
        c.add(ref)

    return c


c = demo_connect_bundle()
c
../_images/notebooks_04_routing_35_0.png
[25]:
connect_bundle: uid 293, ports [], aliases [], 0 polygons, 20 references
[26]:
import gdsfactory as gf

c = gf.Component("route_bend_5um")
c1 = c << gf.components.mmi2x2()
c2 = c << gf.components.mmi2x2()

c2.move((100, 50))
routes = gf.routing.get_bundle(
    [c1.ports["o4"], c1.ports["o3"]], [c2.ports["o1"], c2.ports["o2"]], radius=5
)
for route in routes:
    c.add(route.references)
c
../_images/notebooks_04_routing_36_0.png
[26]:
route_bend_5um: uid 394, ports [], aliases [], 0 polygons, 12 references
[27]:
import gdsfactory as gf

c = gf.Component("electrical")
c1 = c << gf.components.pad()
c2 = c << gf.components.pad()
c2.move((200, 100))
routes = gf.routing.get_bundle(
    [c1.ports["e3"]], [c2.ports["e1"]], cross_section=gf.cross_section.metal1
)
for route in routes:
    c.add(route.references)
c
../_images/notebooks_04_routing_37_0.png
[27]:
electrical: uid 402, ports [], aliases [], 0 polygons, 7 references
[28]:
c = gf.Component("get_bundle_with_ubends_bend_from_top")
pad_array = gf.components.pad_array()

c1 = c << pad_array
c2 = c << pad_array
c2.rotate(90)
c2.movex(1000)
c2.ymax = -200

routes_bend180 = gf.routing.get_routes_bend180(
    ports=c2.get_ports_list(),
    radius=75 / 2,
    cross_section=gf.cross_section.metal1,
    bend_port1="e1",
    bend_port2="e2",
)
c.add(routes_bend180.references)

routes = gf.routing.get_bundle(
    c1.get_ports_list(), routes_bend180.ports, cross_section=gf.cross_section.metal1
)
for route in routes:
    c.add(route.references)
c
../_images/notebooks_04_routing_38_0.png
[28]:
get_bundle_with_ubends_bend_from_top: uid 411, ports [], aliases [], 0 polygons, 26 references
[29]:
c = gf.Component("get_bundle_with_ubends_bend_from_bottom")
pad_array = gf.components.pad_array()

c1 = c << pad_array
c2 = c << pad_array
c2.rotate(90)
c2.movex(1000)
c2.ymax = -200

routes_bend180 = gf.routing.get_routes_bend180(
    ports=c2.get_ports_list(),
    radius=75 / 2,
    cross_section=gf.cross_section.metal1,
    bend_port1="e2",
    bend_port2="e1",
)
c.add(routes_bend180.references)

routes = gf.routing.get_bundle(
    c1.get_ports_list(), routes_bend180.ports, cross_section=gf.cross_section.metal1
)
for route in routes:
    c.add(route.references)
c
../_images/notebooks_04_routing_39_0.png
[29]:
get_bundle_with_ubends_bend_from_bottom: uid 439, ports [], aliases [], 0 polygons, 26 references

Problem

Sometimes 90 degrees routes do not have enough space for a Manhattan route

[30]:
import gdsfactory as gf

c = gf.Component("route_fail_1")
c1 = c << gf.components.nxn(east=3, ysize=20)
c2 = c << gf.components.nxn(west=3)
c2.move((80, 0))
c
../_images/notebooks_04_routing_41_0.png
[30]:
route_fail_1: uid 442, ports [], aliases [], 0 polygons, 2 references
[31]:
import gdsfactory as gf

c = gf.Component("route_fail_1")
c1 = c << gf.components.nxn(east=3, ysize=20)
c2 = c << gf.components.nxn(west=3)
c2.move((80, 0))
routes = gf.routing.get_bundle(
    c1.get_ports_list(orientation=0),
    c2.get_ports_list(orientation=180),
    auto_widen=False,
)
for route in routes:
    c.add(route.references)
c
../_images/notebooks_04_routing_42_0.png
[31]:
route_fail_1: uid 449, ports [], aliases [], 0 polygons, 21 references
[32]:
c = gf.Component("route_fail_2")
pitch = 2.0
ys_left = [0, 10, 20]
N = len(ys_left)
ys_right = [(i - N / 2) * pitch for i in range(N)]
layer = (1, 0)

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

for route in routes:
    c.add(route.references)
c
../_images/notebooks_04_routing_43_0.png
[32]:
route_fail_2: uid 461, ports [], aliases [], 0 polygons, 19 references

Solution

Add Sbend routes using get_bundle_sbend

[33]:
import gdsfactory as gf

c = gf.Component("route_solution_1_get_bundle_sbend")
c1 = c << gf.components.nxn(east=3, ysize=20)
c2 = c << gf.components.nxn(west=3)
c2.move((80, 0))
routes = gf.routing.get_bundle_sbend(
    c1.get_ports_list(orientation=0), c2.get_ports_list(orientation=180)
)
c.add(routes.references)
c
/home/runner/work/gdsfactory/gdsfactory/gdsfactory/components/bezier.py:99: RuntimeWarning: divide by zero encountered in double_scalars
  min_bend_radius = gf.snap.snap_to_grid(1 / max(np.abs(curv)))
../_images/notebooks_04_routing_45_1.png
[33]:
route_solution_1_get_bundle_sbend: uid 468, ports [], aliases [], 0 polygons, 5 references
[34]:
routes
[34]:
Routes(references=[ComponentReference (parent Component "bezier_08c93533_bend_s__f3faaa5b", ports ['o1', 'o2'], origin [8.   1.25], rotation 0, x_reflection False), ComponentReference (parent Component "bezier_6f3b5e6e_bend_s__3daf6097", ports ['o1', 'o2'], origin [ 8. 10.], rotation 0, x_reflection False), ComponentReference (parent Component "bezier_5a820ac3_bend_s__6f6f9cd6", ports ['o1', 'o2'], origin [ 8.   18.75], rotation 0, x_reflection False)], lengths=[72.0, 72.354, 73.398], ports=None, bend_radius=[inf, 159.432, 83.82])
[35]:
c = gf.Component("route_solution_2_get_bundle_sbend")
route = gf.routing.get_bundle_sbend(right_ports, left_ports)
c.add(route.references)

get_bundle_from_waypoints#

While get_bundle routes bundles of ports automatically, you can also use get_bundle_from_waypoints to manually specify the route waypoints.

You can think of get_bundle_from_waypoints as a manual version of get_bundle

[36]:
import numpy as np
import gdsfactory as gf


@gf.cell
def test_connect_bundle_waypoints(layer=(1, 0)):
    """Connect bundle of ports with bundle of routes following a list of waypoints."""
    ys1 = np.array([0, 5, 10, 15, 30, 40, 50, 60]) + 0.0
    ys2 = np.array([0, 10, 20, 30, 70, 90, 110, 120]) + 500.0
    N = ys1.size

    ports1 = [
        gf.Port(
            name=f"A_{i}", midpoint=(0, ys1[i]), width=0.5, orientation=0, layer=layer
        )
        for i in range(N)
    ]
    ports2 = [
        gf.Port(
            name=f"B_{i}",
            midpoint=(500, ys2[i]),
            width=0.5,
            orientation=180,
            layer=layer,
        )
        for i in range(N)
    ]

    p0 = ports1[0].position

    c = gf.Component("B")
    c.add_ports(ports1)
    c.add_ports(ports2)
    waypoints = [
        p0 + (200, 0),
        p0 + (200, -200),
        p0 + (400, -200),
        (p0[0] + 400, ports2[0].y),
    ]

    routes = gf.routing.get_bundle_from_waypoints(ports1, ports2, waypoints)
    lengths = {}
    for i, route in enumerate(routes):
        c.add(route.references)
        lengths[i] = route.length

    return c


cell = test_connect_bundle_waypoints()
cell
../_images/notebooks_04_routing_49_0.png
[36]:
test_connect_bundle_waypoints: uid 488, ports ['A_0', 'A_1', 'A_2', 'A_3', 'A_4', 'A_5', 'A_6', 'A_7', 'B_0', 'B_1', 'B_2', 'B_3', 'B_4', 'B_5', 'B_6', 'B_7'], aliases [], 0 polygons, 72 references
[37]:
import numpy as np
import gdsfactory as gf

c = gf.Component()
r = c << gf.components.array(
    component=gf.components.straight, rows=2, columns=1, spacing=(0, 20)
)

r.movex(60)
r.movey(40)

lt = c << gf.components.straight(length=15)
lb = c << gf.components.straight(length=5)
lt.movey(5)

ports1 = lt.get_ports_list(orientation=0) + lb.get_ports_list(orientation=0)
ports2 = r.get_ports_list(orientation=180)


dx = 20
p0 = ports1[0].midpoint + (dx, 0)
p1 = (ports1[0].midpoint[0] + dx, ports2[0].midpoint[1])
waypoints = (p0, p1)

routes = gf.routing.get_bundle_from_waypoints(ports1, ports2, waypoints=waypoints)
for route in routes:
    c.add(route.references)
c
/home/runner/work/gdsfactory/gdsfactory/gdsfactory/component.py:1054: UserWarning: Component 'Unnamed_d86649bb' contains 1 Unnamed cells
  warnings.warn(
../_images/notebooks_04_routing_50_1.png
[37]:
Unnamed_d86649bb: uid 531, ports [], aliases [], 0 polygons, 13 references

get_bundle_from_steps#

[38]:
import gdsfactory as gf

c = gf.Component("get_route_from_steps_sample")
w = gf.components.array(
    gf.partial(gf.components.straight, layer=(2, 0)),
    rows=3,
    columns=1,
    spacing=(0, 50),
)

left = c << w
right = c << w
right.move((200, 100))
p1 = left.get_ports_list(orientation=0)
p2 = right.get_ports_list(orientation=180)

routes = gf.routing.get_bundle_from_steps(
    p1,
    p2,
    steps=[{"x": 150}],
)

for route in routes:
    c.add(route.references)

c
../_images/notebooks_04_routing_52_0.png
[38]:
get_route_from_steps_sample: uid 541, ports [], aliases [], 0 polygons, 17 references

get_bundle_path_length_match#

Sometimes you need to set up a route a bundle of ports that need to keep the same lengths

[39]:
import gdsfactory as gf

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
layer = (1, 0)

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

routes = gf.routing.get_bundle_path_length_match(ports1, ports2)

for route in routes:
    c.add(route.references)
    print(route.length)
c
2659.822
2659.822
2659.822
2659.822
2659.822
2659.822
2659.822
2659.822
2659.822
2659.822
2659.822
2659.822
../_images/notebooks_04_routing_54_1.png
[39]:
path_length_match_sample: uid 550, ports [], aliases [], 0 polygons, 130 references

Add extra length#

You can also add some extra length to all the routes

[40]:
import gdsfactory as gf

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
layer = (1, 0)

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

routes = gf.routing.get_bundle_path_length_match(ports1, ports2, extra_length=44)
for route in routes:
    c.add(route.references)
    print(route.length)
c
2703.822
2703.822
2703.822
2703.822
2703.822
2703.822
2703.822
2703.822
2703.822
2703.822
2703.822
2703.822
../_images/notebooks_04_routing_56_1.png
[40]:
path_length_match_sample: uid 622, ports [], aliases [], 0 polygons, 132 references

increase number of loops#

You can also increase the number of loops

[41]:
c = gf.Component("path_length_match_sample")

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

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

a1 = 90
a2 = a1 + 180
layer = (1, 0)

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

routes = gf.routing.get_bundle_path_length_match(
    ports1, ports2, nb_loops=2, auto_widen=False
)
for route in routes:
    c.add(route.references)
    print(route.length)
c
3586.37
3586.37
3586.37
3586.37
3586.37
3586.37
3586.37
3586.37
3586.37
3586.37
3586.37
3586.37
../_images/notebooks_04_routing_58_1.png
[41]:
path_length_match_sample: uid 689, ports [], aliases [], 0 polygons, 200 references
[42]:
# Problem, sometimes when you do path length matching you need to increase the separation
import gdsfactory as gf

c = gf.Component()
c1 = c << gf.components.straight_array(spacing=90)
c2 = c << gf.components.straight_array(spacing=5)
c2.movex(200)
c1.y = 0
c2.y = 0

routes = gf.routing.get_bundle_path_length_match(
    c1.get_ports_list(orientation=0),
    c2.get_ports_list(orientation=180),
    end_straight_length=0,
    start_straight_length=0,
    separation=30,
    radius=5,
)

for route in routes:
    c.add(route.references)
c
/home/runner/work/gdsfactory/gdsfactory/gdsfactory/component.py:1054: UserWarning: Component 'Unnamed_d05db35a' contains 1 Unnamed cells
  warnings.warn(
../_images/notebooks_04_routing_59_1.png
[42]:
Unnamed_d05db35a: uid 756, ports [], aliases [], 0 polygons, 42 references
[43]:
# Solution: increase separation
import gdsfactory as gf

c = gf.Component()
c1 = c << gf.components.straight_array(spacing=90)
c2 = c << gf.components.straight_array(spacing=5)
c2.movex(200)
c1.y = 0
c2.y = 0

routes = gf.routing.get_bundle_path_length_match(
    c1.get_ports_list(orientation=0),
    c2.get_ports_list(orientation=180),
    end_straight_length=0,
    start_straight_length=0,
    separation=80,  # increased
    radius=5,
)

for route in routes:
    c.add(route.references)
c
/home/runner/work/gdsfactory/gdsfactory/gdsfactory/component.py:1054: UserWarning: Component 'Unnamed_37789447' contains 1 Unnamed cells
  warnings.warn(
../_images/notebooks_04_routing_60_1.png
[43]:
Unnamed_37789447: uid 774, ports [], aliases [], 0 polygons, 42 references

Route to IO (Pads, grating couplers …)#

Route to electrical pads#

[44]:
import gdsfactory as gf

mzi = gf.components.straight_heater_metal(length=30)
mzi
../_images/notebooks_04_routing_62_0.png
[44]:
straight_heater_metal_u_3ff09402: uid 787, ports ['o1', 'o2', 'e1', 'e2'], aliases [], 0 polygons, 5 references
[45]:
import gdsfactory as gf

mzi = gf.components.mzi_phase_shifter(
    length_x=30, straight_x_top=gf.components.straight_heater_metal_90_90
)
mzi_te = gf.routing.add_electrical_pads_top(component=mzi, layer=(41, 0))
mzi_te
../_images/notebooks_04_routing_63_0.png
[45]:
mzi_5911ef5e_add_electr_323ad49c: uid 806, ports ['o1', 'o2', 'e2', 'e1'], aliases [], 0 polygons, 4 references
[46]:
import gdsfactory as gf

hr = gf.components.straight_heater_metal()
cc = gf.routing.add_electrical_pads_shortest(component=hr, layer=(41, 0))
cc
../_images/notebooks_04_routing_64_0.png
[46]:
straight_heater_metal_u_7dc7e623: uid 814, ports ['pad1_e1', 'pad1_e2', 'pad1_e3', 'pad1_e4', 'pad1_pad', 'pad2_e1', 'pad2_e2', 'pad2_e3', 'pad2_e4', 'pad2_pad', 'o1', 'o2'], aliases [], 2 polygons, 3 references
[47]:
# Problem: Sometimes the shortest path does not work well
import gdsfactory as gf

c = gf.components.mzi_phase_shifter_top_heater_metal(length_x=70)
cc = gf.routing.add_electrical_pads_shortest(component=c, layer=(41, 0))
cc
../_images/notebooks_04_routing_65_0.png
[47]:
mzi_78bded51_add_electr_1c9fa583: uid 824, ports ['pad1_e1', 'pad1_e2', 'pad1_e3', 'pad1_e4', 'pad1_pad', 'pad2_e1', 'pad2_e2', 'pad2_e3', 'pad2_e4', 'pad2_pad', 'o1', 'o2'], aliases [], 2 polygons, 3 references
[48]:
# Solution: you can use define the pads separate and route metal lines to them

c = gf.Component("mzi_with_pads")
c1 = c << gf.components.mzi_phase_shifter_top_heater_metal(length_x=70)
c2 = c << gf.components.pad_array(columns=2)

c2.ymin = c1.ymax + 20
c2.x = 0
c1.x = 0
c
../_images/notebooks_04_routing_66_0.png
[48]:
mzi_with_pads: uid 827, ports [], aliases [], 0 polygons, 2 references
[49]:
c = gf.Component("mzi_with_pads")
c1 = c << gf.components.mzi_phase_shifter(
    straight_x_top=gf.components.straight_heater_metal_90_90, length_x=70  # 150
)
c2 = c << gf.components.pad_array(columns=2, orientation=270)

c2.ymin = c1.ymax + 30
c2.x = 0
c1.x = 0

ports1 = c1.get_ports_list(port_type="electrical")
ports2 = c2.get_ports_list()

routes = gf.routing.get_bundle(
    ports1=ports1,
    ports2=ports2,
    cross_section=gf.cross_section.metal1,
    width=10,
    bend=gf.components.wire_corner,
)
for route in routes:
    c.add(route.references)

c
../_images/notebooks_04_routing_67_0.png
[49]:
mzi_with_pads: uid 828, ports [], aliases [], 0 polygons, 12 references

Route to Fiber Array#

Routing allows you to define routes to optical or electrical IO (grating couplers or electrical pads)

[50]:
import numpy as np
import gdsfactory as gf
from gdsfactory import LAYER
from gdsfactory import Port


@gf.cell
def big_device(w=400.0, h=400.0, N=16, port_pitch=15.0, layer=LAYER.WG, wg_width=0.5):
    """big component with N ports on each side"""
    component = gf.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 = Port(
            name=f"W{i}",
            midpoint=p0 + (-dx, (i - N / 2) * port_pitch),
            orientation=180,
            **port_params,
        )

        component.add_port(port)

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

        component.add_port(port)

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

        component.add_port(port)

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

        component.add_port(port)
    return component


component = big_device(N=10)
c = gf.routing.add_fiber_array(component=component, radius=10.0, fanout_length=60.0)
c
../_images/notebooks_04_routing_69_0.png
[50]:
big_device_N10_add_fibe_d3d24951: uid 843, ports ['vertical_te_00', 'vertical_te_01', 'vertical_te_02', 'vertical_te_03', 'vertical_te_04', 'vertical_te_05', 'vertical_te_06', 'vertical_te_07', 'vertical_te_08', 'vertical_te_09', 'vertical_te_010', 'vertical_te_011', 'vertical_te_012', 'vertical_te_013', 'vertical_te_014', 'vertical_te_015', 'vertical_te_016', 'vertical_te_017', 'vertical_te_018', 'vertical_te_019', 'vertical_te_020', 'vertical_te_021', 'vertical_te_022', 'vertical_te_023', 'vertical_te_024', 'vertical_te_025', 'vertical_te_026', 'vertical_te_027', 'vertical_te_028', 'vertical_te_029', 'vertical_te_030', 'vertical_te_031', 'vertical_te_032', 'vertical_te_033', 'vertical_te_034', 'vertical_te_035', 'vertical_te_036', 'vertical_te_037', 'vertical_te_038', 'vertical_te_039', 'vertical_te_10', 'vertical_te_20'], aliases [], 0 polygons, 364 references
[51]:
import gdsfactory as gf

c = gf.components.ring_double(width=0.8)
cc = gf.routing.add_fiber_array(component=c, taper_length=150)
cc
../_images/notebooks_04_routing_70_0.png
[51]:
ring_double_width0p8_ad_abd73a69: uid 1083, ports ['vertical_te_00', 'vertical_te_01', 'vertical_te_02', 'vertical_te_03', 'vertical_te_10', 'vertical_te_20'], aliases [], 0 polygons, 50 references
[52]:
cc.pprint()
name: ring_double_width0p8_ad_abd73a69
settings:
  changed:
    component:
      name: ring_double_width0p8
      settings:
        changed: &id001
          width: 0.8
        child: null
        default: &id002
          bend: null
          coupler_ring:
            function: coupler_ring
          cross_section:
            function: cross_section
            settings:
              add_bbox:
                function: add_bbox_siepic
              add_pins:
                function: add_pins_siepic
                settings:
                  pin_length: 0.002
              cladding_layers:
              - DEVREC
              cladding_offsets:
              - 0
          gap: 0.2
          length_x: 0.01
          length_y: 0.01
          radius: 10.0
          straight:
            function: straight
        full: &id003
          bend: null
          coupler_ring:
            function: coupler_ring
          cross_section:
            function: cross_section
            settings:
              add_bbox:
                function: add_bbox_siepic
              add_pins:
                function: add_pins_siepic
                settings:
                  pin_length: 0.002
              cladding_layers:
              - DEVREC
              cladding_offsets:
              - 0
          gap: 0.2
          length_x: 0.01
          length_y: 0.01
          radius: 10.0
          straight:
            function: straight
          width: 0.8
        function_name: ring_double
        info: &id004 {}
        info_version: 2
        module: gdsfactory.components.ring_double
        name: ring_double_width0p8
      version: 0.0.1
    taper_length: 150
  child:
    changed:
      width: 0.8
    child: null
    default:
      bend: null
      coupler_ring:
        function: coupler_ring
      cross_section:
        function: cross_section
        settings:
          add_bbox:
            function: add_bbox_siepic
          add_pins:
            function: add_pins_siepic
            settings:
              pin_length: 0.002
          cladding_layers:
          - DEVREC
          cladding_offsets:
          - 0
      gap: 0.2
      length_x: 0.01
      length_y: 0.01
      radius: 10.0
      straight:
        function: straight
    full:
      bend: null
      coupler_ring:
        function: coupler_ring
      cross_section:
        function: cross_section
        settings:
          add_bbox:
            function: add_bbox_siepic
          add_pins:
            function: add_pins_siepic
            settings:
              pin_length: 0.002
          cladding_layers:
          - DEVREC
          cladding_offsets:
          - 0
      gap: 0.2
      length_x: 0.01
      length_y: 0.01
      radius: 10.0
      straight:
        function: straight
      width: 0.8
    function_name: ring_double
    info: {}
    info_version: 2
    module: gdsfactory.components.ring_double
    name: ring_double_width0p8
  default:
    component:
      function: straight
    component_name: null
    cross_section: strip
    gc_port_labels: null
    gc_port_name: o1
    get_input_labels_function:
      function: get_input_labels
    grating_coupler:
      function: grating_coupler_elliptical_trenches
      settings:
        polarization: te
        taper_angle: 35
    layer_label: TEXT
    select_ports:
      function: select_ports
      settings:
        port_type: optical
  full:
    component:
      name: ring_double_width0p8
      settings:
        changed: *id001
        child: null
        default: *id002
        full: *id003
        function_name: ring_double
        info: *id004
        info_version: 2
        module: gdsfactory.components.ring_double
        name: ring_double_width0p8
      version: 0.0.1
    component_name: null
    cross_section: strip
    gc_port_labels: null
    gc_port_name: o1
    get_input_labels_function:
      function: get_input_labels
    grating_coupler:
      function: grating_coupler_elliptical_trenches
      settings:
        polarization: te
        taper_angle: 35
    layer_label: TEXT
    select_ports:
      function: select_ports
      settings:
        port_type: optical
    taper_length: 150
  function_name: add_fiber_array
  info: {}
  info_version: 2
  module: gdsfactory.routing.add_fiber_array
  name: ring_double_width0p8_ad_abd73a69
version: 0.0.1

You can also mix and match TE and TM grating couplers

[53]:
c = gf.components.mzi_phase_shifter()
gcte = gf.components.grating_coupler_te
gctm = gf.components.grating_coupler_tm

cc = gf.routing.add_fiber_array(
    component=c,
    optical_routing_type=2,
    grating_coupler=[gctm, gcte, gctm, gcte],
    radius=20,
)
cc
../_images/notebooks_04_routing_73_0.png
[53]:
mzi_7a18d033_add_fiber__dd7e8211: uid 1128, ports ['e1', 'e2', 'vertical_tm_00', 'vertical_te_01', 'vertical_tm_10', 'vertical_tm_20'], aliases [], 0 polygons, 32 references

Route to fiber single#

[54]:
import gdsfactory as gf

c = gf.components.ring_single()
cc = gf.routing.add_fiber_single(component=c)
cc
../_images/notebooks_04_routing_75_0.png
[54]:
ring_single_move_fcf2cf_f09ac9e9: uid 1162, ports ['vertical_te_00', 'vertical_te_1', 'loopback1', 'loopback2'], aliases [], 0 polygons, 8 references
[55]:
import gdsfactory as gf

c = gf.components.ring_single()
cc = gf.routing.add_fiber_single(component=c, with_loopback=False)
cc
../_images/notebooks_04_routing_76_0.png
[55]:
ring_single_move_fcf2cf_6ec52213: uid 1171, ports ['vertical_te_00', 'vertical_te_1'], aliases [], 0 polygons, 5 references
[56]:
c = gf.components.mmi2x2()
cc = gf.routing.add_fiber_single(component=c, with_loopback=False)
cc
../_images/notebooks_04_routing_77_0.png
[56]:
mmi2x2_move_e93caf81_ad_d2b37ac1: uid 1177, ports ['vertical_te_00', 'vertical_te_01', 'vertical_te_1', 'vertical_te_2'], aliases [], 0 polygons, 25 references
[57]:
c = gf.components.mmi1x2()
cc = gf.routing.add_fiber_single(component=c, with_loopback=False, fiber_spacing=150)
cc
../_images/notebooks_04_routing_78_0.png
[57]:
mmi1x2_move_e4219bc5_ad_b073e1da: uid 1189, ports ['vertical_te_00', 'vertical_te_1', 'vertical_te_2'], aliases [], 0 polygons, 15 references
[58]:
c = gf.components.mmi1x2()
cc = gf.routing.add_fiber_single(component=c, with_loopback=False, fiber_spacing=50)
cc
../_images/notebooks_04_routing_79_0.png
[58]:
mmi1x2_move_e4219bc5_ad_0bb78b33: uid 1198, ports ['vertical_te_00', 'vertical_te_1', 'vertical_te_2'], aliases [], 0 polygons, 15 references
[59]:
c = gf.components.crossing()
cc = gf.routing.add_fiber_single(component=c, with_loopback=False)
cc
../_images/notebooks_04_routing_80_0.png
[59]:
crossing_move_5fbb1a97__7c0dc355: uid 1209, ports ['vertical_te_00', 'vertical_te_1', 'vertical_te_2', 'vertical_te_3'], aliases [], 0 polygons, 23 references
[60]:
c = gf.components.cross(length=200, width=2, port_type="optical")
cc = gf.routing.add_fiber_single(component=c, with_loopback=False)
cc
../_images/notebooks_04_routing_81_0.png
[60]:
cross_9bc31ebd_move_785_d5bc1aa6: uid 1228, ports ['vertical_te_00', 'vertical_te_1', 'vertical_te_2', 'vertical_te_3'], aliases [], 0 polygons, 23 references
[61]:
c = gf.components.spiral()
cc = gf.routing.add_fiber_single(component=c, with_loopback=False)
cc
../_images/notebooks_04_routing_82_0.png
[61]:
spiral_move_ce1b812e_ad_d80b515b: uid 1245, ports ['vertical_te_0', 'vertical_te_1'], aliases [], 0 polygons, 3 references