Esempio n. 1
0
def ring_double(
    wg_width: float = 0.5,
    gap: float = 0.2,
    length_x: float = 3.0,
    bend_radius: float = 5.0,
    length_y: float = 2.0,
    coupler: Callable = coupler_ring,
    waveguide: Callable = waveguide_function,
    pins: bool = False,
) -> Component:
    """ double bus ring made of two couplers (ct: top, cb: bottom)
    connected with two vertical waveguides (wyl: left, wyr: right)

    .. code::

         --==ct==--
          |      |
          wl     wr length_y
          |      |
         --==cb==-- gap

          length_x

    .. plot::
      :include-source:

      import pp

      c = pp.c.ring_double(wg_width=0.5, gap=0.2, length_x=4, length_y=0.1, bend_radius=5)
      pp.plotgds(c)
    """
    assert_on_2nm_grid(gap)

    coupler = call_if_func(coupler,
                           gap=gap,
                           wg_width=wg_width,
                           bend_radius=bend_radius,
                           length_x=length_x)
    waveguide = call_if_func(waveguide, width=wg_width, length=length_y)

    c = Component()
    cb = c << coupler
    ct = c << coupler
    wl = c << waveguide
    wr = c << waveguide

    wl.connect(port="E0", destination=cb.ports["N0"])
    ct.connect(port="N1", destination=wl.ports["W0"])
    wr.connect(port="W0", destination=ct.ports["N0"])
    cb.connect(port="N1", destination=wr.ports["E0"])
    c.add_port("E0", port=cb.ports["E0"])
    c.add_port("W0", port=cb.ports["W0"])
    c.add_port("E1", port=ct.ports["W0"])
    c.add_port("W1", port=ct.ports["E0"])
    if pins:
        pp.add_pins_to_references(c)
    return c
Esempio n. 2
0
def import_phidl_component(component: Device, **kwargs) -> Component:
    """ returns a gdsfactory Component from a phidl Device or function
    """
    D = call_if_func(component, **kwargs)
    D_copy = Component(name=D._internal_name)
    D_copy.info = copy.deepcopy(D.info)
    for ref in D.references:
        new_ref = ComponentReference(
            device=ref.parent,
            origin=ref.origin,
            rotation=ref.rotation,
            magnification=ref.magnification,
            x_reflection=ref.x_reflection,
        )
        new_ref.owner = D_copy
        D_copy.add(new_ref)
        for alias_name, alias_ref in D.aliases.items():
            if alias_ref == ref:
                D_copy.aliases[alias_name] = new_ref

    for p in D.ports.values():
        D_copy.add_port(
            port=Port(
                name=p.name,
                midpoint=p.midpoint,
                width=p.width,
                orientation=p.orientation,
                parent=p.parent,
            )
        )
    for poly in D.polygons:
        D_copy.add_polygon(poly)
    for label in D.labels:
        D_copy.add_label(
            text=label.text,
            position=label.position,
            layer=(label.layer, label.texttype),
        )
    return D_copy
Esempio n. 3
0
def ring_single(
    wg_width: float = 0.5,
    gap: float = 0.2,
    length_x: float = 4.0,
    bend_radius: float = 5.0,
    length_y: float = 2.0,
    coupler: Callable = coupler_ring,
    waveguide: Callable = waveguide,
    bend: Callable = bend_circular,
) -> Component:
    """ single bus ring made of two couplers (ct: top, cb: bottom)
    connected with two vertical waveguides (wyl: left, wyr: right)

    .. code::

          bl-wt-br
          |      |
          wl     wr length_y
          |      |
         --==cb==-- gap

          length_x

    .. plot::
      :include-source:

      import pp

      c = pp.c.ring_single(wg_width=0.5, gap=0.2, length_x=4, length_y=0.1, bend_radius=5)
      pp.plotgds(c)

    """
    bend_radius = float(bend_radius)
    assert_on_2nm_grid(gap)

    coupler = call_if_func(coupler,
                           gap=gap,
                           wg_width=wg_width,
                           bend_radius=bend_radius,
                           length_x=length_x)
    waveguide_side = call_if_func(waveguide, width=wg_width, length=length_y)
    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
    wr = 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"])
    wr.connect(port="W0", destination=br.ports["W0"])
    wr.connect(port="E0", destination=cb.ports["N1"])  # just for netlist

    c.add_port("E0", port=cb.ports["E0"])
    c.add_port("W0", port=cb.ports["W0"])
    return c
