Source code for gdsfactory.components.coupler_full

from __future__ import annotations

import gdsfactory as gf
from gdsfactory.component import Component
from gdsfactory.components import bend_s
from gdsfactory.typings import CrossSectionSpec


[docs] @gf.cell def coupler_full( coupling_length: float = 40.0, dx: float = 10.0, dy: float = 4.8, gap: float = 0.5, dw: float = 0.1, cross_section: CrossSectionSpec = "xs_sc", **kwargs, ) -> Component: """Adiabatic Full coupler. Design based on asymmetric adiabatic full coupler designs, such as the one reported in 'Integrated Optic Adiabatic Devices on Silicon' by Y. Shani, et al (IEEE Journal of Quantum Electronics, Vol. 27, No. 3 March 1991). 1. is the first half of the input S-bend straight where the input straights widths taper by +dw and -dw, 2. is the second half of the S-bend straight with constant, unbalanced widths, 3. is the coupling region where the straights from unbalanced widths to balanced widths to reverse polarity unbalanced widths, 4. is the fixed width straight that curves away from the coupling region, 5.is the final curve where the straights taper back to the regular width specified in the straight template. Args: coupling_length: Length of the coupling region in um. dx: Length of the bend regions in um. dy: Port-to-port distance between the bend regions in um. gap: Distance between the two straights in um. dw: delta width. Top arm tapers to width - dw, bottom to width + dw in um. cross_section: cross-section spec. Keyword Args: cross_section kwargs. """ c = gf.Component() x = gf.get_cross_section(cross_section=cross_section, **kwargs) x_top = x.copy(width=x.width + dw) x_bottom = x.copy(width=x.width - dw) taper_top = c << gf.components.taper( length=coupling_length, width1=x_top.width, width2=x_bottom.width, cross_section=x_top, ) taper_bottom = c << gf.components.taper( length=coupling_length, width1=x_bottom.width, width2=x_top.width, cross_section=x_bottom, ) bend_input_top = ( c << bend_s( size=(dx, (dy - gap - x_top.width) / 2.0), cross_section=x_top ).mirror() ) bend_input_top.movey(origin=0, destination=(x_top.width + gap) / 2.0) bend_input_bottom = ( c << bend_s( size=(dx, (-dy + gap + x_bottom.width) / 2.0), cross_section=x_bottom ).mirror() ) bend_input_bottom.movey(origin=0, destination=-(x_bottom.width + gap) / 2.0) taper_top.connect("o1", bend_input_top.ports["o1"]) taper_bottom.connect("o1", bend_input_bottom.ports["o1"]) bend_output_top = c << bend_s( size=(dx, (dy - gap - x_top.width) / 2.0), cross_section=x_bottom ) bend_output_top.move(destination=taper_top.ports["o2"]) bend_output_bottom = c << bend_s( size=(dx, (-dy + gap + x_bottom.width) / 2.0), cross_section=x_top ) bend_output_bottom.move(destination=taper_bottom.ports["o2"]) bend_output_top.connect("o2", taper_top.ports["o2"]) bend_output_bottom.connect("o2", taper_bottom.ports["o2"]) c.absorb(bend_input_bottom) c.absorb(bend_input_top) c.absorb(bend_output_top) c.absorb(bend_output_bottom) c.absorb(taper_top) c.absorb(taper_bottom) c.add_port("o1", port=bend_input_bottom.ports["o2"]) c.add_port("o2", port=bend_input_top.ports["o2"]) c.add_port("o3", port=bend_output_top.ports["o1"]) c.add_port("o4", port=bend_output_bottom.ports["o1"]) return c
if __name__ == "__main__": c = coupler_full( # coupling_length=40, # gap=0.2, # dw=0.1, # cladding_layers=[(111, 0)], # cladding_offsets=[3], ) c.show() # c.show(show_ports=True)