示例#1
0
def from_phidl(component: Device, **kwargs) -> Component:
    """Returns gf.Component from a phidl Device or function"""
    device = call_if_func(component, **kwargs)
    component = Component(name=device.name)

    for ref in device.references:
        new_ref = ComponentReference(
            component=ref.parent,
            origin=ref.origin,
            rotation=ref.rotation,
            magnification=ref.magnification,
            x_reflection=ref.x_reflection,
        )
        new_ref.owner = component
        component.add(new_ref)
        for alias_name, alias_ref in device.aliases.items():
            if alias_ref == ref:
                component.aliases[alias_name] = new_ref

    for p in device.ports.values():
        component.add_port(
            port=Port(
                name=p.name,
                midpoint=p.midpoint,
                width=p.width,
                orientation=p.orientation,
                parent=p.parent,
            )
        )
    for poly in device.polygons:
        component.add_polygon(poly)
    for label in device.labels:
        component.add_label(
            text=label.text,
            position=label.position,
            layer=(label.layer, label.texttype),
        )
    return component
示例#2
0
def ring_single_dut(component=taper2,
                    wg_width=0.5,
                    gap=0.2,
                    length_x=4,
                    radius=5,
                    length_y=0,
                    coupler=coupler_ring,
                    straight=straight_function,
                    bend=bend_euler,
                    with_component=True,
                    **kwargs):
    """Single bus ring made of two couplers (ct: top, cb: bottom)
    connected with two vertical straights (wyl: left, wyr: right)
    (Device Under Test) in the middle to extract loss from quality factor


    Args:
        with_component: if False changes component for just a straight

    .. code::

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

          length_x
    """
    component = call_if_func(component)
    assert_on_2nm_grid(gap)

    coupler = call_if_func(coupler,
                           gap=gap,
                           radius=radius,
                           length_x=length_x,
                           **kwargs)
    straight_side = call_if_func(straight,
                                 width=wg_width,
                                 length=length_y + component.xsize,
                                 **kwargs)
    straight_top = call_if_func(straight,
                                width=wg_width,
                                length=length_x,
                                **kwargs)
    bend = call_if_func(bend, width=wg_width, radius=radius, **kwargs)

    c = Component()
    c.component = component
    cb = c << coupler
    wl = c << straight_side
    if with_component:
        d = c << component
    else:
        d = c << straight_side
    bl = c << bend
    br = c << bend
    wt = c << straight_top

    wl.connect(port="o2", destination=cb.ports["o2"])
    bl.connect(port="o2", destination=wl.ports["o1"])

    wt.connect(port="o1", destination=bl.ports["o1"])
    br.connect(port="o2", destination=wt.ports["o2"])
    d.connect(port="o1", destination=br.ports["o1"])

    c.add_port("o2", port=cb.ports["o4"])
    c.add_port("o1", port=cb.ports["o1"])
    c.copy_child_info(component)
    return c
