def ring_double_bus(**kwargs): """ Ring double bus Args: bend_radius=5 length_x=1 length_y=1 gap=0.2 coupler90_factory=coupler90 straight_factory=waveguide cpl_straight_factory=coupler_straight wg_width=0.5 .. code:: -CTL==CTS==CTR- | | VL VR | | -CBL==CBS==CBR- .. plot:: :include-source: import pp c = pp.c.ring_double_bus(gap=0.2, length_x=10, length_y=5, bend_radius=5) pp.plotgds(c) """ components, connections, ports_map = ring_double_bus_netlist(**kwargs) component = netlist_to_component(components, connections, ports_map) return component
def ring_single_bus(**kwargs): """ Ring single bus Args: bend_radius=5 length_x=1 length_y=1 gap=0.2 bend90_factory=bend_circular coupler90_factory=coupler90 straight_factory=waveguide cpl_straight_factory=coupler_straight wg_width=0.5 .. code:: --length_x- | | | length_y | | ---===gap===--- .. plot:: :include-source: import pp c = pp.c.ring_single_bus(gap=0.2, length_x=10, length_y=5, bend_radius=5) pp.plotgds(c) """ components, connections, ports_map = ring_single_bus_netlist(**kwargs) component = netlist_to_component(components, connections, ports_map) return component
def coupler(**kwargs) -> Component: """ symmetric coupler Args: gap length coupler_symmetric_factory coupler_straight .. code:: W1 __ __ E1 \ / \ / ========= gap / \ _/ \_ W0 length E0 coupler_straight coupler_symmetric_factory .. plot:: :include-source: import pp c = pp.c.coupler(gap=0.2, length=10) pp.plotgds(c) """ components, connections, ports_map = coupler_netlist(**kwargs) component = netlist_to_component(components, connections, ports_map) return component
def coupler_biased(**kwargs): """symmetric coupler""" components, connections, ports_map = coupler_netlist( coupler_symmetric_factory=coupler_symmetric_biased, coupler_straight=coupler_straight_biased, **kwargs) component = netlist_to_component(components, connections, ports_map) return component
def simple_mzi2x2(coupler_length=20.147, arm_length=40, gap=0.234, waveguide_factory=pp.c.waveguide): """ arm_top /-----\ CP1= =CP2= \-----/ arm_bot """ # Define the components to use coupler = pp.c.coupler(length=coupler_length, gap=gap) arm = waveguide_factory(length=arm_length) # Create component references and give them unique names {name : (component, transform)} # Transform can be either "None", "mirror_x", "mirror_y", "R90", "R180", "R270" components = { "CP1": (coupler, "None"), "CP2": (coupler, "None"), "arm_top": (arm, "None"), "arm_bot": (arm, "mirror_x"), } # Provide how components are connected (component 1, port A, component 2, port B) # means that port B from component 2 is positioned at port A from component 1 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"), ] # Create the ports for this component, choosing which ports from the subcomponents should be exposed # {port name: (subcomponent, subcomponent port name)} ports_map = { "W0": ("CP1", "W0"), "W1": ("CP1", "W1"), "E0": ("CP2", "E0"), "E1": ("CP2", "E1"), } component = netlist_to_component(components, connections, ports_map) return component
def ring_single_bus_deprecated(**kwargs): """ Ring single bus use single_bus instead as this one can have snaping issues that create gaps between waveguides of the ring Args: bend_radius=5 length_x=1 length_y=1 gap=0.2 bend90_factory=bend_circular coupler90_factory=coupler90 straight_factory=waveguide cpl_straight_factory=coupler_straight wg_width=0.5 .. code:: --length_x- | | | length_y | | ---===gap===--- .. plot:: :include-source: import pp c = pp.c.ring_single_bus(gap=0.2, length_x=10, length_y=5, bend_radius=5) pp.plotgds(c) """ components, connections, ports_map = ring_single_bus_netlist(**kwargs) component = netlist_to_component(components, connections, ports_map) return component
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 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
def netlist_from_yaml( yaml: Union[str, pathlib.Path, IO[Any]], component_factory=None, ) -> Component: """ Loads Component settings from YAML file, and connections Deprecated! use component_from_yaml instead Args: netlist: YAML IO describing instances, connections and ports_map Returns: Component .. code-block:: yaml instances: CP1: component: mmi1x2 settings: width_mmi: 4.5 length_mmi: 10 CP2: component: mmi1x2 settings: width_mmi: 4.5 length_mmi: 5 transformations: mirror_y arm_top: component: mzi_arm settings: L0: 10 DL: 0 arm_bot: component: mzi_arm settings: L0: 100 DL: 0 transformations: mirror_x 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] connections: - [CP1, E0, arm_bot, W0] - [arm_bot, E0, CP2, E0] - [CP1, E1, arm_top, W0] - [arm_top, E0, CP2, E0] """ yaml = io.StringIO(yaml) if isinstance(yaml, str) and "\n" in yaml else yaml conf = OmegaConf.load(yaml) component_factory = component_factory or component_factory_default instances = {} for instance_name in conf.instances: instance_conf = conf.instances[instance_name] component_type = instance_conf["component"] component_settings = instance_conf["settings"] or {} instance = component_factory[component_type](**component_settings) instance_transformations = instance_conf["transformations"] or "None" instance_properties = instance_conf["properties"] or {} for k, v in instance_properties.items(): setattr(instance, k, v) instance.name = instance_name instances[instance_name] = (instance, instance_transformations) connections = conf.connections ports_map = conf.ports_map return netlist_to_component(instances, connections, ports_map)