Ejemplo n.º 1
0
def straight(
    length: float = 10.0,
    npoints: int = 2,
    with_cladding_box: bool = True,
    cross_section: CrossSectionFactory = strip,
    **kwargs
) -> Component:
    """Returns a Straight waveguide.

    Args:
        length: straight length
        npoints: number of points
        with_cladding_box: box in layers_cladding to avoid DRC sharp edges
        cross_section:
        **kwargs: cross_section settings
    """
    p = gf.path.straight(length=length, npoints=npoints)
    x = cross_section(**kwargs)

    c = gf.path.extrude(p, x)
    c.info.length = gf.snap.snap_to_grid(length)
    c.info.width = float(x.info["width"])
    if with_cladding_box and x.info["layers_cladding"]:
        layers_cladding = x.info["layers_cladding"]
        cladding_offset = x.info["cladding_offset"]
        points = get_padding_points(
            component=c,
            default=0,
            bottom=cladding_offset,
            top=cladding_offset,
        )
        for layer in layers_cladding or []:
            c.add_polygon(points, layer=layer)
    return c
Ejemplo n.º 2
0
def bend_circular(angle: int = 90,
                  npoints: int = 720,
                  with_cladding_box: bool = True,
                  cross_section: CrossSectionOrFactory = strip,
                  **kwargs) -> Component:
    """Returns a radial arc.

    Args:
        angle: angle of arc (degrees)
        npoints: number of points
        with_cladding_box: square in layers_cladding to remove DRC
        cross_section:
        kwargs: cross_section settings


    .. code::

                  o2
                  |
                 /
                /
               /
       o1_____/

    """
    x = cross_section(**kwargs) if callable(cross_section) else cross_section
    radius = x.info["radius"]

    p = arc(radius=radius, angle=angle, npoints=npoints)
    c = Component()
    path = extrude(p, x)
    ref = c << path
    c.add_ports(ref.ports)

    c.info.length = snap_to_grid(p.length())
    c.info.dy = float(abs(p.points[0][0] - p.points[-1][0]))
    c.info.radius = float(radius)

    if with_cladding_box and x.info["layers_cladding"]:
        layers_cladding = x.info["layers_cladding"]
        cladding_offset = x.info["cladding_offset"]
        top = cladding_offset if angle == 180 else 0
        points = get_padding_points(
            component=c,
            default=0,
            bottom=cladding_offset,
            right=cladding_offset,
            top=top,
        )
        for layer in layers_cladding or []:
            c.add_polygon(points, layer=layer)

    c.absorb(ref)
    return c
Ejemplo n.º 3
0
def bend_s(size: Float2 = (10.0, 2.0),
           nb_points: int = 99,
           with_cladding_box: bool = True,
           cross_section: CrossSectionFactory = strip,
           **kwargs) -> Component:
    """S bend with bezier curve

    stores min_bend_radius property in self.info['min_bend_radius']
    min_bend_radius depends on height and length

    Args:
        size: in x and y direction
        nb_points: number of points
        with_cladding_box: square bounding box to avoid DRC errors
        cross_section: function
        kwargs: cross_section settings

    """
    dx, dy = size
    x = cross_section(**kwargs)
    width = x.info["width"]
    layer = x.info["layer"]

    c = Component()

    bend = bezier(
        width=width,
        control_points=[(0, 0), (dx / 2, 0), (dx / 2, dy), (dx, dy)],
        npoints=nb_points,
        layer=layer,
    )

    bend_ref = c << bend
    c.add_ports(bend_ref.ports)
    c.copy_child_info(bend)
    c.info.start_angle = bend.info.start_angle
    c.info.end_angle = bend.info.end_angle
    c.info.length = bend.info.length
    c.info.min_bend_radius = bend.info.min_bend_radius

    if with_cladding_box and x.info["layers_cladding"]:
        layers_cladding = x.info["layers_cladding"]
        cladding_offset = x.info["cladding_offset"]
        points = get_padding_points(
            component=c,
            default=0,
            bottom=cladding_offset,
            top=cladding_offset,
        )
        for layer in layers_cladding or []:
            c.add_polygon(points, layer=layer)

    auto_rename_ports(c)
    return c
