from typing import Dict, List, Tuple, Union
import matplotlib.pylab as plt
import numpy as np
import pytest
import tqdm
from numpy import float64, ndarray
from modes._structure import RidgeWaveguide
from modes.mode_solver_full import mode_solver_full
from modes.waveguide import waveguide
[docs]def sweep_waveguide(
waveguides: List[RidgeWaveguide],
sweep_param_list: ndarray,
plot: bool = True,
x_label: str = "waveguide width (um)",
fraction_mode_list: List[int] = [],
overwrite: bool = False,
n_modes: int = 6,
legend: None = None,
) -> Dict[
str,
Union[
List[ndarray],
List[List[Tuple[str, float64]]],
List[List[float64]],
List[List[List[Union[str, float]]]],
List[List[float]],
],
]:
"""
Find the modes of many waveguides.
Args:
waveguides (list): A list of `waveguides` to find the modes of.
sweep_param_list (list): parameter that we sweep (for plotting)
plot (bool): `True` generates plots
x_label (str): x-axis text to display in the plot.
fraction_mode_list (list): A list of mode indices of the modes
that should be included in the TE/TM mode fraction plot.
If the list is empty, all modes will be included. The list
is empty by default.
overwrite: when True forces to resimulate the structure
n_modes: number of modes to compute
legend:
Returns:
list: A list of the effective indices found for each structure.
.. plot::
:include-source:
import numpy as np
import modes as ms
widths = np.arange(0.5, 2.0, 0.5)
wgs = [ms.waveguide(width=width) for width in widths]
r = ms.sweep_waveguide(
wgs, widths, x_label="waveguide width", fraction_mode_list=[1, 2],
)
print(r["n_effs"][0])
"""
n_effs = []
mode_types: List[Tuple[str, float64]] = []
fractions_te = []
fractions_tm = []
for wg in tqdm.tqdm(waveguides, ncols=70):
ms = mode_solver_full(wg=wg, overwrite=overwrite, n_modes=n_modes, plot=False)
n_effs.append(np.real(ms.n_effs))
mode_types.append(ms.mode_types)
fractions_te.append(ms.fraction_te)
fractions_tm.append(ms.fraction_tm)
results = dict(
n_effs=n_effs,
mode_types=mode_types,
fractions_te=fractions_te,
fractions_tm=fractions_tm,
)
# suffix = "_".join([f"{int(i*1e3)}" for i in sweep_param_list])
suffix = "_".join([f"{int(sweep_param_list[i]*1e3)}" for i in [0, -1]])
suffix += f"_{len(sweep_param_list)}"
filename = ms._modes_directory / f"{ms.name}_{suffix}.dat"
filename_neffs = filename.parent / f"{filename.stem}_neffs.dat"
filename_mode_types = filename.parent / f"{filename.stem}_mode_types.dat"
filename_fraction_te = filename.parent / f"{filename.stem}_fraction_te.dat"
filename_fraction_tm = filename.parent / f"{filename.stem}_fraction_tm.dat"
# filename_neffs = ms._modes_directory / f"{ms.name}_{suffix}_neffs.dat"
# filename_mode_types = ms._modes_directory / f"{ms.name}_{suffix}_mode_types.dat"
# filename_fraction_te = ms._modes_directory / f"{ms.name}_{suffix}_fraction_te.dat"
# filename_fraction_tm = ms._modes_directory / f"{ms.name}_{suffix}_fraction_tm.dat"
# if overwrite or not filename_neffs.exists():
ms._write_n_effs_to_file(n_effs, filename_neffs, sweep_param_list)
with open(filename_mode_types, "w") as fs:
header = ",".join(f"Mode{i}" for i in range(len(mode_types[0])))
fs.write(f"# {header} \n")
for mt in mode_types:
txt = ",".join([f"{pair[0]} {pair[1]}" for pair in mt])
fs.write(txt + "\n")
with open(filename_fraction_te, "w") as fs:
header = "fraction te"
fs.write("# param sweep," + header + "\n")
for param, fte in zip(sweep_param_list, fractions_te):
txt = "%.6f," % param
txt += ",".join("%.2f" % f for f in fte)
fs.write(txt + "\n")
with open(filename_fraction_tm, "w") as fs:
header = "fraction tm"
fs.write("# param sweep," + header + "\n")
for param, ftm in zip(sweep_param_list, fractions_tm):
txt = "%.6f," % param
txt += ",".join("%.2f" % f for f in ftm)
fs.write(txt + "\n")
suffix = f"@ {waveguides[0]._wl}"
if plot:
plt.figure()
title = f"$n_{{eff}}$ {suffix}"
y_label = "$n_{eff}$"
ms._plot_n_effs(
filename_neffs,
filename_fraction_te,
x_label,
y_label,
title,
)
if legend:
plt.legend(legend)
plt.figure()
title = f"TE Fraction {suffix}"
ms._plot_fraction(
filename_fraction_te,
x_label,
"TE Fraction [%]",
title,
fraction_mode_list,
)
if legend:
plt.legend(legend)
plt.figure()
title = f"TM Fraction {suffix}"
ms._plot_fraction(
filename_fraction_tm,
x_label,
"TM Fraction [%]",
title,
fraction_mode_list,
)
if legend:
plt.legend(legend)
return results
@pytest.mark.parametrize("overwrite", [True, False])
def test_sweep(overwrite: bool) -> None:
widths = np.arange(0.5, 2.0, 0.5)
wgs = [waveguide(width=width) for width in widths]
r = sweep_waveguide(
wgs,
widths,
n_modes=2,
fraction_mode_list=[1, 2],
overwrite=overwrite,
)
print(r["n_effs"][0])
assert np.isclose(
r["n_effs"][0], np.array([2.47170794, 1.81238363]), atol=0.1
).all()
assert r
@pytest.mark.parametrize("overwrite", [True, False])
def test_sweep2(overwrite: bool) -> None:
widths = np.arange(0.3, 1.0, 0.5)
wgs = [waveguide(width=width) for width in widths]
r = sweep_waveguide(
wgs,
widths,
n_modes=2,
fraction_mode_list=[1, 2],
overwrite=overwrite,
)
print(r["n_effs"][0])
assert np.isclose(
r["n_effs"][0], np.array([1.84891783, 1.60477969]), atol=0.1
).all()
assert r
if __name__ == "__main__":
test_sweep2(overwrite=False)
plt.show()