예제 #1
0
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.port.rename_ports_by_orientation(c)
    return c
예제 #2
0
def add_io_optical(c,
                   grating_coupler=grating_coupler_te,
                   gc_port_name="W0",
                   component_name=None,
                   **kwargs):
    """ returns component with optical IO (tapers, south routes and grating_couplers)

    Args:
        component: to connect
        optical_io_spacing: SPACING_GC
        grating_coupler: grating coupler instance, function or list of functions
        bend_factory: bend_circular
        straight_factory: waveguide
        fanout_length: None,  # if None, automatic calculation of fanout length
        max_y0_optical: None
        with_align_ports: True, adds loopback structures
        waveguide_separation=4.0
        bend_radius: BEND_RADIUS
        list_port_labels: None, adds TM labels to port indices in this list
        connected_port_list_ids: None # only for type 0 optical routing
        nb_optical_ports_lines: 1
        force_manhattan: False
        excluded_ports:
        grating_indices: None
        routing_waveguide: None
        routing_method: connect_strip
        gc_port_name: W0
        optical_routing_type: None: autoselection, 0: no extension
        gc_rotation=-90
        layer_label=LAYER.LABEL
        input_port_indexes=[0]
        component_name: for the label

    """
    if not c.ports:
        return c
    cc = Component(
        settings=c.get_settings(),
        test_protocol=c.test_protocol,
        data_analysis_protocol=c.data_analysis_protocol,
    )
    cc.function_name = "add_io_optical"

    if isinstance(grating_coupler, list):
        gc = grating_coupler[0]
    else:
        gc = grating_coupler
    gc = pp.call_if_func(gc)

    if "polarization" in gc.settings:
        gc.polarization = gc.settings["polarization"]

    cc.name = "{}_{}".format(c.name, gc.polarization)

    port_width_gc = list(gc.ports.values())[0].width
    port_width_component = list(c.ports.values())[0].width

    if port_width_component != port_width_gc:
        c = add_tapers(
            c,
            taper(length=10, width1=port_width_gc,
                  width2=port_width_component))

    elements, io_gratings_lines, _ = _get_optical_io_elements(
        component=c,
        grating_coupler=grating_coupler,
        gc_port_name=gc_port_name,
        component_name=component_name,
        **kwargs)
    if len(elements) == 0:
        return c

    cc.add(elements)
    for io_gratings in io_gratings_lines:
        cc.add(io_gratings)
    cc.add(c.ref())
    cc.move(origin=io_gratings_lines[0][0].ports[gc_port_name],
            destination=(0, 0))

    return cc
예제 #3
0
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:
    r"""Grating coupler uniform (grating with rectangular shape not elliptical).
    Therefore it needs a longer taper.
    Grating teeth are straight instead of elliptical.

    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)

    .. code::

                 \  \  \  \
                  \  \  \  \
                _|-|_|-|_|-|___
               |_______________  W0

    """
    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)
    pp.assert_grating_coupler_properties(G)
    return G
예제 #4
0
                                  width=wg_width,
                                  length=length_y + dut.xsize)
    waveguide_top = call_if_func(waveguide, width=wg_width, length=length_x)
    bend = call_if_func(bend, width=wg_width, radius=bend_radius)

    c = Component()
    cb = c << coupler
    wl = c << waveguide_side
    if with_dut:
        d = c << dut
    else:
        d = c << waveguide_side
    bl = c << bend
    br = c << bend
    wt = c << waveguide_top

    wl.connect(port="E0", destination=cb.ports["N0"])
    bl.connect(port="N0", destination=wl.ports["W0"])

    wt.connect(port="W0", destination=bl.ports["W0"])
    br.connect(port="N0", destination=wt.ports["E0"])
    d.connect(port="W0", destination=br.ports["W0"])
    c.add_port("E0", port=cb.ports["E0"])
    c.add_port("W0", port=cb.ports["W0"])
    return c


if __name__ == "__main__":
    c = ring_single_dut(component=taper(width2=3))
    pp.show(c)
예제 #5
0
                                  width=wg_width,
                                  length=length_y + dut.xsize)
    waveguide_top = call_if_func(waveguide, width=wg_width, length=length_x)
    bend = call_if_func(bend, width=wg_width, radius=bend_radius)

    c = Component()
    cb = c << coupler
    wl = c << waveguide_side
    if with_dut:
        d = c << dut
    else:
        d = c << waveguide_side
    bl = c << bend
    br = c << bend
    wt = c << waveguide_top

    wl.connect(port="E0", destination=cb.ports["N0"])
    bl.connect(port="N0", destination=wl.ports["W0"])

    wt.connect(port="W0", destination=bl.ports["W0"])
    br.connect(port="N0", destination=wt.ports["E0"])
    d.connect(port="W0", destination=br.ports["W0"])
    c.add_port("E0", port=cb.ports["E0"])
    c.add_port("W0", port=cb.ports["W0"])
    return c


if __name__ == "__main__":
    c = ring_single_dut(component=taper(width2=3), pins=True)
    pp.show(c)