Ejemplo n.º 4
0
def bend_circular(angle: int = 90,
                  npoints: int = 720,
                  with_cladding_box: bool = True,
                  cross_section: CrossSectionFactory = strip,
                  **kwargs) -> Component:
    """Returns a radial arc.

    Args:
        angle: angle of arc (degrees)
        npoints: number of points
        with_cladding_box: square in layers_cladding to remove DRC
        cross_section:
        **kwargs: cross_section settings

    .. plot::
        :include-source:

        import gdsfactory as gf

        c = gf.components.bend_circular(radius=10, angle=90, npoints=720)
        c.plot()

    """
    x = cross_section(**kwargs)
    radius = x.info["radius"]

    p = arc(radius=radius, angle=angle, npoints=npoints)
    c = extrude(p, x)

    c.info.length = snap_to_grid(p.length())
    c.info.dy = float(abs(p.points[0][0] - p.points[-1][0]))
    c.info.radius_min = float(radius)

    if with_cladding_box and x.info["layers_cladding"]:
        layers_cladding = x.info["layers_cladding"]
        cladding_offset = x.info["cladding_offset"]
        top = cladding_offset if angle == 180 else 0
        points = get_padding_points(
            component=c,
            default=0,
            bottom=cladding_offset,
            right=cladding_offset,
            top=top,
        )
        for layer in layers_cladding or []:
            c.add_polygon(points, layer=layer)
    return c
Ejemplo n.º 5
0
def add_outline(
    component: Component,
    reference: Optional[ComponentReference] = None,
    layer: Tuple[int, int] = LAYER.DEVREC,
    **kwargs,
) -> None:
    """Adds devices outline bounding box in layer.

    Args:
        component: where to add the markers
        reference: to read outline from
        layer: to add padding
        default: default padding
        top: North padding
        bottom
        right
        left
    """
    c = reference or component
    if hasattr(component, "parent"):
        component = component.parent
    points = get_padding_points(component=c, default=0, **kwargs)
    component.add_polygon(points, layer=layer)
Ejemplo n.º 6
0
def taper_strip_to_ridge(
    length: float = 10.0,
    width1: float = 0.5,
    width2: float = 0.5,
    w_slab1: float = 0.15,
    w_slab2: float = 6.0,
    layer_wg: Layer = gf.LAYER.WG,
    layer_slab: Layer = gf.LAYER.SLAB90,
    with_slab_port: bool = False,
    layers_cladding: Optional[Tuple[Layer, ...]] = None,
    cladding_offset: float = 3.0,
) -> Component:
    r"""Linear taper from strip to rib

    Args:
        length:
        width1:
        width2:
        w_slab1
        w_slab2
        layer_wg:
        layer_slab:
        with_slab_port: adds a wide slab port
        layers_cladding
        cladding_offset:

    .. code::

                      __________________________
                     /           |
             _______/____________|______________
                   /             |
       width1     |w_slab1       | w_slab2  width2
             ______\_____________|______________
                    \            |
                     \__________________________

    """

    taper_wg = taper(length=length,
                     width1=width1,
                     width2=width2,
                     layer=layer_wg)
    taper_slab = taper(length=length,
                       width1=w_slab1,
                       width2=w_slab2,
                       layer=layer_slab)

    c = gf.Component()
    for _t in [taper_wg, taper_slab]:
        taper_ref = _t.ref()
        c.add(taper_ref)
        c.absorb(taper_ref)

    c.info["length"] = length
    c.add_port(name="o1", port=taper_wg.ports["o1"])
    if with_slab_port:
        c.add_port(name="o2", port=taper_slab.ports["o2"])
    else:
        c.add_port(name="o2", port=taper_wg.ports["o2"])

    if layers_cladding:
        points = get_padding_points(
            component=c,
            default=0,
            bottom=cladding_offset,
            top=cladding_offset,
        )
        for layer in layers_cladding:
            c.add_polygon(points, layer=layer)

    return c
