S-Bend MMI Route¶
This example connects the output of a 1×2 MMI splitter to the input of a second MMI using a route that contains both explicit corner bends and a spliced S-bend.
The two MMIs are placed so that their ports sit at different heights — a common layout constraint when building photonic circuits on a fixed grid. A regular rectilinear route would use three 90° bends to handle the offset; the S-bend replaces the middle jog with a single smooth element, reducing back-reflections and tightening the footprint.
Two variants are shown:
- Microns (µm) —
add_route_from_corners_with_sbends— the recommended user-facing API, consistent withadd_route_manual. - Database units (dbu) —
add_route_from_corners_with_sbends_dbu— the low-level variant for when you already work in dbu (1 dbu = 1 nm in the generic PDK, so 1 µm = 1 000 dbu).
Imports¶
from functools import partial
import gdsfactory as gf
from gdsfactory.gpdk import PDK
from doroutes.routing import (
add_route_from_corners_with_sbends,
add_route_from_corners_with_sbends_dbu,
)
PDK.activate()
Component factories¶
We use the generic PDK's strip cross-section throughout. bend_euler is
the standard 90° corner; bend_s is the S-bend element that will be spliced
in where marked.
_BEND = partial(gf.get_component, "bend_euler", radius=5, cross_section="strip")
_STRAIGHT = partial(gf.get_component, "straight", cross_section="strip")
_BEND_S = partial(gf.get_component, "bend_s", cross_section="strip")
Floorplan¶
mmi_in sits at the origin. mmi_out is placed 80 µm to the right and
50 µm above, giving a 50 µm vertical offset between the two input/output
ports. We will route mmi_in.o2 → mmi_out.o1.
Port positions (in µm):
- mmi_in.o2 : (15.5, 0.625), angle 0° (east)
- mmi_out.o1: (70.0, 50.0), angle 180° (west)
c = gf.Component("sbend_mmi_route")
mmi_in = c << gf.get_component("mmi1x2")
mmi_out = c << gf.get_component("mmi1x2")
mmi_out.dmove((80, 50))
sbend_mmi_route: ports ['o1', 'o2', 'o3'], KCell(name=mmi1x2_gdsfactorypcomponentspmmispmmi1x2_WNone_WT1_LT10_1f097353, ports=['o1', 'o2', 'o3'], pins=[], instances=[], locked=True, kcl=DEFAULT)
Route with corners + S-bend (µm)¶
The route is defined in microns — the standard user-facing unit.
mmi_in.o2
│ east
├──────────────────┐ c0 (30, 0.625) — corner: east → north
│ north
│ (30, 10) — s-bend starts here (all_points[2])
╭─────╮ s-bend: propagates north 30 µm,
│ │ shifts east 10 µm
╰─────╯ (40, 40) — s-bend ends (all_points[5])
│ north
│ (40, 50) — corner: north → east
└──────────────────── mmi_out.o1
Corner indices in sbend_jogs are all_points indices where
all_points = [start, *corners, stop]. Index 2 refers to corners[1] —
the point where the S-bend begins. The S-bend spans all_points[2..5],
i.e. through the two topology corners at indices 3 and 4.
corners_um = [
(30.0, 0.625), # c0 — east → north corner (all_points[1])
(30.0, 10.0), # c1 — north segment end / sbend in (all_points[2])
(30.0, 25.0), # c2 — Z topology corner 1 (all_points[3])
(40.0, 25.0), # c3 — Z topology corner 2 (all_points[4])
(40.0, 40.0), # c4 — sbend out (all_points[5])
(40.0, 50.0), # c5 — north → east corner (all_points[6])
]
add_route_from_corners_with_sbends(
component=c,
start=mmi_in.ports["o2"],
stop=mmi_out.ports["o1"],
corners=corners_um,
straight=_STRAIGHT,
bend=_BEND,
sbend_jogs={2: {"factory": _BEND_S}},
)
Result (µm)¶
Route with corners + S-bend (dbu)¶
The same route expressed in database units. This is the low-level API — useful when coordinates come from a layout engine or other dbu-native code.
c_dbu = gf.Component("sbend_mmi_route_dbu")
mmi_in_dbu = c_dbu << gf.get_component("mmi1x2")
mmi_out_dbu = c_dbu << gf.get_component("mmi1x2")
mmi_out_dbu.dmove((80, 50))
corners_dbu = [
(30_000, 625), # c0 — east → north corner (all_points[1])
(30_000, 10_000), # c1 — north segment end / sbend in (all_points[2])
(30_000, 25_000), # c2 — Z topology corner 1 (all_points[3])
(40_000, 25_000), # c3 — Z topology corner 2 (all_points[4])
(40_000, 40_000), # c4 — sbend out (all_points[5])
(40_000, 50_000), # c5 — north → east corner (all_points[6])
]
add_route_from_corners_with_sbends_dbu(
component=c_dbu,
start=mmi_in_dbu.ports["o2"],
stop=mmi_out_dbu.ports["o1"],
corners=corners_dbu,
straight=_STRAIGHT,
bend=_BEND,
sbend_jogs={2: {"factory": _BEND_S}},
)