def ring_single_sample(gap: float = 0.2,
                       radius: float = 10.0,
                       length_x: float = 4.0,
                       length_y: float = 0.010,
                       coupler_ring: ComponentFactory = coupler_ring_function,
                       straight: ComponentFactory = straight_function,
                       bend: Optional[ComponentFactory] = None,
                       cross_section: CrossSectionFactory = strip,
                       **kwargs) -> Component:
    """Single bus ring made of a ring coupler (cb: bottom)
    connected with two vertical straights (wl: left, wr: right)
    two bends (bl, br) and horizontal straight (wg: top)

    Args:
        gap: gap between for coupler
        radius: for the bend and coupler
        length_x: ring coupler length
        length_y: vertical straight length
        coupler_ring: ring coupler function
        straight: straight function
        bend: 90 degrees bend function
        cross_section:
        kwargs: cross_section settings


    .. code::

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

          length_x

    """
    assert_on_2nm_grid(gap)

    coupler_ring_component = (coupler_ring(bend=bend,
                                           gap=gap,
                                           radius=radius,
                                           length_x=length_x,
                                           cross_section=cross_section,
                                           **kwargs)
                              if callable(coupler_ring) else coupler_ring)
    straight_side = call_if_func(straight,
                                 length=length_y,
                                 cross_section=cross_section,
                                 **kwargs)
    straight_top = call_if_func(straight,
                                length=length_x,
                                cross_section=cross_section,
                                **kwargs)

    bend = bend or bend_euler
    bend_ref = (bend(radius=radius, cross_section=cross_section, **kwargs)
                if callable(bend) else bend)

    c = Component()
    cb = c << coupler_ring_component
    wl = c << straight_side
    wr = c << straight_side
    bl = c << bend_ref
    br = c << bend_ref
    wt = c << straight_top
    # wt.mirror(p1=(0, 0), p2=(1, 0))

    wl.connect(port="o2", destination=cb.ports["o2"])
    bl.connect(port="o2", destination=wl.ports["o1"])

    wt.connect(port="o2", destination=bl.ports["o1"])
    br.connect(port="o2", destination=wt.ports["o1"])
    wr.connect(port="o1", destination=br.ports["o1"])

    c.add_port("o2", port=cb.ports["o2"])
    c.add_port("o1", port=cb.ports["o1"])
    return c
示例#4
0
def ring_double_heater(
        gap: float = 0.2,
        radius: float = 10.0,
        length_x: float = 0.01,
        length_y: float = 0.01,
        coupler_ring: ComponentFactory = coupler_ring_function,
        straight: ComponentFactory = straight_function,
        bend: Optional[ComponentFactory] = None,
        cross_section_heater: gf.types.CrossSectionFactory = gf.cross_section.
    strip_heater_metal,
        cross_section: CrossSectionFactory = strip,
        contact: gf.types.ComponentFactory = contact_heater_m3_mini,
        port_orientation: int = 90,
        contact_offset: Float2 = (0, 0),
        **kwargs) -> Component:
    """Double bus ring made of two couplers (ct: top, cb: bottom)
    connected with two vertical straights (sl: left, sr: right)
    includes heater on top

    Args:
        gap: gap between for coupler
        radius: for the bend and coupler
        length_x: ring coupler length
        length_y: vertical straight length
        coupler_ring: ring coupler function
        straight: straight function
        bend: bend function
        cross_section_heater:
        cross_section:
        contact:
        port_orientation: for electrical ports to promote from contact
        contact_offset: for each contact
        kwargs: cross_section settings

    .. code::

         --==ct==--
          |      |
          sl     sr length_y
          |      |
         --==cb==-- gap

          length_x

    """
    assert_on_2nm_grid(gap)

    coupler_component = (coupler_ring(gap=gap,
                                      radius=radius,
                                      length_x=length_x,
                                      bend=bend,
                                      cross_section=cross_section,
                                      bend_cross_section=cross_section_heater,
                                      **kwargs)
                         if callable(coupler_ring) else coupler_ring)
    straight_component = call_if_func(straight,
                                      length=length_y,
                                      cross_section=cross_section_heater,
                                      **kwargs)

    c = Component()
    cb = c.add_ref(coupler_component)
    ct = c.add_ref(coupler_component)
    sl = c.add_ref(straight_component)
    sr = c.add_ref(straight_component)

    sl.connect(port="o1", destination=cb.ports["o2"])
    ct.connect(port="o3", destination=sl.ports["o2"])
    sr.connect(port="o2", destination=ct.ports["o2"])
    c.add_port("o1", port=cb.ports["o1"])
    c.add_port("o2", port=cb.ports["o4"])
    c.add_port("o3", port=ct.ports["o4"])
    c.add_port("o4", port=ct.ports["o1"])

    c1 = c << contact()
    c2 = c << contact()
    c1.xmax = -length_x / 2 + cb.x - contact_offset[0]
    c2.xmin = +length_x / 2 + cb.x + contact_offset[0]
    c1.movey(contact_offset[1])
    c2.movey(contact_offset[1])
    c.add_ports(c1.get_ports_list(orientation=port_orientation), prefix="e1")
    c.add_ports(c2.get_ports_list(orientation=port_orientation), prefix="e2")
    c.auto_rename_ports()
    return c
