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
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
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
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
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