Skip to content

Discretization

The A* routing functions (add_route_astar and add_bundle_astar) don't search the layout continuously — internally they project everything onto a uniform grid and search over that. Two consequences for you as a user:

  • Routes always step on grid lines. The router won't return a path finer than the grid pitch.
  • Obstacles are taken cell-by-cell. A cell that any obstacle polygon touches is treated as fully blocked.

The grid_unit parameter (in dbu) controls how fine that grid is. There's a trade-off:

  • Coarser grids (larger grid_unit) search faster, but can miss valid routes that thread through narrow gaps and produce more "boxy" paths around obstacles.
  • Finer grids (smaller grid_unit) follow obstacles more accurately and squeeze through tighter spaces, but the search space grows fast — A* slows down quadratically with the grid pitch.

There's also a hard lower bound: grid_unit must be at most half the bend radius. The router enforces this because the bend's geometry needs at least two grid cells along each axis to be representable. A useful starting point is somewhere in [radius / 20, radius / 4] — this notebook shows the difference between the two ends of that range.

Imports

import gdsfactory as gf
from gdsfactory.gpdk import PDK

import gdsfactoryplus as gfp
dr = gfp.routing.doroutes

PDK.activate()

A Route at a Coarse Grid

Routing on field1 with grid_unit = 2500 dbu (2.5 µm — exactly half the 5 µm bend radius, the coarsest the router will accept). The search has limited freedom: every step has to be a multiple of 2.5 µm, so the route can only make wide detours and the path looks blocky.

c = gf.Component()
ref = c << dr.pcells.field1()
dr.add_route_astar(
    component=c,
    start=ref.ports["o1"],
    stop=ref.ports["o2"],
    straight="straight",
    bend={"component": "bend_euler", "settings": {"radius": 5}},
    layers=["WG"],
    grid_unit=2500,
)
dr.util.show_cell(c)
API key for organization 'GDSFactory' found.

Same Route at a Finer Grid

Same start, stop, and obstacles, with grid_unit = 250 dbu (0.25 µm — a twentieth of the bend radius). The router has many more grid points to work with, so the path can hug obstacles closely and take a more compact route.

c = gf.Component()
ref = c << dr.pcells.field1()
dr.add_route_astar(
    component=c,
    start=ref.ports["o1"],
    stop=ref.ports["o2"],
    straight="straight",
    bend={"component": "bend_euler", "settings": {"radius": 5}},
    layers=["WG"],
    grid_unit=250,
)
dr.util.show_cell(c)
API key for organization 'GDSFactory' found.