示例#5
0
def add_fiber_single(
    component: ComponentOrFactory,
    grating_coupler: ComponentFactory = grating_coupler_te,
    layer_label: Tuple[int, int] = TECH.layer_label,
    fiber_spacing: float = TECH.fiber_spacing,
    bend: ComponentFactory = bend_circular,
    straight: ComponentFactory = straight,
    route_filter: Callable = get_route_from_waypoints,
    min_input_to_output_spacing: float = 200.0,
    optical_routing_type: int = 2,
    with_loopback: bool = True,
    component_name: Optional[str] = None,
    gc_port_name: str = "o1",
    get_input_label_text_loopback_function:
    Callable = get_input_label_text_loopback,
    get_input_label_text_function: Callable = get_input_label_text,
    select_ports: Callable = select_ports_optical,
    cross_section: CrossSectionFactory = strip,
    **kwargs,
) -> Component:
    r"""Returns component with grating ports and labels on each port.

    Can add loopback reference structure next to it.

    Args:
        component: to connect
        grating_coupler: grating coupler instance, function or list of functions
        layer_label: for test and measurement label
        fiber_spacing: between outputs
        bend: bend_circular
        straight: straight
        route_filter:
        max_y0_optical: None
        with_loopback: True, adds loopback structures
        straight_separation: 4.0
        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: get_route
        gc_port_name: W0
        get_input_labels_function: function to get input labels for grating couplers
        optical_routing_type: None: autoselection, 0: no extension
        gc_rotation: -90
        component_name: name of component
        cross_section:
        **kwargs: cross_section settings

    .. code::

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

          |
         xmin = 0

    .. plot::
        :include-source:

        import gdsfactory as gf

        c = gf.components.crossing()
        cc = gf.routing.add_fiber_single(
            component=c,
            optical_routing_type=0,
            grating_coupler=gf.components.grating_coupler_elliptical_te,
        )
        cc.plot()

    """
    component = component() if callable(component) else component
    optical_ports = select_ports(component.ports)
    optical_ports = list(optical_ports.values())
    optical_port_names = [p.name for p in optical_ports]

    if not optical_ports:
        raise ValueError(f"No ports for {component.name}")

    component = component() if callable(component) else component
    component_name = component_name or component.get_parent_name()

    gc = grating_coupler = (grating_coupler()
                            if callable(grating_coupler) else grating_coupler)
    if gc_port_name not in gc.ports:
        raise ValueError(f"{gc_port_name} not in {list(gc.ports.keys())}")

    gc_port_to_edge = abs(gc.xmax - gc.ports[gc_port_name].midpoint[0])

    c = Component()

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

    for port in cr.ports.values():
        if port.name not in optical_port_names:
            c.add_port(name=port.name, port=port)

    if (len(optical_ports) == 2
            and abs(optical_ports[0].x - optical_ports[1].x) >
            min_input_to_output_spacing):

        grating_coupler = call_if_func(grating_coupler)
        grating_couplers = []
        for port in cr.ports.values():
            if port.name in optical_port_names:
                gc_ref = grating_coupler.ref()
                gc_ref.connect(gc_port_name, port)
                grating_couplers.append(gc_ref)

        elements = get_input_labels(
            io_gratings=grating_couplers,
            ordered_ports=list(cr.ports.values()),
            component_name=component_name,
            layer_label=layer_label,
            gc_port_name=gc_port_name,
            get_input_label_text_function=get_input_label_text_function,
        )

    else:
        elements, grating_couplers = route_fiber_single(
            component,
            fiber_spacing=fiber_spacing,
            bend=bend,
            straight=straight,
            route_filter=route_filter,
            grating_coupler=grating_coupler,
            layer_label=layer_label,
            optical_routing_type=optical_routing_type,
            min_input_to_output_spacing=min_input_to_output_spacing,
            gc_port_name=gc_port_name,
            component_name=component_name,
            cross_section=cross_section,
            select_ports=select_ports,
            **kwargs,
        )

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

    for i, io_row in enumerate(grating_couplers):
        if isinstance(io_row, list):
            for j, io in enumerate(io_row):
                ports = io.get_ports_list(prefix="vertical")
                if ports:
                    port = ports[0]
                    c.add_port(f"{port.name}_{i}{j}", port=port)
        else:
            ports = io_row.get_ports_list(prefix="vertical")
            if ports:
                port = ports[0]
                c.add_port(f"{port.name}_{i}", port=port)

    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_loopback:
        length = c.ysize - 2 * gc_port_to_edge
        wg = c << straight(
            length=length, cross_section=cross_section, **kwargs)
        wg.rotate(90)
        wg.xmax = (c.xmin - fiber_spacing if abs(c.xmin) > abs(fiber_spacing)
                   else c.xmin - fiber_spacing)
        wg.ymin = c.ymin + gc_port_to_edge

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

        port = wg.ports["o2"]
        text = get_input_label_text_loopback_function(
            port=port,
            gc=grating_coupler,
            gc_index=0,
            component_name=component_name)

        c.add_label(
            text=text,
            position=port.midpoint,
            anchor="o",
            layer=layer_label,
        )

        port = wg.ports["o1"]
        text = get_input_label_text_loopback_function(
            port=port,
            gc=grating_coupler,
            gc_index=1,
            component_name=component_name)
        c.add_label(
            text=text,
            position=port.midpoint,
            anchor="o",
            layer=layer_label,
        )

    c.copy_child_info(component)
    return c
