Layout#

All UBC ubcpdk.cells are conveniently combined into the ubcpdk.components module.

import gdsfactory as gf

from ubcpdk import PDK, cells

PDK.activate()

Fixed Component cells#

Most ubcpdk components are imported from GDS files as fixed cells.

c = cells.ebeam_crossing4()
c.plot()
../_images/ac9b288d80a90c2f981b31ab35970631c8a6a662a3dd4a4ac0dc10a115aea1f9.png
c = cells.ebeam_swg_edgecoupler()
c.plot()
../_images/34abc6bd9116525cf06e8a52bd585b31b001ee3319e7f2a11b0fcad0ddd8efbb.png
c = cells.ebeam_bdc_te1550()
c.plot()
../_images/94ffa34b48b731f0dad5d5ab6e06b8ee5dbbd05a466209bc3a608dfdfc011395.png
c = cells.ebeam_adiabatic_te1550()
c.plot()
../_images/a1da1e996e345d01da22bd0d5d3aff282ca8746e3530da5818db5bf51aaa0553.png
c = cells.ebeam_y_adiabatic()
c.plot()
../_images/0009e746fa159cbf1e23e6d5a5f51b5ca1a785f78bab9a95c93d1da1ca236865.png
c = cells.ebeam_y_1550()
c.plot()
../_images/dfa47380814a05398cf2ccca84f17e6cba3e50b55aff1561f6583524c318a2ac.png

Parametric Component PCells#

You can also define cells adapted from gdsfactory generic pdk.

c = cells.straight(length=2)
c.plot()
../_images/524ccfa920cd1210da806d8f6cb7c9502199cc747b6e29e97f8e6c5600a3e559.png
c = cells.bend_euler(radius=5)
c.plot()
../_images/fdedb00fb1967ac2d42c7053127ccdfa187ad99a572e4b572b2b302fc65a1062.png
c = cells.spiral()
c.plot()
../_images/575e88e17ecf79161a1d6a25c4c3f1f42f66942ba6ed502a6f068fb7b8a198d8.png
c = cells.ring_single_heater()
c.plot()
../_images/25a007952dce3e465fdacef0a1e4698e4e77fd062a455202fa0dff28b89ad0fb.png

Components with grating couplers#

To test your devices you can add grating couplers. Both for single fibers and for fiber arrays.

splitter = cells.ebeam_y_1550()
mzi = gf.components.mzi(splitter=splitter)
mzi.plot()
../_images/491dd6fc2c40f6f89e9ae4261ce8ec3c1af5c92142a7cc14cc08f141a5ffc6e7.png
component_fiber_array = cells.add_fiber_array(component=mzi, fanout_length=5)
component_fiber_array.plot()
../_images/e33b62073f40f3ca515209326116d99e11b047bb1c8114b04866523793ccc21e.png
c = cells.ring_single_heater()
c = cells.add_fiber_array_pads_rf(c)
c.plot()
../_images/b98e7796817dfeb50aea266a6ae534965681abcc4b54c7370be1ddd51edc8b18.png
c = cells.mzi_heater()
c = cells.add_fiber_array_pads_rf(c)
c.plot()
../_images/f059ac530f6d16f93127e0e515268908711df98c61dcd98ce1accc8a423929d0.png

3D rendering#

scene = c.to_3d()
scene.show()

Die assembly#

from functools import partial

import gdsfactory as gf

from ubcpdk.tech import LAYER

size = (440, 470)
add_gc = cells.add_fiber_array


@gf.cell
def EBeam_JoaquinMatres_1() -> gf.Component:
    """Add DBR cavities."""
    e = [add_gc(cells.straight())]
    e += [add_gc(cells.mzi(delta_length=dl)) for dl in [9.32, 93.19]]
    e += [
        add_gc(cells.ring_single(radius=12, gap=gap, length_x=coupling_length))
        for gap in [0.2]
        for coupling_length in [2.5, 4.5, 6.5]
    ]

    c = gf.Component()
    _ = c << gf.pack(e, max_size=size, spacing=2)[0]
    _ = c << gf.components.rectangle(size=size, layer=LAYER.FLOORPLAN)
    return c


c = EBeam_JoaquinMatres_1()
c.show()  # show in klayout
c.plot()  # plot in notebook
2025-11-27 03:24:14.887 | WARNING  | kfactory.kcell:show:4022 - Could not connect to klive server
../_images/9c58b492f5c24de6d627a2db5c676f0988d0265471e6b7e92722e69fa7dc2626.png
def EBeam_JoaquinMatres_2() -> gf.Component:
    """spirals for extracting straight waveguide loss"""

    e = [
        cells.add_fiber_array(component=cells.spiral(n_loops=8, length=length))
        for length in [0, 100, 200]
    ]

    c = gf.Component()
    _ = c << gf.pack(e, max_size=size, spacing=2)[0]
    _ = c << gf.components.rectangle(size=size, layer=LAYER.FLOORPLAN)
    return c


