Source code for gdsfactory.components.grating_coupler_elliptical_trenches

from __future__ import annotations

from functools import partial

import numpy as np

import gdsfactory as gf
from gdsfactory.component import Component
from gdsfactory.components.grating_coupler_elliptical import grating_tooth_points
from gdsfactory.geometry.functions import DEG2RAD
from gdsfactory.typings import CrossSectionSpec, LayerSpec


[docs] @gf.cell def grating_coupler_elliptical_trenches( polarization: str = "te", taper_length: float = 16.6, taper_angle: float = 30.0, trenches_extra_angle: float = 9.0, wavelength: float = 1.53, fiber_angle: float = 15.0, grating_line_width: float = 0.343, neff: float = 2.638, # tooth effective index ncladding: float = 1.443, # cladding index layer_trench: LayerSpec | None = "SHALLOW_ETCH", p_start: int = 26, n_periods: int = 30, end_straight_length: float = 0.2, cross_section: CrossSectionSpec = "xs_sc", **kwargs, ) -> Component: r"""Returns Grating coupler with defined trenches. Some foundries define the grating coupler by a shallow etch step (trenches) Others define the slab that they keep (see grating_coupler_elliptical) Args: polarization: 'te' or 'tm'. taper_length: taper length from straight I/O. taper_angle: grating flare angle. wavelength: grating transmission central wavelength. fiber_angle: fibre polish angle in degrees. grating_line_width: of the 220 ridge. neff: tooth effective index. ncladding: cladding index. layer_trench: for the trench. p_start: first tooth. n_periods: number of grating teeth. end_straight_length: at the end of straight. cross_section: cross_section spec. kwargs: cross_section settings. .. code:: fiber / / / / / / / / _|-|_|-|_|-|___ WG o1 ______________| """ xs = gf.get_cross_section(cross_section, **kwargs) wg_width = xs.width layer = xs.layer # Compute some ellipse parameters sthc = np.sin(fiber_angle * DEG2RAD) d = neff**2 - ncladding**2 * sthc**2 a1 = wavelength * neff / d b1 = wavelength / np.sqrt(d) x1 = wavelength * ncladding * sthc / d a1 = round(a1, 3) b1 = round(b1, 3) x1 = round(x1, 3) period = float(a1 + x1) trench_line_width = period - grating_line_width c = gf.Component() # Make each grating line for p in range(int(p_start), int(p_start + n_periods + 1)): pts = grating_tooth_points( p * a1, p * b1, p * x1, width=trench_line_width, taper_angle=taper_angle + trenches_extra_angle, ) c.add_polygon(pts, layer_trench) # Make the taper p_taper = p_start - 1 p_taper_eff = p_taper a_taper = a1 * p_taper_eff # b_taper = b1 * p_taper_eff x_taper = x1 * p_taper_eff x_output = a_taper + x_taper - taper_length + grating_line_width / 2 xmax = x_output + taper_length + n_periods * period + 3 y = wg_width / 2 + np.tan(taper_angle / 2 * np.pi / 180) * xmax pts = [ (x_output, -wg_width / 2), (x_output, +wg_width / 2), (xmax, +y), (xmax + end_straight_length, +y), (xmax + end_straight_length, -y), (xmax, -y), ] c.add_polygon(pts, layer) x_output = gf.snap.snap_to_grid(x_output) c.add_port( name="o1", center=(x_output, 0), width=wg_width, orientation=180, layer=layer, cross_section=xs, ) c.info["period"] = period c.info["polarization"] = polarization c.info["wavelength"] = wavelength x = np.round(taper_length + period * n_periods / 2, 3) c.add_port( name="o2", center=(x, 0), width=10, orientation=0, layer=layer, port_type=f"optical_{polarization}", ) return c
grating_coupler_te = partial( grating_coupler_elliptical_trenches, polarization="te", taper_angle=35 ) grating_coupler_tm = partial( grating_coupler_elliptical_trenches, polarization="tm", neff=1.8, grating_line_width=0.6, ) if __name__ == "__main__": c = grating_coupler_te() # c = grating_coupler_elliptical_trenches(polarization="TE") # print(c.polarization) # c = grating_coupler_te(end_straight_length=10) # c = grating_coupler_tm() # print(c.ports.keys()) # c = gf.routing.add_fiber_array(grating_coupler=grating_coupler_elliptical_trenches) c.show(show_ports=True)