Source code for gdsfactory.components.grating_coupler_rectangular

from __future__ import annotations

import numpy as np

import gdsfactory as gf
from gdsfactory.component import Component
from gdsfactory.components.rectangle import rectangle
from gdsfactory.components.taper import taper as taper_function
from gdsfactory.typings import (
    ComponentSpec,
    CrossSectionSpec,
    LayerSpec,
)


[docs] @gf.cell def grating_coupler_rectangular( n_periods: int = 20, period: float = 0.75, fill_factor: float = 0.5, width_grating: float = 11.0, length_taper: float = 150.0, polarization: str = "te", wavelength: float = 1.55, taper: ComponentSpec = taper_function, layer_slab: LayerSpec | None = None, layer_grating: LayerSpec | None = None, fiber_angle: float | None = None, slab_xmin: float = -1.0, slab_offset: float = 1.0, cross_section: CrossSectionSpec = "xs_sc", **kwargs, ) -> Component: r"""Grating coupler with rectangular shapes (not elliptical). Needs longer taper than elliptical. Grating teeth are straight. For a focusing grating take a look at grating_coupler_elliptical. Args: n_periods: number of grating teeth. period: grating pitch. fill_factor: ratio of grating width vs gap. width_grating: 11. length_taper: 150. polarization: 'te' or 'tm'. wavelength: in um. taper: function. layer_slab: layer that protects the slab under the grating. layer_grating: optional layer for the grating. Defaults to the cross_section main layer. fiber_angle: in degrees. slab_xmin: where 0 is at the start of the taper. slab_offset: from edge of grating to edge of the slab. cross_section: for input waveguide port. kwargs: cross_section settings. .. code:: side view fiber / / / / / / / / _|-|_|-|_|-|___ layer layer_slab | o1 ______________| top view _________ /| | | | | / | | | | | /taper_angle /_ _| | | | | wg_width | | | | | | \ | | | | | \ | | | | | \ | | | | | \|_|_|_|_| <--> taper_length """ xs = gf.get_cross_section(cross_section, **kwargs) wg_width = xs.width layer = layer_grating or xs.layer c = Component() taper_ref = c << gf.get_component( taper, length=length_taper, width2=width_grating, width1=wg_width, cross_section=cross_section, ) c.add_port(port=taper_ref.ports["o1"], name="o1") x0 = taper_ref.xmax for i in range(n_periods): xsize = gf.snap.snap_to_grid(period * fill_factor) cgrating = c.add_ref( rectangle(size=(xsize, width_grating), layer=layer, port_type=None) ) cgrating.xmin = gf.snap.snap_to_grid(x0 + i * period) cgrating.y = 0 if fiber_angle is not None: c.info["fiber_angle"] = fiber_angle c.info["polarization"] = polarization c.info["wavelength"] = wavelength slab_xmin = length_taper for section in xs.sections[1:]: slab_xsize = cgrating.xmax + section.width / 2 slab_ysize = width_grating + section.width yslab = slab_ysize / 2 c.add_polygon( [ (slab_xmin, yslab), (slab_xsize, yslab), (slab_xsize, -yslab), (slab_xmin, -yslab), ], layer=section.layer, ) if layer_slab: slab_xsize = cgrating.xmax + slab_offset slab_ysize = width_grating + 2 * slab_offset yslab = slab_ysize / 2 c.add_polygon( [ (slab_xmin, yslab), (slab_xsize, yslab), (slab_xsize, -yslab), (slab_xmin, -yslab), ], layer_slab, ) xport = np.round((x0 + cgrating.x) / 2, 3) c.add_port( name="o2", port_type=f"vertical_{polarization}", center=(xport, 0), orientation=0, width=width_grating, layer=layer, ) return c
if __name__ == "__main__": # c = grating_coupler_rectangular(name='gcu', partial_etch=True) gc = grating_coupler_rectangular(cross_section="xs_rc") c = gf.routing.add_fiber_array(grating_coupler=gc) print(c.ports) c.show(show_ports=False)