def mzi1x2( L0: float = 0.1, DL: float = 9.0, L2: float = 10.0, bend_radius: float = 10.0, bend90_factory: Callable = bend_circular, straight_heater_factory: Callable = waveguide_heater, straight_factory: Callable = waveguide, coupler_factory: Callable = mmi1x2, with_elec_connections: bool = False, ) -> Component: """ Mzi 1x2 Args: L0: vertical length for both and top arms DL: bottom arm extra length L2: L_top horizontal length bend_radius: 10.0 bend90_factory: bend_circular straight_heater_factory: waveguide_heater or waveguide straight_factory: waveguide coupler_factory: coupler .. code:: __L2__ | | L0 L0 | | --| |-- | | L0 L0 | | DL DL | | |__L2__| top_arm -CP1= =CP2- bot_arm .. plot:: :include-source: import pp c = pp.c.mzi1x2(L0=0.1, DL=0, L2=10) pp.plotgds(c) """ if not with_elec_connections: straight_heater_factory = straight_factory cpl = pp.call_if_func(coupler_factory) arm_defaults = { "L_top": L2, "bend_radius": bend_radius, "bend90_factory": bend90_factory, "straight_heater_factory": straight_heater_factory, "straight_factory": straight_factory, "with_elec_connections": with_elec_connections, } arm_top = mzi_arm(L0=L0, **arm_defaults) arm_bot = mzi_arm(L0=L0 + DL, **arm_defaults) components = { "CP1": (cpl, "None"), "CP2": (cpl, "mirror_y"), "arm_top": (arm_top, "None"), "arm_bot": (arm_bot, "mirror_x"), } connections = [ # Bottom arm ("CP1", "E0", "arm_bot", "W0"), ("arm_bot", "E0", "CP2", "E0"), # Top arm ("CP1", "E1", "arm_top", "W0"), ("arm_top", "E0", "CP2", "E0"), ] if with_elec_connections: ports_map = { "W0": ("CP1", "W0"), "E0": ("CP2", "W0"), "E_TOP_0": ("arm_top", "E_0"), "E_TOP_1": ("arm_top", "E_1"), "E_TOP_2": ("arm_top", "E_2"), "E_TOP_3": ("arm_top", "E_3"), "E_BOT_0": ("arm_bot", "E_0"), "E_BOT_1": ("arm_bot", "E_1"), "E_BOT_2": ("arm_bot", "E_2"), "E_BOT_3": ("arm_bot", "E_3"), } component = netlist_to_component(components, connections, ports_map) # Need to connect common ground and redefine electrical ports ports = component.ports y_elec = ports["E_TOP_0"].y for ls, le in [ ("E_BOT_0", "E_BOT_1"), ("E_TOP_0", "E_TOP_1"), ("E_BOT_2", "E_TOP_2"), ]: component.add_polygon(line(ports[ls], ports[le]), layer=ports[ls].layer) # Add GND ("E_BOT_2", "E_TOP_2") component.add_port( name="GND", midpoint=0.5 * (ports["E_BOT_2"].midpoint + ports["E_TOP_2"].midpoint), orientation=180, width=ports["E_BOT_2"].width, layer=ports["E_BOT_2"].layer, ) component.ports["E_TOP_3"].orientation = 0 component.ports["E_BOT_3"].orientation = 0 # Remove the eletrical ports that we have just used internally for lbl in [ "E_BOT_0", "E_BOT_1", "E_TOP_0", "E_TOP_1", "E_BOT_2", "E_TOP_2" ]: component.ports.pop(lbl) # Reroute electrical ports _e_ports = select_electrical_ports(component) conn, e_ports = route_elec_ports_to_side(_e_ports, side="north", y=y_elec) for c in conn: component.add(c) for p in e_ports: component.ports[p.name] = p # Create nice electrical port names component.ports["HT1"] = component.ports["E_TOP_3"] component.ports.pop("E_TOP_3") component.ports["HT2"] = component.ports["E_BOT_3"] component.ports.pop("E_BOT_3") else: ports_map = {"W0": ("CP1", "W0"), "E0": ("CP2", "W0")} component = netlist_to_component(components, connections, ports_map) return component
def wg_heater_connector( heater_ports: List[Port], metal_width: float = 10.0, tlm_layers: List[Tuple[int, int]] = [ LAYER.VIA1, LAYER.M1, LAYER.VIA2, LAYER.M2, LAYER.VIA3, LAYER.M3, ], ) -> Component: """ Connects together a pair of wg heaters and connect to a M3 port """ cmp = Component() assert len(heater_ports) == 2 assert (heater_ports[0].orientation == heater_ports[1].orientation ), "both ports should be facing in the same direction" angle = heater_ports[0].orientation angle = angle % 360 assert angle in [0, 180], "angle should be 0 or 180, got {}".format(angle) dx = 0.0 dy = 0.0 angle_to_dps = {0: [(-dx, -dy), (-dx, dy)], 180: [(dx, -dy), (dx, dy)]} ports = heater_ports hw = heater_ports[0].width if angle in [0, 180]: ports.sort(key=lambda p: p.y) else: ports.sort(key=lambda p: p.x) _heater_to_metal = tlm(width=0.5, height=0.5, layers=tlm_layers, vias=[]) tlm_positions = [] for port, dp in zip(ports, angle_to_dps[angle]): # Extend heater p = port.midpoint # Add via/metal transitions tlm_pos = p + dp hm = _heater_to_metal.ref(position=tlm_pos) tlm_positions += [tlm_pos] cmp.add(hm) ss = 1 if angle == 0 else -1 # Connect both sides with top metal edge_metal_piece_width = 7.0 x = ss * edge_metal_piece_width / 2 top_metal_layer = tlm_layers[-1] cmp.add_polygon( line( tlm_positions[0] + (x, -hw / 2), tlm_positions[1] + (x, hw / 2), edge_metal_piece_width, ), layer=top_metal_layer, ) # Add metal port cmp.add_port( name="0", midpoint=0.5 * sum(tlm_positions) + (ss * edge_metal_piece_width / 2, 0), orientation=angle, width=metal_width, layer=top_metal_layer, port_type="dc", ) return cmp
def mzi2x2( CL_1=20.147, L0=60, L1=7.38, L2=10.0, gap=0.234, bend_radius=10.0, bend90_factory=bend_circular, straight_heater_factory=waveguide_heater, straight_factory=waveguide, coupler_factory=coupler, with_elec_connections=True, ): """ Mzi 2x2 Args: CL_1: coupler length L0: vertical length for both and top arms L1: bottom arm extra length L2: L_top horizontal length gap: 0.235 bend_radius: 10.0 bend90_factory: bend_circular straight_heater_factory: waveguide_heater or waveguide straight_factory: waveguide coupler_factory: coupler .. code:: __L2__ | | L0 L0 | | ==| |== | | L0 L0 | | L1 L1 | | |__L2__| .. code:: top_arm ==CL_1= =CL_1=== bot_arm .. plot:: :include-source: import pp c = pp.c.mzi2x2(CL_1=10, gap=0.2) pp.plotgds(c) """ if callable(coupler_factory): cpl = coupler_factory(length=CL_1, gap=gap) else: cpl = coupler_factory arm_defaults = { "L_top": L2, "bend_radius": bend_radius, "bend90_factory": bend90_factory, "straight_heater_factory": straight_heater_factory, "straight_factory": straight_factory, "with_elec_connections": with_elec_connections, } arm_top = mzi_arm(L0=L0, **arm_defaults) arm_bot = mzi_arm(L0=L0, L1=L1, **arm_defaults) components = { "CP1": (cpl, "None"), "CP2": (cpl, "None"), "arm_top": (arm_top, "None"), "arm_bot": (arm_bot, "mirror_x"), } connections = [ ## Top arm ("CP1", "E1", "arm_top", "W0"), ("arm_top", "E0", "CP2", "W1"), ## Bottom arm ("CP1", "E0", "arm_bot", "W0"), ("arm_bot", "E0", "CP2", "W0"), ] if with_elec_connections: ports_map = { "W0": ("CP1", "W0"), "W1": ("CP1", "W1"), "E0": ("CP2", "E0"), "E1": ("CP2", "E1"), "E_TOP_0": ("arm_top", "E_0"), "E_TOP_1": ("arm_top", "E_1"), "E_TOP_2": ("arm_top", "E_2"), "E_TOP_3": ("arm_top", "E_3"), "E_BOT_0": ("arm_bot", "E_0"), "E_BOT_1": ("arm_bot", "E_1"), "E_BOT_2": ("arm_bot", "E_2"), "E_BOT_3": ("arm_bot", "E_3"), } component = netlist_to_component(components, connections, ports_map) # Need to connect common ground and redefine electrical ports ports = component.ports y_elec = ports["E_TOP_0"].y for ls, le in [ ("E_BOT_0", "E_BOT_1"), ("E_TOP_0", "E_TOP_1"), ("E_BOT_2", "E_TOP_2"), ]: component.add_polygon(line(ports[ls], ports[le]), layer=ports[ls].layer) # Add GND component.add_port( name="GND", midpoint=0.5 * (ports["E_BOT_2"].midpoint + ports["E_TOP_2"].midpoint), orientation=180, width=ports["E_BOT_2"].width, layer=ports["E_BOT_2"].layer, ) component.ports["E_TOP_3"].orientation = 0 component.ports["E_BOT_3"].orientation = 0 # Remove the eletrical ports that we have just used internally for lbl in ["E_BOT_0", "E_BOT_1", "E_TOP_0", "E_TOP_1", "E_BOT_2", "E_TOP_2"]: component.ports.pop(lbl) # Reroute electrical ports _e_ports = select_electrical_ports(component) conn, e_ports = route_elec_ports_to_side(_e_ports, side="north", y=y_elec) for c in conn: component.add(c) for p in e_ports: component.ports[p.name] = p # Create nice electrical port names component.ports["HT1"] = component.ports["E_TOP_3"] component.ports.pop("E_TOP_3") component.ports["HT2"] = component.ports["E_BOT_3"] component.ports.pop("E_BOT_3") # Make sure each port knows its name for k, p in component.ports.items(): p.name = k elif straight_heater_factory == waveguide: ports_map = { "W0": ("CP1", "W0"), "W1": ("CP1", "W1"), "E0": ("CP2", "E0"), "E1": ("CP2", "E1"), } component = netlist_to_component(components, connections, ports_map) return component