Source code for modes.mode_solver_full

import json
from typing import Optional, Tuple

import numpy as np
import pytest

from modes._mode_solver_full_vectorial import ModeSolverFullyVectorial
from modes._structure import RidgeWaveguide
from modes.autoname import autoname, clean_value
from modes.get_modes_jsonpath import get_modes_jsonpath
from modes.materials import nitride, sio2
from modes.types import Field
from modes.waveguide import waveguide


@pytest.mark.parametrize("overwrite", [True, False])
def test_mode_solver_full_vectorial(overwrite: bool) -> None:
    mode_solver = mode_solver_full(overwrite=overwrite, logscale=True, plot=True)
    # modes = mode_solver.solve()
    # neff0 = modes["n_effs"][0].real

    neff0 = mode_solver.results["n_effs"][0].real
    print(neff0)
    assert np.isclose(neff0, 2.4717079424099673)


@pytest.mark.parametrize("overwrite", [True, False])
def test_mode_solver_full_vectorial_multi_clad(overwrite: bool) -> None:
    mode_solver = mode_solver_full(
        overwrite=overwrite,
        logscale=True,
        plot=False,
        clad_thickness=[50e-3, 50e-3, 0.5],
        n_clads=[sio2, nitride, sio2],
    )
    # modes = mode_solver.solve()
    # neff0 = modes["n_effs"][0].real

    neff0 = mode_solver.results["n_effs"][0].real
    print(neff0)
    assert np.isclose(neff0, 2.483481412238637)


@autoname
def _full(
    n_modes: int = 2,
    wg: Optional[RidgeWaveguide] = None,
    plot_index: bool = True,
    **wg_kwargs
) -> ModeSolverFullyVectorial:
    """Returns mode solver and
    can also plot the index profile.

    Args:
        n_modes: 2
        wg: waveguide object
        plot_index: plot index profile
        wg_kwargs: for waveguide
    """

    wg = wg or waveguide(**wg_kwargs)

    if plot_index:
        wg.plot()

    mode_solver = ModeSolverFullyVectorial(n_modes)
    mode_solver.wg = wg
    return mode_solver


[docs]def mode_solver_full( n_modes: int = 2, overwrite: bool = False, plot: bool = False, plot_index: bool = False, logscale: bool = False, wg: Optional[RidgeWaveguide] = None, fields_to_write: Tuple[Field, ...] = ( "Ex", "Ey", "Ez", "Hx", "Hy", "Hz", ), **wg_kwargs ) -> ModeSolverFullyVectorial: """Return full vectorial mode solver with the computed modes Args: n_modes: 2 overwrite: whether to run again even if it finds the modes in PATH.cache plot: plot modes plot_index: plots index profile logscale: plots mode in logscale wg: waveguide fields_to_write: List of fields_to_write "Ex", "Ey", "Ez", "Hx", "Hy", "Hz" Keyword Args: x_step: 0.02 grid step (um) y_step: 0.02 grid step (um) thickness: 0.22 (um) width: 0.5 (um) slab_thickness: 0 (um) sub_width: 2.0 related to the total simulation width sub_thickness: 0.5 bottom simulation margin clad_thickness: [0.5] List of claddings (top simulation margin) n_sub: sio2 substrate index material n_wg: si waveguide index material n_clads: list of cladding materials [sio2] wavelength: 1.55 wavelength (um) angle: 90 sidewall angle (degrees) .. plot:: :include-source: import modes as ms s = ms.mode_solver_full(plot=True, plot_index=True, n_modes=1, width=0.5, thickness=0.22) print(s.results.keys()) """ mode_solver = _full(n_modes=n_modes, wg=wg, plot_index=plot_index, **wg_kwargs) settings = {k: clean_value(v) for k, v in mode_solver.settings.items()} jsonpath = get_modes_jsonpath(mode_solver) filepath = jsonpath.with_suffix(".dat") if overwrite or not jsonpath.exists(): r = mode_solver.solve() n_effs_real = r["n_effs"].real.tolist() n_effs_imag = r["n_effs"].imag.tolist() modes = r["modes"] modes_real = [ {k: v.real.tolist() for k, v in mode.fields.items()} for mode in modes ] modes_imag = [ {k: v.imag.tolist() for k, v in mode.fields.items()} for mode in modes ] d = dict( n_effs_real=n_effs_real, n_effs_imag=n_effs_imag, modes_real=modes_real, modes_imag=modes_imag, n_modes=len(n_effs_real), settings=settings, mode_types=mode_solver._get_mode_types(), fraction_te=mode_solver.fraction_te, fraction_tm=mode_solver.fraction_tm, ) with open(jsonpath, "w") as f: f.write(json.dumps(d)) mode_solver.write_modes_to_file( filepath, plot=plot, fields_to_write=fields_to_write, logscale=logscale ) r["settings"] = settings else: d = json.loads(open(jsonpath).read()) modes_real = d["modes_real"] modes_imag = d["modes_imag"] modes_cache = [ {k: np.array(np.array(mr[k]) + 1j * np.array(mi[k])) for k in mr.keys()} for mr, mi in zip(modes_real, modes_imag) ] n_effs_real = d["n_effs_real"] n_effs_imag = d["n_effs_imag"] n_effs_cache = [ np.array(np.array(mr) + 1j * np.array(mi)) for mr, mi in zip(n_effs_real, n_effs_imag) ] mode_solver.mode_types = mode_types = d["mode_types"] mode_solver.fraction_tm = fraction_tm = d["fraction_tm"] mode_solver.fraction_te = fraction_te = d["fraction_te"] r = dict( modes=modes_cache, n_effs=n_effs_cache, mode_types=mode_types, fraction_te=fraction_te, fraction_tm=fraction_tm, ) mode_solver.modes = r["modes"] mode_solver.n_effs = r["n_effs"] if plot: mode_solver.plot_modes( filepath, fields_to_write=fields_to_write, logscale=logscale ) mode_solver.results = r return mode_solver
if __name__ == "__main__": import matplotlib.pylab as plt test_mode_solver_full_vectorial_multi_clad(overwrite=True) # test_mode_solver_full_vectorial(overwrite=True) # test_mode_solver_full_vectorial(overwrite=False) plt.show()