def cutback_phase(straight_length=100.0, bend_radius=10.0, n=2): # Define sub components bend180 = bend_circular(radius=bend_radius, start_angle=-90, theta=180) pm_wg = phase_modulator_waveguide(length=straight_length) wg_short = waveguide(length=1.0) wg_short2 = waveguide(length=2.0) wg_heater = waveguide_heater(length=10.0) taper = _taper() # Define a map between symbols and (component, input port, output port) string_to_device_in_out_ports = { "I": (taper, "1", "wg_2"), "O": (taper, "wg_2", "1"), "S": (wg_short, "W0", "E0"), "P": (pm_wg, "W0", "E0"), "A": (bend180, "W0", "W1"), "B": (bend180, "W1", "W0"), "H": (wg_heater, "W0", "E0"), "-": (wg_short2, "W0", "E0"), } # Generate a sequence # This is simply a chain of characters. Each of them represents a component # with a given input and and a given output repeated_sequence = "SIPOSASIPOSB" heater_seq = "-H-H-H-H-" sequence = repeated_sequence * n + "SIPO" + heater_seq component = component_sequence(sequence, string_to_device_in_out_ports) return component
def cutback_bend(bend90, straight_length=5.0, n_steps=6, n_stairs=5): """ Deprecated! use cutback_bend90 instead! this is a stair .. code:: _ _| _| _ this is a step """ wg = waveguide(length=straight_length, width=bend90.ports["W0"].width) # Define a map between symbols and (component, input port, output port) string_to_device_in_out_ports = { "A": (bend90, "W0", "N0"), "B": (bend90, "N0", "W0"), "S": (wg, "W0", "E0"), } # Generate the sequence of staircases s = "" for i in range(n_stairs): s += "ASBS" * n_steps s += "ASAS" if i % 2 == 0 else "BSBS" s = s[:-4] # Create the component from the sequence c = component_sequence(s, string_to_device_in_out_ports, start_orientation=90) c.update_settings(n_bends=n_steps * n_stairs * 2 + n_stairs * 2 - 2) return c
def test_add_keepout(): from pp.components.waveguide import waveguide c = waveguide() target_layers = [LAYER.WG] keepout_layers = [LAYER.NO_TILE_SI] # print(len(c.get_polygons())) assert len(c.get_polygons()) == 2 c = add_keepout(c, target_layers=target_layers, keepout_layers=keepout_layers) # print(len(c.get_polygons())) assert len(c.get_polygons()) == 3
def test_cutback_heater(): # Define subcomponents bend_radius = 10.0 bend180 = bend_circular(radius=bend_radius, start_angle=-90, theta=180) wg = waveguide(length=5.0) wg_heater = waveguide_heater(length=20.0) # Define a map between symbols and (component, input port, output port) string_to_device_in_out_ports = { "A": (bend180, "W0", "W1"), "B": (bend180, "W1", "W0"), "H": (wg_heater, "W0", "E0"), "-": (wg, "W0", "E0"), } # Generate a sequence # This is simply a chain of characters. Each of them represents a component # with a given input and and a given output sequence = "AB-H-H-H-H-BA" component = component_sequence(sequence, string_to_device_in_out_ports) assert component return component
def coupler90(bend_radius=10.0, width=0.5, gap=0.2): """ Waveguide coupled to a bend with gap Args: bend_radius: um width: waveguide width (um) gap: um .. plot:: :include-source: import pp c = pp.c.coupler90() pp.plotgds(c) """ y = width + gap _bend = bend_circular(radius=bend_radius, width=width).ref((0, y)) c = Component() _wg = c.add_ref(waveguide(length=bend_radius, width=width)) c.add(_bend) # This component is a leaf cell => using absorb c.absorb(_wg) c.absorb(_bend) port_width = 2 * width + gap c.add_port(port=_wg.ports["E0"], name="E0") c.add_port(port=_bend.ports["N0"], name="N0") c.add_port(name="W0", midpoint=[0, y / 2], width=port_width, orientation=180) c.y = y return c
def cdsem_uturn( width=0.5, radius=10.0, symbol_bot="S", symbol_top="U", wg_length=LINE_LENGTH, waveguide=pp.c.waveguide, layer=pp.layer("wgcore"), layer_cladding=pp.layer("wgclad"), cladding_offset=3, ): """ Args: width: of the line cladding_offset: radius: bend radius wg_length """ c = pp.Component() r = radius bend90 = bend_circular( width=width, radius=r, layer=layer, cladding_layer=layer_cladding ) if wg_length is None: wg_length = 2 * r wg = waveguide( width=width, length=wg_length, layer=layer, layer_cladding=layer_cladding, cladding_offset=cladding_offset, ) # bend90.ports() rename_ports_by_orientation(bend90) # Add the U-turn on waveguide layer b1 = c.add_ref(bend90) b2 = c.add_ref(bend90) b2.connect("N0", b1.ports["W0"]) wg1 = c.add_ref(wg) wg1.connect("W0", b1.ports["N0"]) wg2 = c.add_ref(wg) wg2.connect("W0", b2.ports["W0"]) # Add symbols sym1 = c.add_ref(CENTER_SHAPES_MAP[symbol_bot]()) sym1.rotate(-90) sym1.movey(r) sym2 = c.add_ref(CENTER_SHAPES_MAP[symbol_top]()) sym2.rotate(-90) sym2.movey(2 * r) c.absorb(sym1) c.absorb(sym2) c.rotate(angle=90) # print(c._bb_valid) # print(c.size_info) c.move(c.size_info.cc, (0, 0)) return c
def splitter_tree( coupler: Callable = mmi1x2, n_o_outputs: int = 4, bend_radius: float = 10.0, spacing: float = 50.0, termination_component=None, ): """tree of 1x2 splitters Args: coupler: 1x2 coupler factory n_o_outputs: bend_radius: for routing spacing: 2X spacing termination_component: factory or component for EAST termination .. code:: __| __| |__ _| |__ |__ spacing .. plot:: :include-source: import pp c = pp.c.splitter_tree(coupler=pp.c.mmi1x2(), n_o_outputs=4, spacing=50, bend_radius=10) pp.plotgds(c) """ n_o_outputs = n_o_outputs c = pp.Component() coupler = pp.call_if_func(coupler) _coupler = c.add_ref(coupler) coupler_sep = coupler.ports["E1"].y - coupler.ports["E0"].y if n_o_outputs > 2: _cmp = splitter_tree( coupler=coupler, n_o_outputs=n_o_outputs // 2, bend_radius=bend_radius, spacing=spacing / 2, ) else: termination_component = (termination_component if termination_component is not None else waveguide(length=0.1)) _cmp = pp.call_if_func(termination_component) spacing = (spacing if spacing is not None else _cmp.ports["W0"].y - _coupler.size_info.south) if spacing < coupler_sep: tree_top = _cmp.ref(port_id="W0", position=_coupler.ports["E1"]) tree_bot = _cmp.ref( port_id="W0", position=_coupler.ports["E0"], v_mirror=False # True ) else: d = 2 * bend_radius + 1 spacing = max(spacing, d) tree_top = _cmp.ref(port_id="W0", position=_coupler.ports["E1"].position + (d, spacing)) tree_bot = _cmp.ref( port_id="W0", position=_coupler.ports["E0"].position + (d, -spacing), v_mirror=False, # True, ) c.add(connect_strip(coupler.ports["E1"], tree_top.ports["W0"])) c.add(connect_strip(coupler.ports["E0"], tree_bot.ports["W0"])) i = 0 for p in get_ports_facing(tree_bot, "E"): c.add_port(name="{}".format(i), port=p) i += 1 for p in get_ports_facing(tree_top, "E"): c.add_port(name="{}".format(i), port=p) i += 1 c.add(tree_bot) c.add(tree_top) c.add_port(name="W0", port=_coupler.ports["W0"]) return c