Benchmark of the mode solver 1#
Reproducing [1], where the modes of a analytically solvable geometry are calculated. The error for all modes is calculated to be smaller than \(\pm 1 \cdot 10^{-8}\). We’ll show that we get pretty close, but will stop at a resonable resolution to keep the runtime sensible. Getting even higher accurancy will be left open for adaptive refinement. The results are presented here:
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
Cell In[1], line 43
40 for subdomain, e in epsilons.items():
41 epsilon[basis0.get_dofs(elements=subdomain)] = e
---> 43 modes = compute_modes(
44 basis0,
45 epsilon,
46 wavelength=1.5,
47 num_modes=1,
48 order=2,
49 metallic_boundaries=boundaries,
50 solver="slepc",
51 )
52 neff_values_femwell_slepc.append(np.real(modes[0].n_eff))
54 modes = compute_modes(
55 basis0,
56 epsilon,
(...) 61 solver="scipy",
62 )
File ~/miniconda3/lib/python3.13/site-packages/femwell/maxwell/waveguide.py:611, in compute_modes(basis_epsilon_r, epsilon_r, wavelength, mu_r, num_modes, order, metallic_boundaries, radius, n_guess, solver)
608 sigma = sigma = k0**2 * np.max(epsilon_r) * 1.1
610 if metallic_boundaries:
--> 611 lams, xs = solve(
612 *condense(
613 -A,
614 -B,
615 D=basis.get_dofs(None if metallic_boundaries is True else metallic_boundaries),
616 x=basis.zeros(dtype=complex),
617 ),
618 solver=solver(k=num_modes, sigma=sigma),
619 )
620 else:
621 lams, xs = solve(
622 -A,
623 -B,
624 solver=solver(k=num_modes, sigma=sigma),
625 )
File ~/miniconda3/lib/python3.13/site-packages/skfem/utils.py:268, in solve(A, b, x, I, solver, **kwargs)
266 logger.info("Solving linear system, shape={}.".format(A.shape))
267 if isinstance(b, spmatrix):
--> 268 out = solve_eigen(A, b, x, I, solver, **kwargs) # type: ignore
269 elif isinstance(b, ndarray):
270 out = solve_linear(A, b, x, I, solver, **kwargs) # type: ignore
File ~/miniconda3/lib/python3.13/site-packages/skfem/utils.py:211, in solve_eigen(A, M, x, I, solver, **kwargs)
208 solver = solver_eigen_scipy(**kwargs)
210 if x is not None and I is not None:
--> 211 L, X = solver(A, M, **kwargs)
212 y = np.tile(x.copy()[:, None], (1, X.shape[1]))
213 if isinstance(I, tuple):
File ~/miniconda3/lib/python3.13/site-packages/femwell/solver.py:93, in solver_eigen_slepc.<locals>.solver(K, M, **solve_time_kwargs)
92 def solver(K, M, **solve_time_kwargs):
---> 93 from petsc4py import PETSc
94 from slepc4py import SLEPc
96 which = {
97 "LM": SLEPc.EPS.Which.LARGEST_MAGNITUDE,
98 "SM": SLEPc.EPS.Which.SMALLEST_MAGNITUDE,
(...) 106 "ALL": SLEPc.EPS.Which.ALL,
107 }
ModuleNotFoundError: No module named 'petsc4py'
Bibliography#
[1]
G.R. Hadley. High-accuracy finite-difference equations for dielectric waveguide analysis II: dielectric corners. Journal of Lightwave Technology, 20(7):1219–1231, July 2002. URL: https://doi.org/10.1109/jlt.2002.800371, doi:10.1109/jlt.2002.800371.