示例#6
0
def ring_double(gap: float = 0.2,
                radius: float = 10.0,
                length_x: float = 0.01,
                length_y: float = 0.01,
                coupler_ring: ComponentFactory = coupler_ring_function,
                straight: ComponentFactory = straight_function,
                bend: Optional[ComponentFactory] = None,
                cross_section: CrossSectionFactory = strip,
                **kwargs) -> Component:
    """Double bus ring made of two couplers (ct: top, cb: bottom)
    connected with two vertical straights (sl: left, sr: right)

    Args:
        gap: gap between for coupler
        radius: for the bend and coupler
        length_x: ring coupler length
        length_y: vertical straight length
        coupler: ring coupler function
        straight: straight function
        bend: bend function
        **kwargs: cross_section settings

    .. code::

         --==ct==--
          |      |
          sl     sr length_y
          |      |
         --==cb==-- gap

          length_x

    """
    assert_on_2nm_grid(gap)

    coupler_component = (coupler_ring(gap=gap,
                                      radius=radius,
                                      length_x=length_x,
                                      bend=bend,
                                      cross_section=cross_section,
                                      **kwargs)
                         if callable(coupler_ring) else coupler_ring)
    straight_component = call_if_func(straight,
                                      length=length_y,
                                      cross_section=cross_section,
                                      **kwargs)

    c = Component()
    cb = c.add_ref(coupler_component)
    ct = c.add_ref(coupler_component)
    sl = c.add_ref(straight_component)
    sr = c.add_ref(straight_component)

    sl.connect(port="o1", destination=cb.ports["o2"])
    ct.connect(port="o3", destination=sl.ports["o2"])
    sr.connect(port="o2", destination=ct.ports["o2"])
    c.add_port("o1", port=cb.ports["o1"])
    c.add_port("o2", port=cb.ports["o4"])
    c.add_port("o3", port=ct.ports["o4"])
    c.add_port("o4", port=ct.ports["o1"])
    return c