from __future__ import annotations
import gdsfactory as gf
from gdsfactory.component import Component
from gdsfactory.components.bend_euler import bend_euler
from gdsfactory.components.coupler90 import coupler90
from gdsfactory.components.coupler_straight import coupler_straight
from gdsfactory.components.straight import straight
from gdsfactory.typings import (
ComponentFactory,
ComponentSpec,
Coordinates,
CrossSectionSpec,
LayerSpecs,
)
[docs]
@gf.cell
def coupler_ring(
gap: float = 0.2,
radius: float = 5.0,
length_x: float = 4.0,
coupler90: ComponentFactory = coupler90,
bend: ComponentSpec = bend_euler,
coupler_straight: ComponentFactory = coupler_straight,
cross_section: CrossSectionSpec = "xs_sc",
cross_section_bend: CrossSectionSpec | None = None,
length_extension: float = 3,
) -> Component:
r"""Coupler for ring.
Args:
gap: spacing between parallel coupled straight waveguides.
radius: of the bends.
length_x: length of the parallel coupled straight waveguides.
coupler90: straight coupled to a 90deg bend.
bend: bend spec.
coupler_straight: two parallel coupled straight waveguides.
cross_section: cross_section spec.
cross_section_bend: optional bend cross_section spec.
length_extension: for the ports.
.. code::
o2 o3
| |
\ /
\ /
---=========---
o1 length_x o4
"""
c = Component()
gap = gf.snap.snap_to_grid(gap, grid_factor=2)
xs = gf.get_cross_section(cross_section)
cross_section_bend = cross_section_bend or xs
xs_bend = gf.get_cross_section(cross_section_bend)
xs_bend = xs_bend.copy(radius=radius)
# define subcells
coupler90_component = coupler90(
gap=gap,
radius=radius,
bend=bend,
cross_section=xs,
cross_section_bend=xs_bend,
)
coupler_straight_component = coupler_straight(
gap=gap,
length=length_x,
cross_section=xs,
)
# add references to subcells
cbl = c << coupler90_component
cbr = c << coupler90_component
cs = coupler_straight_component.ref()
if length_x > 0:
c.add(cs)
# connect references
y = coupler90_component.y
cs.connect(port="o4", destination=cbr.ports["o1"])
cbl.mirror(p1=(0, y), p2=(1, y))
cbl.connect(port="o2", destination=cs.ports["o2"])
s = straight(length=length_extension, cross_section=xs)
s1 = c << s
s2 = c << s
s1.connect("o2", cbl["o4"])
s2.connect("o1", cbr["o4"])
c.add_port("o1", port=s1["o1"])
c.add_port("o2", port=cbl["o3"])
c.add_port("o3", port=cbr["o3"])
c.add_port("o4", port=s2["o2"])
c.add_ports(cbl.get_ports_list(port_type="electrical"), prefix="cbl")
c.add_ports(cbr.get_ports_list(port_type="electrical"), prefix="cbr")
c.auto_rename_ports()
return c
[docs]
@gf.cell
def coupler_ring_point(
coupler_ring: ComponentFactory = coupler_ring,
open_layers: LayerSpecs | None = None,
open_sizes: Coordinates | None = None,
**kwargs,
) -> Component:
"""Coupler ring that removes some layers at the coupling region.
This allows short interaction lengths (point couplers).
Args:
coupler_ring: coupler_ring component to process.
open_layers: layers to perform the boolean operations on.
open_sizes: sizes of the boxes to use to remove layers, centered at bus center.
Keyword Args:
gap: spacing between parallel coupled straight waveguides.
radius: of the bends.
length_x: length of the parallel coupled straight waveguides.
coupler90: straight coupled to a 90deg bend.
bend: bend spec.
coupler_straight: two parallel coupled straight waveguides.
cross_section: cross_section spec.
length_extension: for the ports.
"""
c = gf.Component()
coupler_ring_component = coupler_ring(**kwargs)
open_layers = open_layers or []
open_sizes = open_sizes or []
open_layers_tuples = [gf.get_layer(open_layer) for open_layer in open_layers]
untouched_layers = list(
set(coupler_ring_component.get_layers()) - set(open_layers_tuples)
)
for layer, size in zip(open_layers, open_sizes):
subcomponent = coupler_ring_component.extract(layers=[layer])
rectangle = gf.components.rectangle(size=size, layer=layer, centered=True)
_ = c << gf.geometry.boolean(subcomponent, rectangle, "A-B", layer=layer)
coupler_ref = c << coupler_ring_component.extract(layers=untouched_layers)
c.add_ports(coupler_ring_component.get_ports_list())
c.absorb(coupler_ref)
return c
if __name__ == "__main__":
c = coupler_ring(cross_section_bend="xs_sc_heater_metal")
c.show(show_ports=False)