EME with MEOW

Contents

EME with MEOW#

Some components are more efficiently modeled with Eigenmode Expansion.

Gdsfactory provides a plugin for MEOW to efficiently extract component S-parameters through EME.

Currently the component needs to specifically have a single “o1” port facing west, and a single “o2” port facing east, like this taper:

import gdsfactory as gf
import matplotlib.pyplot as plt
import numpy as np
from gdsfactory.generic_tech import get_generic_pdk

from gplugins.meow import MEOW

gf.config.rich_output()
PDK = get_generic_pdk()
PDK.activate()

LAYER_STACK = PDK.layer_stack
c = gf.components.taper_cross_section_sine()
c.plot()

../_images/5f299e6a9a32863878ce37e9969609a6af49651e155a493978f77fe7c4accee0.png

You also need to explicitly provide a LayerStack to define cross-sections, for instance the generic one:

layer_stack = LAYER_STACK

filtered_layer_stack = gf.technology.LayerStack(
    layers={
        k: layer_stack.layers[k]
        for k in (
            "slab90",
            "core",
            "box",
            "clad",
        )
    }
)

Since you need to make sure that your entire LayerStack has e.g. material information for all present layers, it is safer to only keep the layers that you need for your simulation:

The EME simulator can be instantiated with only these two elements, alongside parameters:

eme = MEOW(
    component=c, layer_stack=filtered_layer_stack, wavelength=1.55, overwrite=True
)

Plotting functions allow you to check your simulation:

eme.plot_structure()

The cross-section themselves:

eme.plot_cross_section(xs_num=0)

../_images/8b16b48b7c2d9aa6ad26239e12fb2dae0996bc0bfe95644973e15d917b8eb986.png
eme.plot_cross_section(xs_num=-1)

../_images/137d14a8a7220891567e72ccd2c83e20084f81f68383ae67df191ecef2c41ca8.png

And the modes (after calculating them):

eme.plot_mode(xs_num=0, mode_num=0)

../_images/8cf7bb782f6293a85f58142137aa51b69d49869a83ba637642cfc4aec829ba5f.png
eme.plot_mode(xs_num=-1, mode_num=0)

../_images/729da2243b6f21e11ace922d2239c83d7ba8f651391048fa2bff8c594259c758.png

The S-parameters can be calculated, and are returned in the same format as for the FDTD solvers (the original MEOW S-parameter results S and port_names are saved as attributes):

sp = eme.compute_sparameters()
2024-05-10 10:21:08.818 | INFO     | gplugins.meow.meow_eme:compute_sparameters:442 - Write simulation results to PosixPath('/home/runner/.gdsfactory/sp/taper_cross_section/taper_cross_section_npoints101_303db1d3f0fd55b034c4998d104048af.npz')
2024-05-10 10:21:08.826 | INFO     | gplugins.meow.meow_eme:compute_sparameters:444 - Write simulation settings to PosixPath('/home/runner/.gdsfactory/sp/taper_cross_section/taper_cross_section_npoints101_303db1d3f0fd55b034c4998d104048af.yml')
print(np.abs(sp["o1@0,o2@0"]) ** 2)
0.9938576082075395
print(eme.port_map)
eme.plot_s_params()
{'left@0': 0, 'left@1': 1, 'left@2': 2, 'left@3': 3, 'right@0': 4, 'right@1': 5, 'right@2': 6, 'right@3': 7}

../_images/62a47e5ecf8229ce377300870e63452decc9944273e40d02a692d7f0d7138516.png

As you can see most light stays on the fundamental TE mode

Sweep EME length#

Lets sweep the length of the taper.

layer_stack = LAYER_STACK

filtered_layer_stack = gf.technology.LayerStack(
    layers={
        k: layer_stack.layers[k]
        for k in (
            "slab90",
            "core",
            "box",
            "clad",
        )
    }
)

c = gf.components.taper(width1=0.5, width2=2, length=10.0)
c.plot()

../_images/b816fbc2e1528e183bff9e4e6fc12f8396146595f5bac3905b577b60fbd150a2.png

Lets do a convergence tests on the cell_length parameter. This depends a lot on the structure.

trans = []
cells_lengths = [0.1, 0.25, 0.5, 0.75, 1]

for cell_length in cells_lengths:
    m = MEOW(
        component=c,
        layer_stack=filtered_layer_stack,
        wavelength=1.55,
        overwrite=True,
        spacing_y=-3,
        cell_length=cell_length,
    )
    sp = m.compute_sparameters()
    te0_trans = np.abs(sp["o1@0,o2@0"]) ** 2
    trans.append(te0_trans)