Ejemplo n.º 7
0
def taper(length: float = 10.0,
          width1: float = 0.5,
          width2: Optional[float] = None,
          port: Optional[Port] = None,
          with_cladding_box: bool = True,
          cross_section: CrossSectionFactory = strip,
          **kwargs) -> Component:
    """Linear taper.

    Args:
        length:
        width1: width of the west port
        width2: width of the east port
        port: can taper from a port instead of defining width1
        with_cladding_box: to avoid DRC acute angle errors in cladding
        cross_section:
        kwargs: cross_section settings

    .. plot::
      :include-source:

      import gdsfactory as gf

      c = gf.components.taper(width1=0.5, width2=5, length=3)
      c.plot()

    """
    x = cross_section(**kwargs)

    layers_cladding = x.info["layers_cladding"]
    layer = x.info["layer"]

    if isinstance(port, gf.Port) and width1 is None:
        width1 = port.width
    if width2 is None:
        width2 = width1

    y1 = width1 / 2
    y2 = width2 / 2

    xpts = [0, length, length, 0]
    ypts = [y1, y2, -y2, -y1]

    c = gf.Component()
    c.add_polygon((xpts, ypts), layer=layer)
    c.add_port(
        name="o1",
        midpoint=[0, 0],
        width=width1,
        orientation=180,
        layer=layer,
        cross_section=x,
    )
    c.add_port(
        name="o2",
        midpoint=[length, 0],
        width=width2,
        orientation=0,
        layer=layer,
        cross_section=x,
    )

    if with_cladding_box and x.info["layers_cladding"]:
        layers_cladding = x.info["layers_cladding"]
        cladding_offset = x.info["cladding_offset"]
        points = get_padding_points(
            component=c,
            default=0,
            bottom=cladding_offset,
            top=cladding_offset,
        )
        for layer in layers_cladding or []:
            c.add_polygon(points, layer=layer)

    c.info["length"] = length
    c.info["width1"] = float(width1)
    c.info["width2"] = float(width2)
    return c
Ejemplo n.º 8
0
def fanout2x2(component: ComponentOrFactory,
              port_spacing: float = 20.0,
              bend_length: Optional[float] = None,
              npoints: int = 101,
              select_ports: Callable = select_ports_optical,
              cross_section: CrossSectionFactory = strip,
              with_cladding_box: bool = True,
              **kwargs) -> Component:
    """returns component with port_spacing.

    Args:
        component: to package
        port_spacing: for the returned component
        bend_length: length of the bend (defaults to port_spacing)
        npoints: for sbend
        select_ports: function to select  optical_ports ports
        cross_section:
        with_cladding_box: square bounding box to avoid DRC errors

    Keyword Args:
        cross_section settings

    """

    c = gf.Component()

    component = component() if callable(component) else component
    component.component = component
    ref = c << component
    ref.movey(-ref.y)

    if bend_length is None:
        bend_length = port_spacing
    dx = bend_length

    y = port_spacing / 2.0

    p_w0 = ref.ports["o1"].midpoint
    p_w1 = ref.ports["o2"].midpoint
    p_e1 = ref.ports["o3"].midpoint
    p_e0 = ref.ports["o4"].midpoint
    y0 = p_e1[1]

    dy = y - y0

    control_points = [(0, 0), (dx / 2, 0), (dx / 2, dy), (dx, dy)]

    x = cross_section(**kwargs)
    width = x.info["width"]
    layer = x.info["layer"]

    bend = bezier(
        control_points=control_points,
        npoints=npoints,
        start_angle=0,
        end_angle=0,
        width=width,
        layer=layer,
    )
    if with_cladding_box and x.info["layers_cladding"]:
        layers_cladding = x.info["layers_cladding"]
        cladding_offset = x.info["cladding_offset"]
        bend.unlock()
        points = get_padding_points(
            component=bend,
            default=0,
            bottom=cladding_offset,
            top=cladding_offset,
        )
        for layer in layers_cladding or []:
            bend.add_polygon(points, layer=layer)

    b_tr = bend.ref(port_id="o1", position=p_e1)
    b_br = bend.ref(port_id="o1", position=p_e0, v_mirror=True)
    b_tl = bend.ref(port_id="o1", position=p_w1, h_mirror=True)
    b_bl = bend.ref(port_id="o1", position=p_w0, rotation=180)

    c.add([b_tr, b_br, b_tl, b_bl])

    c.add_port("o1", port=b_bl.ports["o2"])
    c.add_port("o2", port=b_tl.ports["o2"])
    c.add_port("o3", port=b_tr.ports["o2"])
    c.add_port("o4", port=b_br.ports["o2"])

    c.min_bend_radius = bend.info["min_bend_radius"]

    optical_ports = select_ports(ref.ports)
    for port_name in ref.ports.keys():
        if port_name not in optical_ports:
            c.add_port(port_name, port=ref.ports[port_name])
    c.copy_child_info(component)
    return c