def add_fiber_single(
    component: Component,
    grating_coupler: Callable = grating_coupler_te,
    layer_label: Tuple[int, int] = LAYER.LABEL,
    optical_io_spacing: int = 50,
    bend_factory: Callable = bend_circular,
    straight_factory: Callable = waveguide,
    taper_factory: Callable = taper,
    taper_length: float = 10.0,
    route_filter: Callable = connect_strip_way_points,
    min_input2output_spacing: int = 127,
    optical_routing_type: int = 2,
    with_align_ports: bool = True,
    component_name: Optional[str] = None,
    gc_port_name: str = "W0",
    **kwargs,
) -> Component:
    r"""returns component with grating ports and labels on each port
    can add align_ports reference structure

    Args:
        component: to connect
        grating_coupler: grating coupler instance, function or list of functions
        layer_label: LAYER.LABEL
        optical_io_spacing: SPACING_GC
        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_method: connect_strip
        gc_port_name: W0
        optical_routing_type: None: autoselection, 0: no extension
        gc_rotation: -90
        component_name: name of component
        taper_factory: taper

    .. code::

              fiber
             ______
            /| | |
           / | | |
        W0|  | | |
           \ | | |
          | \|_|_|_

          |
         xmin = 0

    .. plot::
      :include-source:

       import pp
       from pp.routing import add_fiber_array

       c = pp.c.crossing()
       cc = add_fiber_array(c)
       pp.plotgds(cc)

    """
    component = component() if callable(component) else component
    gc = grating_coupler = (grating_coupler()
                            if callable(grating_coupler) else grating_coupler)
    gc_port_to_edge = abs(gc.xmax - gc.ports[gc_port_name].midpoint[0])
    port_width_gc = grating_coupler.ports[gc_port_name].width
    optical_ports = component.get_ports_list(port_type="optical")
    port_width_component = optical_ports[0].width

    if port_width_component != port_width_gc:
        component = add_tapers(
            component,
            taper_factory(length=taper_length,
                          width1=port_width_gc,
                          width2=port_width_component),
        )

    component_name = component_name or component.name
    name = f"{component_name}_{grating_coupler.name}"

    elements, grating_couplers = route_fiber_single(
        component,
        component_name=component_name,
        optical_io_spacing=optical_io_spacing,
        bend_factory=bend_factory,
        straight_factory=straight_factory,
        route_filter=route_filter,
        grating_coupler=grating_coupler,
        layer_label=layer_label,
        optical_routing_type=optical_routing_type,
        min_input2output_spacing=min_input2output_spacing,
        gc_port_name=gc_port_name,
        **kwargs,
    )

    c = Component(name=name)
    cr = c << component
    cr.rotate(90)

    for e in elements:
        c.add(e)
    for gc in grating_couplers:
        c.add(gc)

    for pname, p in component.ports.items():
        if p.port_type != "optical":
            c.add_port(pname, port=p)

    if isinstance(grating_coupler, list):
        grating_couplers = [call_if_func(g) for g in grating_coupler]
        grating_coupler = grating_couplers[0]
    else:
        grating_coupler = call_if_func(grating_coupler)
        grating_couplers = [grating_coupler]

    if with_align_ports:
        length = c.ysize - 2 * gc_port_to_edge
        wg = c << straight_factory(length=length)
        wg.rotate(90)
        wg.xmax = (c.xmin - optical_io_spacing
                   if abs(c.xmin) > abs(optical_io_spacing) else c.xmin -
                   optical_io_spacing)
        wg.ymin = c.ymin + gc_port_to_edge

        gci = c << grating_coupler
        gco = c << grating_coupler
        gci.connect(gc_port_name, wg.ports["W0"])
        gco.connect(gc_port_name, wg.ports["E0"])

        gds_layer_label, gds_datatype_label = pd._parse_layer(layer_label)

        port = wg.ports["E0"]
        text = get_optical_text(port,
                                grating_coupler,
                                0,
                                component_name=f"loopback_{component.name}")

        label = pd.Label(
            text=text,
            position=port.midpoint,
            anchor="o",
            layer=gds_layer_label,
            texttype=gds_datatype_label,
        )
        c.add(label)

        port = wg.ports["W0"]
        text = get_optical_text(port,
                                grating_coupler,
                                1,
                                component_name=f"loopback_{component.name}")
        label = pd.Label(
            text=text,
            position=port.midpoint,
            anchor="o",
            layer=gds_layer_label,
            texttype=gds_datatype_label,
        )
        c.add(label)

    return c