plt.plot(cells_lengths, trans, ".-")
plt.title("10um taper, resx = resy = 100, num_modes = 4")
plt.xlabel("Cell length (um)")
plt.ylabel("TE0 transmission")
2024-05-10 10:23:09.506 | INFO     | gplugins.meow.meow_eme:compute_sparameters:442 - Write simulation results to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_width22_147b8acb38dc6e35ab6222ecb12136eb.npz')
2024-05-10 10:23:09.512 | INFO     | gplugins.meow.meow_eme:compute_sparameters:444 - Write simulation settings to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_width22_147b8acb38dc6e35ab6222ecb12136eb.yml')
2024-05-10 10:23:58.390 | INFO     | gplugins.meow.meow_eme:compute_sparameters:442 - Write simulation results to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_width22_aabdd3d75d38a5aacab6454296c04716.npz')
2024-05-10 10:23:58.395 | INFO     | gplugins.meow.meow_eme:compute_sparameters:444 - Write simulation settings to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_width22_aabdd3d75d38a5aacab6454296c04716.yml')
2024-05-10 10:24:22.671 | INFO     | gplugins.meow.meow_eme:compute_sparameters:442 - Write simulation results to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_width22_0d8e9f7b0723e21142c159defde76aaa.npz')
2024-05-10 10:24:22.676 | INFO     | gplugins.meow.meow_eme:compute_sparameters:444 - Write simulation settings to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_width22_0d8e9f7b0723e21142c159defde76aaa.yml')
2024-05-10 10:24:40.829 | INFO     | gplugins.meow.meow_eme:compute_sparameters:442 - Write simulation results to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_width22_c768af9f81d2ceda1c6ebe39367b7d30.npz')
2024-05-10 10:24:40.835 | INFO     | gplugins.meow.meow_eme:compute_sparameters:444 - Write simulation settings to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_width22_c768af9f81d2ceda1c6ebe39367b7d30.yml')
2024-05-10 10:24:54.436 | INFO     | gplugins.meow.meow_eme:compute_sparameters:442 - Write simulation results to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_width22_762a8e5ff88971c19b2f0cd56c159a97.npz')
2024-05-10 10:24:54.441 | INFO     | gplugins.meow.meow_eme:compute_sparameters:444 - Write simulation settings to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_width22_762a8e5ff88971c19b2f0cd56c159a97.yml')

Text(0, 0.5, 'TE0 transmission')

../_images/049bd1a4e40c853f390e950b72229e5e2aaffdf12c862d2154f29a8075d313c8.png
eme = MEOW(
    component=c,
    layer_stack=filtered_layer_stack,
    wavelength=1.55,
    overwrite=True,
    spacing_y=-3,
    cell_length=0.25,
)
eme.plot_cross_section(xs_num=0)

../_images/f189351570eff46c924919c7f68bab628b360e7a4c7ff4976741e2342c7ddb6f.png
eme.plot_mode(xs_num=0, mode_num=0)

../_images/ec3830f792372f56a37033e1abad01d5aa9cc40205406dc27c53a4cc324df7b2.png
eme.plot_cross_section(xs_num=-1)

../_images/0ffaa62a047745dbdfff5d7cec7feffcc5c6ed17ee011da52cc487513ad7fef1.png
eme.plot_mode(xs_num=-1, mode_num=0)

../_images/91cf8937e004fd117e21c74406ebaf305948d7debfd49fc7f893a317ac91e8da.png
sp = eme.compute_sparameters()
2024-05-10 10:25:45.751 | INFO     | gplugins.meow.meow_eme:compute_sparameters:442 - Write simulation results to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_width22_aabdd3d75d38a5aacab6454296c04716.npz')
2024-05-10 10:25:45.756 | INFO     | gplugins.meow.meow_eme:compute_sparameters:444 - Write simulation settings to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_width22_aabdd3d75d38a5aacab6454296c04716.yml')
print(eme.port_map)
eme.plot_s_params()
{'left@0': 0, 'left@1': 1, 'left@2': 2, 'left@3': 3, 'right@0': 4, 'right@1': 5, 'right@2': 6, 'right@3': 7}

../_images/6c8f38d5d220a73ed42216fa0c6694be86e60b2c27d92eb69a43684ee8126b6d.png
T = np.abs(sp["o1@0,o2@0"]) ** 2
T

0.9793136838922382
np.abs(sp["o1@0,o2@2"]) ** 2

0.0009141304516847901
lengths = np.array([1, 2, 3, 5, 10, 20])
T = np.zeros_like(lengths, dtype=float)
for length in lengths:
    c = gf.components.taper(width1=0.5, width2=2, length=length)
    c.plot()