c = EBeam_JoaquinMatres_2()
c.show()  # show in klayout
c.plot()  # plot in notebook
2025-11-27 03:24:15.247 | WARNING  | kfactory.kcell:show:4022 - Could not connect to klive server
../_images/e1f7d51bd262b376ea3ca4a556d6b58d9af2f1011249a5f97230067a8e9b9e94.png
def EBeam_JoaquinMatres_3() -> gf.Component:
    """Contains mirror cavities and structures inside a resonator."""
    e = []
    e += [add_gc(cells.ebeam_crossing4())]
    e += [add_gc(cells.ebeam_adiabatic_te1550())]
    e += [add_gc(cells.ebeam_bdc_te1550())]
    e += [add_gc(cells.ebeam_y_1550())]
    e += [add_gc(cells.straight(), component_name=f"straight_{i}") for i in range(2)]
    c = gf.Component()
    _ = c << gf.pack(e, max_size=size, spacing=2)[0]
    _ = c << gf.components.rectangle(size=size, layer=LAYER.FLOORPLAN)
    return c


c = EBeam_JoaquinMatres_3()
c.show()  # show in klayout
c.plot()  # plot in notebook
2025-11-27 03:24:15.579 | ERROR    | kfactory.kcell:name:687 - Name conflict in kfactory.kcell::name at line 687
Renaming Unnamed_349 (cell_index=349) to straight_L10_CSstrip_WNone_N2_with_gc would cause it to be named the same as:
 - straight_L10_CSstrip_WNone_N2_with_gc (cell_index=130), function_name=None, basename=None
2025-11-27 03:24:15.619 | ERROR    | kfactory.kcell:name:687 - Name conflict in kfactory.kcell::name at line 687
Renaming Unnamed_351 (cell_index=351) to straight_L10_CSstrip_WNone_N2_with_gc would cause it to be named the same as:
 - straight_L10_CSstrip_WNone_N2_with_gc (cell_index=349), function_name=None, basename=None
 - straight_L10_CSstrip_WNone_N2_with_gc (cell_index=130), function_name=None, basename=None
2025-11-27 03:24:15.672 | WARNING  | kfactory.kcell:show:4022 - Could not connect to klive server
../_images/36eb0e8b4a6f03c4c2ac44f35c7a6627a78ada36bff6ef1ad12c43602247caa2.png
def EBeam_JoaquinMatres_4() -> gf.Component:
    """MZI interferometers."""
    mzi = partial(gf.components.mzi, splitter=cells.ebeam_y_1550)
    mzis = [mzi(delta_length=delta_length) for delta_length in [10, 40]]
    mzis_gc = [cells.add_fiber_array(mzi, fanout_length=5) for mzi in mzis]

    mzis = [cells.mzi_heater(delta_length=delta_length) for delta_length in [40]]
    mzis_heater_gc = [
        cells.add_fiber_array_pads_rf(mzi, orientation=90) for mzi in mzis
    ]

    e = mzis_gc + mzis_heater_gc
    c = gf.Component()
    _ = c << gf.pack(e, max_size=size, spacing=2)[0]
    _ = c << gf.components.rectangle(size=size, layer=LAYER.FLOORPLAN)
    return c


c = EBeam_JoaquinMatres_4()
c.show()  # show in klayout
c.plot()  # plot in notebook
2025-11-27 03:24:15.912 | WARNING  | kfactory.kcell:show:4022 - Could not connect to klive server
../_images/208c9642cf9e0c66fcd71038102e68453fddd29b88b6f07a15f9fb30ecdd60f7.png
def EBeam_JoaquinMatres_5() -> gf.Component:
    """Ring resonators."""

    rings = []
    for length_x in [4, 6]:
        ring = cells.ring_single_heater(length_x=length_x)
        ring_gc = cells.add_fiber_array_pads_rf(ring, pad_yspacing=10)
        rings.append(ring_gc)

    c = gf.Component()
    _ = c << gf.pack(rings, max_size=size, spacing=2)[0]
    _ = c << gf.components.rectangle(size=size, layer=LAYER.FLOORPLAN)
    return c


c = EBeam_JoaquinMatres_5()
c.show()  # show in klayout
c.plot()  # plot in notebook
2025-11-27 03:24:16.195 | WARNING  | kfactory.kcell:show:4022 - Could not connect to klive server
../_images/c2d95eca2689182745f1705925ee985438dd5c46d853e95e8dbc2a728ac34b53.png