diff --git a/cspdk/si220/__init__.py b/cspdk/si220/__init__.py index c55245a..45b5634 100644 --- a/cspdk/si220/__init__.py +++ b/cspdk/si220/__init__.py @@ -24,12 +24,12 @@ def get_pdk() -> Pdk: """Return Cornerstone PDK.""" return Pdk( name="cornerstone_si220", - cells=_cells, + cells=_cells, # layout parametric cells cross_sections=_cross_sections, # type: ignore layers=LAYER, layer_stack=LAYER_STACK, layer_views=LAYER_VIEWS, - models=_models, + models=_models, # models for simulation routing_strategies=routing_strategies, ) diff --git a/cspdk/si220/cells/primitives.py b/cspdk/si220/cells/primitives.py index 6bc5e1c..d52f3f6 100644 --- a/cspdk/si220/cells/primitives.py +++ b/cspdk/si220/cells/primitives.py @@ -614,6 +614,52 @@ def mzi( ) +@gf.cell +def mzi_lattice_sc( + delta_length: float = 10.0, + bend="bend_euler_sc", + straight="straight_sc", + splitter="mmi1x2_sc", + combiner="mmi2x2_sc", + cross_section: CrossSectionSpec = "xs_sc", +) -> gf.Component: + """A Mach-Zehnder Interferometer. + + Args: + delta_length: the difference in length between the upper and lower arms of the mzi + bend: the name of the default bend of the mzi + straight: the name of the default straight of the mzi + splitter: the name of the default splitter of the mzi + combiner: the name of the default combiner of the mzi + cross_section: a cross section or its name or a function generating a cross section. + """ + return gf.c.mzi( + delta_length=delta_length, + length_y=1.0, + length_x=0.1, + straight_y=None, + straight_x_top=None, + straight_x_bot=None, + with_splitter=True, + port_e1_splitter="o2", + port_e0_splitter="o3", + port_e1_combiner="o3", + port_e0_combiner="o4", + nbends=2, + cross_section=cross_section, + cross_section_x_top=None, + cross_section_x_bot=None, + mirror_bot=False, + add_optical_ports_arms=False, + min_length=10e-3, + auto_rename_ports=True, + bend=bend, + straight=straight, + splitter=splitter, + combiner=combiner, + ) + + @gf.cell def coupler_ring_sc( gap: float = 0.2, diff --git a/cspdk/si220/models.py b/cspdk/si220/models.py index 8c55335..39a7f5d 100644 --- a/cspdk/si220/models.py +++ b/cspdk/si220/models.py @@ -257,9 +257,9 @@ def coupler_symmetric() -> sax.SDict: raise NotImplementedError("No model for 'coupler_symmetric'") -coupler_sc = partial(sm.mmi2x2, wl0=1.55, fwhm=0.2) +coupler_sc = partial(sm.coupler, wl0=1.55, fwhm=0.2) coupler_rc = coupler_sc -coupler_so = partial(sm.mmi2x2, wl0=1.31, fwhm=0.2) +coupler_so = partial(sm.coupler, wl0=1.31, fwhm=0.2) coupler_ro = coupler_so coupler_ring_sc = partial(sm.coupler, wl0=1.55) diff --git a/cspdk/si220/samples/circuit_lattice.py b/cspdk/si220/samples/circuit_lattice.py new file mode 100644 index 0000000..59be04b --- /dev/null +++ b/cspdk/si220/samples/circuit_lattice.py @@ -0,0 +1,29 @@ +"""Circuit simulation with routes.""" + +import gdsfactory as gf +import jax.numpy as jnp +import matplotlib.pyplot as plt +import sax + +from cspdk.si220 import PDK, cells + +def lattice_filter(): + +if __name__ == "__main__": + c = gf.Component() + mzi_lattice = cells.mzi_lattice(delta_length=10) + + netlist = c.get_netlist(recursive=True) + c.plot_netlist(recursive=True) + models = PDK.models + circuit, _ = sax.circuit(netlist, models=models) # type: ignore + wl = jnp.linspace(1.5, 1.6, 256) + + S = circuit(wl=wl) + plt.figure(figsize=(14, 4)) + plt.title("MZI") + plt.plot(1e3 * wl, jnp.abs(S["o1", "o2"]) ** 2) # type: ignore + plt.xlabel("λ [nm]") + plt.ylabel("T") + plt.grid(True) + plt.show() diff --git a/cspdk/si220/samples/circuit_simulations_sc.py b/cspdk/si220/samples/circuit_simulations_sc.py index b6c3c6c..de2ac40 100644 --- a/cspdk/si220/samples/circuit_simulations_sc.py +++ b/cspdk/si220/samples/circuit_simulations_sc.py @@ -7,8 +7,11 @@ from cspdk.si220 import PDK, cells if __name__ == "__main__": - c = cells.mzi_sc(delta_length=12) - c.show() + # Layout definition + c = cells.mzi_sc(delta_length=12 * 2) + c.show() # show the layout in Klayout + + # Circuit simulation netlist = c.get_netlist() c.plot_netlist() models = PDK.models