Mathieu eigenvalue problem in an interval

Mathieu eigenvalue problem in an interval#

\[\begin{split} \mathbb{S} \begin{cases} \Omega = [0, L_x] \\ \textbf{k}=2\,\textbf{e}_x \\ u_{\text{D}}\vert_{\partial\Omega}=0 \\ u^{q=0}_{\text{e}, n}(x)=\sin(\sqrt{\lambda_{\text{e}, n}}x)~,~\lambda^{q=0}_{\text{e}, n}=\frac{n^2\pi^2}{L_x^2} \end{cases} \end{split}\]
import numpy as np
from dolfinx.fem import FunctionSpace

from lucifex.mesh import interval_mesh
from lucifex.fem import Constant
from lucifex.solver import evp, EigenvalueProblem, BoundaryConditions, OptionsSLEPc
from lucifex.viz import plot_line, create_cycler, save_figure
from lucifex.pde.eigen import mathieu


def create_solver(
    Lx: float,
    Nx: int,
    bcs: BoundaryConditions, 
    q: float,
    k: float,
    nev: int,
) -> EigenvalueProblem:
    mesh = interval_mesh(Lx, Nx)
    q = Constant(mesh, q)
    k = Constant(mesh, (k, ))

    fs = FunctionSpace(mesh, ('P', 1))
    slepc = OptionsSLEPc(
        eps_tol=1e-10,
        eps_target=0.0,
        eps_nev=nev,
        eps_ncv=50,
        eps_max_it=1000,
        eps_which='smallest_real',
    )
    u_solver = evp(mathieu, bcs, slepc)(fs, q, k)
    return u_solver


Lx = 1.0
Nx = 200
bcs = BoundaryConditions(
        ('dirichlet', lambda x: x[0], 0.0),
        ('dirichlet', lambda x: x[0] - Lx, 0.0),
    )
nev = 4
k = 2.0

q_axis = np.linspace(0, 20, num=10)
solvers = [create_solver(Lx, Nx, bcs, q, k, nev) for q in q_axis]
[s.solve() for s in solvers]
eigenvalues = [s.eigenvalues for s in solvers]
eigenreals = [[np.real(l) for l in lmbdas] for lmbdas in eigenvalues]
eigenreals_q0 = [(n * np.pi/ Lx) ** 2 for n in range(nev)]
lines = [
    (q_axis, [eigenreals[q_index][n] for q_index in range(len(q_axis))])
    for n in range(nev)
]
cyc = create_cycler(linestyle=['dashed'], marker=['o'], ms=[4], color=['black'])
slc = slice(1, None)
fig, ax = plot_line(
    lines[slc], 
    cyc=cyc,
    x_label='$q$', 
    y_label='$\lambda(q)$')
ax.set_xlim(q_axis[0], q_axis[-1])
ax.hlines(eigenreals_q0[slc], q_axis[0], q_axis[-1], color='black', lw=0.5, ls='-')
ax.set_yscale('log')
save_figure('eigenvalues', thumbnail=True)(fig)
../../_images/dd5e28ee78a4574589dd91802ef8e3acd79fda8c8cf990ee3fdb8ef79ec2ab42.png