def crossing_from_taper(taper=lambda: taper(width2=2.5, length=3.0)): """ Crossing based on a taper. The default is a dummy taper """ taper = pp.call_if_func(taper) c = pp.Component() for i, a in enumerate([0, 90, 180, 270]): _taper = taper.ref(position=(0, 0), port_id="2", rotation=a) c.add(_taper) c.add_port(name="{}".format(i), port=_taper.ports["1"]) c.absorb(_taper) c = pp.ports.port_naming.rename_ports_by_orientation(c) return c
def grating_coupler_uniform( num_teeth: int = 20, period: float = 0.75, fill_factor: float = 0.5, width_grating: float = 11.0, length_taper: float = 150.0, width: float = 0.5, partial_etch: bool = False, layer: Tuple[int, int] = pp.LAYER.WG, layer_partial_etch: Tuple[int, int] = pp.LAYER.SLAB150, polarization="te", wavelength=1500, ) -> Component: """Grating coupler uniform Args: num_teeth: 20 period: 0.75 fill_factor: 0.5 width_grating: 11 length_taper: 150 width: 0.5 partial_etch: False .. plot:: :include-source: import pp c = pp.c.grating_coupler_uniform() pp.plotgds(c) """ # returns a fiber grating G = Component() if partial_etch: partetch_overhang = 5 _compass = compass( size=[period * (1 - fill_factor), width_grating + partetch_overhang * 2], layer=layer_partial_etch, ) # make the etched areas (opposite to teeth) for i in range(num_teeth): cgrating = G.add_ref(_compass) cgrating.x += i * period # draw the deep etched square around the grating deepbox = G.add_ref( compass(size=[num_teeth * period, width_grating], layer=layer) ) deepbox.movex(num_teeth * period / 2) else: for i in range(num_teeth): cgrating = G.add_ref( compass(size=[period * fill_factor, width_grating], layer=layer) ) cgrating.x += i * period # make the taper tgrating = G.add_ref( taper( length=length_taper, width1=width_grating, width2=width, port=None, layer=layer, ) ) tgrating.xmin = cgrating.xmax G.add_port(port=tgrating.ports["2"], name="W0") G.polarization = polarization G.wavelength = wavelength G.rotate(180) return G
def delay_snake( total_length=160000, L0=2350.0, n=5, taper=taper, bend_factory=bend_circular, bend_radius=10.0, straight_factory=waveguide, wg_width=0.5, ): """ Snake input facing west Snake output facing east Args: total_length: L0: n: taper: bend_factory bend_radius straight_factory wg_width .. code:: | L0 | L2 | ->-------------| | pi * radius |-------------------| | |-------------------> | L1 | .. plot:: :include-source: import pp c = pp.c.delay_snake(L0=5, total_length=1600, n=2) pp.plotgds(c) """ epsilon = 0.1 R = bend_radius bend90 = bend_factory(radius=R, width=wg_width) L1 = (total_length + L0 - n * (pi * R + epsilon)) / (2 * n + 1) L2 = L1 - L0 assert ( L2 > 0), "Snake is too short: either reduce L0, increase the total length,\ or decrease n" y = 0 path = [(0, y), (L2, y)] for i in range(n): y -= 2 * R + epsilon path += [(L2, y), (-L0, y)] y -= 2 * R + epsilon path += [(-L0, y), (L2, y)] path = [(round(_x, 3), round(_y, 3)) for _x, _y in path] component = pp.Component() if taper != None: if callable(taper): _taper = taper(width1=wg_width, width2=WG_EXPANDED_WIDTH, length=TAPER_LENGTH) else: _taper = taper else: _taper = None snake = round_corners(path, bend90, straight_factory, taper=_taper) component.add(snake) component.ports = snake.ports pp.ports.port_naming.auto_rename_ports(component) return component