Source code for gdsfactory.components.mzm

from __future__ import annotations

from functools import partial

import gdsfactory as gf
from gdsfactory.cell import cell
from gdsfactory.component import Component
from gdsfactory.components.bend_euler import bend_euler
from gdsfactory.components.coupler import coupler
from gdsfactory.components.mmi1x2 import mmi1x2
from gdsfactory.components.mmi2x2 import mmi2x2
from gdsfactory.components.straight import straight as straight_function
from gdsfactory.components.straight_pin import straight_pin
from gdsfactory.routing.get_route import get_route
from gdsfactory.typings import ComponentSpec, CrossSectionSpec


[docs] @cell def mzm( phase_shifter: ComponentSpec = straight_pin, length_x: float = 500, length_y: float = 2.0, delta_length: float = 0.0, bend: ComponentSpec = bend_euler, straight: ComponentSpec = straight_function, splitter: ComponentSpec = "mmi1x2", combiner: ComponentSpec | None = "mmi1x2", with_splitter: bool = True, port_e1_splitter: str = "o2", port_e0_splitter: str = "o3", port_e1_combiner: str = "o2", port_e0_combiner: str = "o3", nbends: int = 2, cross_section: CrossSectionSpec = "xs_sc", mirror_bot: bool = False, min_length: float = 0.01, ) -> Component: """Mzm modulator. Args: phase_shifter: for bottom and top arms. length_x: horizontal length. None uses to the straight_x_bot/top defaults. length_y: vertical length for both and top arms. delta_length: bottom arm vertical extra length. bend: 90 degrees bend spec. straight: straight function for vertical. splitter: splitter function. combiner: combiner function. Optional adds ports. with_splitter: if False removes splitter. port_e1_splitter: east top splitter port. port_e0_splitter: east bot splitter port. port_e1_combiner: east top combiner port. port_e0_combiner: east bot combiner port. nbends: from straight top/bot to combiner (at least 2). cross_section: for routing (sxtop/sxbot to combiner). mirror_bot: mirrors bottom arm. min_length: minimum length for straight_x_bot/top. .. code:: b2______b3 | sxtop | straight_y | | | b1 b4 splitter==| |==combiner b5 b8 | | straight_y | | | delta_length/2 | | | b6__sxbot__b7 Lx """ bend_spec = bend bend = gf.get_component(bend, cross_section=cross_section) c = Component() cp1 = gf.get_component(splitter) cp2 = gf.get_component(combiner) if combiner else None if with_splitter: cp1 = c << cp1 b5 = c << bend b5.mirror() b5.connect("o1", cp1.ports[port_e0_splitter]) syl = c << straight(length=delta_length / 2 + length_y, cross_section=cross_section) syl.connect("o1", b5.ports["o2"]) b6 = c << bend b6.connect("o1", syl.ports["o2"]) straight_x_bot = gf.get_component(phase_shifter, length=length_x) sxb = c << straight_x_bot if mirror_bot: sxb.mirror() sxb.connect("o1", b6.ports["o2"]) b1 = c << bend b1.connect("o1", cp1.ports[port_e1_splitter]) sytl = c << straight(length=length_y, cross_section=cross_section) sytl.connect("o1", b1.ports["o2"]) b2 = c << bend b2.connect("o2", sytl.ports["o2"]) straight_x_top = gf.get_component(phase_shifter, length=length_x) sxt = c << straight_x_top sxt.connect("o1", b2.ports["o1"]) if combiner: cp2 = c << cp2 cp2.mirror() cp2.xmin = sxt.ports["o2"].x + bend.info["radius"] * nbends + 2 * min_length route = get_route( sxt.ports["o2"], cp2.ports[port_e1_combiner], straight=straight, bend=bend_spec, cross_section=cross_section, with_sbend=False, ) c.add(route.references) route = get_route( sxb.ports["o2"], cp2.ports[port_e0_combiner], straight=straight, bend=bend_spec, cross_section=cross_section, ) c.add(route.references) cp2.name = "cp2" sytl.name = "sytl" syl.name = "syl" sxt.name = "sxt" sxb.name = "sxb" cp1.name = "cp1" c.add_ports(cp2.get_ports_list(orientation=0), prefix="out_") else: c.add_port("o3", port=sxt["o2"]) c.add_port("o4", port=sxb["o2"]) if with_splitter: c.add_ports(cp1.get_ports_list(orientation=180), prefix="in_") else: c.add_port("o1", port=b1.ports["o1"]) c.add_port("o2", port=b5.ports["o1"]) c.add_ports(sxt.get_ports_list(port_type="electrical"), prefix="top_") c.add_ports(sxb.get_ports_list(port_type="electrical"), prefix="bot_") c.add_ports(sxt.get_ports_list(port_type="placement"), prefix="top_") c.add_ports(sxb.get_ports_list(port_type="placement"), prefix="bot_") return c
mzm1x2 = partial(mzm, splitter=mmi1x2, combiner=mmi1x2) mzm2x2_2x2 = partial( mzm, splitter=mmi2x2, combiner=mmi2x2, port_e1_splitter="o3", port_e0_splitter="o4", port_e1_combiner="o3", port_e0_combiner="o4", ) mzm1x2_2x2 = partial( mzm, combiner=mmi2x2, port_e1_combiner="o3", port_e0_combiner="o4", ) mzm_coupler = partial( mzm2x2_2x2, splitter=coupler, combiner=coupler, ) if __name__ == "__main__": c = mzm() # c = mzm1x2_2x2(delta_length=100) c.show(show_ports=True) # c = gf.components.mzi2x2_2x2(straight_x_top="straight_heater_metal") # c2 = gf.routing.add_fiber_array(c) # c2.show() # c2 = gf.read.import_gds("a.gds") # c3 = gf.grid([c2, c1]) # c3.show(show_ports=False)