Source code for gdsfactory.components.couplers.coupler_broadband

from __future__ import annotations

import gdsfactory as gf
from gdsfactory.component import Component
from gdsfactory.typings import ComponentFactory, CrossSectionSpec


[docs] @gf.cell def coupler_broadband( w_sc: float = 0.5, # width of waveguides in the symmetric coupler section gap_sc: float = 0.2, # gap size between the waveguides in the symmetric coupler section w_top: float = 0.6, # width of the top waveguide in the phase control section gap_pc: float = 0.3, # gap size in the phase control section legnth_taper: float = 1.0, # length of the tapers bend: ComponentFactory = "bend_euler", coupler_straight: ComponentFactory = "coupler_straight", length_coupler_straight: float = 12.4, # optimal L_1 from the 3d fdtd analysis lenght_coupler_big_gap: float = 4.7, # optimal L_2 from the 3d fdtd analysis cross_section: CrossSectionSpec = "strip", radius: float = 10.0, ) -> Component: """Returns broadband coupler component. https://docs.flexcompute.com/projects/tidy3d/en/latest/notebooks/BroadbandDirectionalCoupler.html proposed in Zeqin Lu, Han Yun, Yun Wang, Zhitian Chen, Fan Zhang, Nicolas A. F. Jaeger, and Lukas Chrostowski, "Broadband silicon photonic directional coupler using asymmetric-waveguide based phase control," Opt. Express 23, 3795-3808 (2015), DOI: 10.1364/OE.23.003795. Args: w_sc: width of waveguides in the symmetric coupler section. gap_sc: gap size between the waveguides in the symmetric coupler section. w_top: width of the top waveguide in the phase control section. gap_pc: gap size in the phase control section. legnth_taper: length of the tapers. bend: bend factory. coupler_straight: coupler_straight factory. length_coupler_straight: optimal L_1 from the 3d fdtd analysis. lenght_coupler_big_gap: optimal L_2 from the 3d fdtd analysis. cross_section: cross_section of the waveguides. radius: bend radius. """ c = gf.Component() xs = gf.get_cross_section(cross_section) assert xs.layer is not None layer = gf.get_layer(xs.layer) L_t = legnth_taper c = Component() L_2 = lenght_coupler_big_gap L_1 = length_coupler_straight y_coupler = -w_sc + xs.width / 2 + gap_pc / 2 coupler = gf.get_component( coupler_straight, length=L_1, cross_section=cross_section, gap=gap_sc ) coupler1 = c << coupler coupler1.dxmin = -L_2 / 2 - L_t - L_1 coupler1.dy = y_coupler _bend = gf.get_component(bend, radius=radius, cross_section=cross_section) bend_lt = c << _bend bend_lb = c << _bend bend_lb.connect("o1", coupler1.ports["o1"]) bend_lt.connect("o1", coupler1.ports["o2"], mirror=True) vertices_top = [ (L_2 / 2 + L_t, 0), (L_2 / 2 + L_t, w_sc), (L_2 / 2 + L_t, w_sc), (L_2 / 2, w_top), (-L_2 / 2, w_top), (-L_2 / 2 - L_t, w_sc), (-L_2 / 2 - L_t, w_sc), (-L_2 / 2 - L_t, 0), ] c.add_polygon(vertices_top, layer=layer) # define vertices of the bottom waveguide vertices_bot = [ (L_2 / 2 + L_t, -gap_sc - w_sc), (L_2 / 2 + L_t, -gap_sc), (L_2 / 2 + L_t, -gap_sc), (L_2 / 2, -gap_pc), (-L_2 / 2, -gap_pc), (-L_2 / 2 - L_t, -gap_sc), (-L_2 / 2 - L_t, -gap_sc), (-L_2 / 2 - L_t, -gap_sc - w_sc), ] c.add_polygon(vertices_bot, layer=layer) for section in xs.sections[1:]: w = section.width / 2 layer = section.layer # type: ignore assert layer is not None vertices_top = [ (L_2 / 2 + L_t, -w), (L_2 / 2 + L_t, w), (L_2 / 2 + L_t, w), (L_2 / 2, w_top + w), (-L_2 / 2, w_top + w), (-L_2 / 2 - L_t, w), (-L_2 / 2 - L_t, w), (-L_2 / 2 - L_t, -w), ] c.add_polygon(vertices_top, layer=layer) # define vertices of the bottom waveguide vertices_bot = [ (L_2 / 2 + L_t, -gap_sc - w), (L_2 / 2 + L_t, -gap_sc + w), (L_2 / 2 + L_t, -gap_sc + w), (L_2 / 2, -gap_pc + w), (-L_2 / 2, -gap_pc + w), (-L_2 / 2 - L_t, -gap_sc + w), (-L_2 / 2 - L_t, -gap_sc + w), (-L_2 / 2 - L_t, -gap_sc - w), ] c.add_polygon(vertices_bot, layer=layer) coupler2 = c << coupler coupler2.dxmax = L_2 / 2 + L_t + L_1 coupler2.dy = y_coupler _bend = gf.get_component(bend, radius=radius, cross_section=cross_section) bend_rt = c << _bend bend_rb = c << _bend bend_rb.connect("o1", coupler2.ports["o3"]) bend_rt.connect("o1", coupler2.ports["o4"], mirror=True) c.add_port("o1", port=bend_lb.ports["o2"]) c.add_port("o2", port=bend_lt.ports["o2"]) c.add_port("o3", port=bend_rt.ports["o2"]) c.add_port("o4", port=bend_rb.ports["o2"]) return c
if __name__ == "__main__": c = coupler_broadband(cross_section="rib") c.show()