../_images/f29d0d81d5d54309b53235357dfeea64f0a25615e4d222ffeac10d4eb73bc39d.png

../_images/7d4c8b2129b7c805850b1c278dd0204cf59bdc92e35a43be9cb7319569254525.png

../_images/54eaaf0db232d75cb8a10ceb869cfc4a3281e85f6d3fc8217328efd3ed5aa82e.png

../_images/f57d6c0a45f5a1607da619d16f040512dbfc03703dc6bc0178a10a609459f247.png

../_images/b816fbc2e1528e183bff9e4e6fc12f8396146595f5bac3905b577b60fbd150a2.png

../_images/30705ea665eaa73d0765e83a8ea5a8b5b38daa9ec82ae6a31ae4134ae2e84130.png
for i, length in enumerate(lengths):
    print(f"{length=}")
    c = gf.components.taper(width1=0.5, width2=2, length=length)
    eme = MEOW(
        component=c,
        layer_stack=filtered_layer_stack,
        wavelength=1.55,
        overwrite=True,
        spacing_y=-3,
        cell_length=0.25,
    )
    sp = eme.compute_sparameters()
    T[i] = np.abs(sp["o1@0,o2@0"]) ** 2
length=1
2024-05-10 10:25:54.178 | INFO     | gplugins.meow.meow_eme:compute_sparameters:442 - Write simulation results to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_length1_width22_0ab08453d41d2e9c3ec312536d9161c0.npz')
2024-05-10 10:25:54.184 | INFO     | gplugins.meow.meow_eme:compute_sparameters:444 - Write simulation settings to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_length1_width22_0ab08453d41d2e9c3ec312536d9161c0.yml')
length=2
2024-05-10 10:26:05.588 | INFO     | gplugins.meow.meow_eme:compute_sparameters:442 - Write simulation results to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_length2_width22_a9d0bccc8ef13c387971faa4ef249fd2.npz')
2024-05-10 10:26:05.593 | INFO     | gplugins.meow.meow_eme:compute_sparameters:444 - Write simulation settings to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_length2_width22_a9d0bccc8ef13c387971faa4ef249fd2.yml')
length=3
2024-05-10 10:26:21.490 | INFO     | gplugins.meow.meow_eme:compute_sparameters:442 - Write simulation results to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_length3_width22_d11e48c92b653f5acc890ddd0513fca5.npz')
2024-05-10 10:26:21.496 | INFO     | gplugins.meow.meow_eme:compute_sparameters:444 - Write simulation settings to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_length3_width22_d11e48c92b653f5acc890ddd0513fca5.yml')
length=5
2024-05-10 10:26:45.897 | INFO     | gplugins.meow.meow_eme:compute_sparameters:442 - Write simulation results to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_length5_width22_5985a8dd8d9b8574379146a8032c54de.npz')
2024-05-10 10:26:45.902 | INFO     | gplugins.meow.meow_eme:compute_sparameters:444 - Write simulation settings to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_length5_width22_5985a8dd8d9b8574379146a8032c54de.yml')
length=10
2024-05-10 10:27:33.664 | INFO     | gplugins.meow.meow_eme:compute_sparameters:442 - Write simulation results to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_length10_width22_8cf29a2e06436a957fe8bca7fa716b34.npz')
2024-05-10 10:27:33.669 | INFO     | gplugins.meow.meow_eme:compute_sparameters:444 - Write simulation settings to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_length10_width22_8cf29a2e06436a957fe8bca7fa716b34.yml')
length=20
2024-05-10 10:29:08.032 | INFO     | gplugins.meow.meow_eme:compute_sparameters:442 - Write simulation results to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_length20_width22_b0dcacf6ad01e6e5c36cac1032912dda.npz')
2024-05-10 10:29:08.037 | INFO     | gplugins.meow.meow_eme:compute_sparameters:444 - Write simulation settings to PosixPath('/home/runner/.gdsfactory/sp/taper/taper_length20_width22_b0dcacf6ad01e6e5c36cac1032912dda.yml')
plt.plot(lengths, T, marker="o")
plt.ylim(0.6, 1.0)
plt.title("Fundamental mode transmission")
plt.ylabel("Transmission")
plt.xlabel("taper length (um)")
plt.grid(True)
plt.show()

../_images/651fd9c0f8c51797fce9d499436234600c975a9a079e0276be74637e1db87aee.png
eme.plot_s_params()

../_images/015e372e6437ca8a48d0ec2b8a32a3e78b8afc3541df31162b67ab691e5bdc84.png