Esempio n. 5
0
def ring_single_dut(
    component,
    wg_width=0.5,
    gap=0.2,
    length_x=4,
    bend_radius=5,
    length_y=0,
    coupler=coupler_ring,
    waveguide=waveguide,
    bend=bend_circular,
    with_dut=True,
):
    """ single bus ring made of two couplers (ct: top, cb: bottom)
    connected with two vertical waveguides (wyl: left, wyr: right)
    DUT (Device Under Test) in the middle to extract loss from quality factor


    Args:
        with_dut: if False changes dut for just a waveguide

    .. code::

          bl-wt-br
          |      | length_y
          wl     dut
          |      |
         --==cb==-- gap

          length_x
    """
    dut = pp.call_if_func(component)
    dut = rename_ports_by_orientation(dut)

    assert_on_2nm_grid(gap)

    coupler = call_if_func(coupler,
                           gap=gap,
                           wg_width=wg_width,
                           bend_radius=bend_radius,
                           length_x=length_x)
    waveguide_side = call_if_func(waveguide,
                                  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
Esempio n. 6
0
def ring_single(
    wg_width: float = 0.5,
    gap: float = 0.2,
    bend_radius: float = 10.0,
    length_x: float = 4.0,
    length_y: float = 0.001,
    coupler: Callable = coupler_ring,
    waveguide: Callable = waveguide_function,
    bend: Callable = bend_circular,
    pins: bool = False,
) -> Component:
    """Single bus ring made of a ring coupler (cb: bottom)
    connected with two vertical waveguides (wl: left, wr: right)
    two bends (bl, br) and horizontal waveguide (wg: top)

    Args:
        wg_width: waveguide width
        gap: gap between for coupler
        bend_radius: for the bend and coupler
        length_x: ring coupler length
        length_y: vertical waveguide length
        coupler: ring coupler function
        waveguide: waveguide function
        bend: bend function
        pins: add pins


    .. code::

          bl-wt-br
          |      |
          wl     wr length_y
          |      |
         --==cb==-- gap

          length_x

    .. plot::
      :include-source:

      import pp

      c = pp.c.ring_single(wg_width=0.5, gap=0.2, length_x=4, length_y=0.1, bend_radius=5)
      pp.plotgds(c)

    """
    bend_radius = float(bend_radius)
    assert_on_2nm_grid(gap)

    coupler = call_if_func(coupler,
                           gap=gap,
                           wg_width=wg_width,
                           bend_radius=bend_radius,
                           length_x=length_x)
    waveguide_side = call_if_func(waveguide, width=wg_width, length=length_y)
    waveguide_top = call_if_func(waveguide, width=wg_width, length=length_x)
    bend_ref = bend(width=wg_width,
                    radius=bend_radius) if callable(bend) else bend

    c = Component()
    cb = c << coupler
    wl = c << waveguide_side
    wr = c << waveguide_side
    bl = c << bend_ref
    br = c << bend_ref
    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"])
    wr.connect(port="W0", destination=br.ports["W0"])
    wr.connect(port="E0", destination=cb.ports["N1"])  # just for netlist

    c.add_port("E0", port=cb.ports["E0"])
    c.add_port("W0", port=cb.ports["W0"])
    if pins:
        pp.add_pins_to_references(c)
    return c