Ejemplo n.º 9
0
def taper_strip_to_ridge(
    length: float = 10.0,
    width1: float = 0.5,
    width2: float = 0.5,
    w_slab1: float = 0.15,
    w_slab2: float = 6.0,
    layer_wg: Layer = gf.LAYER.WG,
    layer_slab: Layer = gf.LAYER.SLAB90,
    layers_cladding: Optional[Tuple[Layer, ...]] = None,
    cladding_offset: float = 3.0,
    cross_section: CrossSectionFactory = strip,
) -> Component:
    r"""Linear taper from strip to rib

    Deprecated, use gf.c.taper_cross_section instead

    Args:
        length:
        width1:
        width2:
        w_slab1
        w_slab2
        layer_wg:
        layer_slab:
        layers_cladding
        cladding_offset:
        cross_section: for input waveguide

    .. code::

                      __________________________
                     /           |
             _______/____________|______________
                   /             |
       width1     |w_slab1       | w_slab2  width2
             ______\_____________|______________
                    \            |
                     \__________________________

    """
    cross_section = gf.partial(cross_section, width=width1)

    taper_wg = taper(
        length=length,
        width1=width1,
        width2=width2,
        layer=layer_wg,
        cross_section=cross_section,
    )
    taper_slab = taper(
        length=length,
        width1=w_slab1,
        width2=w_slab2,
        layer=layer_slab,
    )

    c = gf.Component()
    for _t in [taper_wg, taper_slab]:
        taper_ref = _t.ref()
        c.add(taper_ref)
        c.absorb(taper_ref)

    c.info["length"] = float(length)
    c.add_port(name="o1", port=taper_wg.ports["o1"])
    c.add_port(name="o2", port=taper_slab.ports["o2"])

    if layers_cladding:
        points = get_padding_points(
            component=c,
            default=0,
            bottom=cladding_offset,
            top=cladding_offset,
        )
        for layer in layers_cladding:
            c.add_polygon(points, layer=layer)

    return c
Ejemplo n.º 10
0
def bend_euler(angle: int = 90,
               p: float = 0.5,
               with_arc_floorplan: bool = True,
               npoints: int = 720,
               direction: str = "ccw",
               with_cladding_box: bool = True,
               cross_section: CrossSectionFactory = strip,
               **kwargs) -> Component:
    """Returns an euler bend that adiabatically transitions from straight to curved.
    By default, `radius` corresponds to the minimum radius of curvature of the bend.
    However, if `with_arc_floorplan` is True, `radius` corresponds to the effective
    radius of curvature (making the curve a drop-in replacement for an arc). If
    p < 1.0, will create a "partial euler" curve as described in Vogelbacher et.
    al. https://dx.doi.org/10.1364/oe.27.031394

    default p = 0.5 based on this paper
    https://www.osapublishing.org/oe/fulltext.cfm?uri=oe-25-8-9150&id=362937

    Args:
        angle: total angle of the curve
        p: Proportion of the curve that is an Euler curve
        with_arc_floorplan: If False: `radius` is the minimum radius of curvature
          If True: The curve scales such that the endpoints match a bend_circular
          with parameters `radius` and `angle`
        npoints: Number of points used per 360 degrees
        direction: cw (clock-wise) or ccw (counter clock-wise)
        with_cladding_box: to avoid DRC acute angle errors in cladding
        cross_section:


    """
    x = cross_section(**kwargs)
    radius = x.info["radius"]

    p = euler(radius=radius,
              angle=angle,
              p=p,
              use_eff=with_arc_floorplan,
              npoints=npoints)
    c = extrude(p, x)
    c.info.length = snap_to_grid(p.length())
    c.info.dy = abs(float(p.points[0][0] - p.points[-1][0]))
    c.info.radius_min = float(p.info["Rmin"])
    c.info.radius = radius

    if with_cladding_box and x.info["layers_cladding"]:
        layers_cladding = x.info["layers_cladding"]
        cladding_offset = x.info["cladding_offset"]
        top = cladding_offset if angle == 180 else 0
        points = get_padding_points(
            component=c,
            default=0,
            bottom=cladding_offset,
            right=cladding_offset,
            top=top,
        )
        for layer in layers_cladding or []:
            c.add_polygon(points, layer=layer)

    if direction == "cw":
        c.mirror(p1=[0, 0], p2=[1, 0])
    return c