60 n_radial_max: int = 2, k_max: int = 2) -> List[ModeComparison]:
61 """All analytic (alpha, k) candidate frequencies for wavenumber ``m``, trivial mode excluded."""
64 for k
in range(k_max + 1):
65 if alpha == 0.0
and k == 0:
67 f = (c / (2.0 * np.pi)) * np.sqrt((alpha / R) ** 2 + (k * np.pi / L) ** 2)
68 out.append(
ModeComparison(m=m, alpha=float(alpha), k=k, f_analytic_hz=float(f), f_fem_hz=float(
"nan")))
69 out.sort(key=
lambda mc: mc.f_analytic_hz)
73def run_case(*, c: float, L: float, R: float, m: int, nx: int, nr: int,
74 n_radial_max: int = 2, k_max: int = 2, n_compare: int = 4) -> List[ModeComparison]:
75 """Run the FEM solve for wavenumber ``m`` and match the lowest ``n_compare`` modes
76 against the analytic candidates (both lists sorted ascending, matched pairwise).
79 sigma = (2.0 * np.pi * 0.5 * candidates[0].f_analytic_hz) ** 2
81 spec = synthetic_uniform_cylinder(L, R, nx, nr, c_sound=c)
82 freqs_hz, _ = solve_passive_modes(spec.mesh, spec.c, m, n_modes=n_compare + 2, sigma=sigma)
86 f_min_analytic = candidates[0].f_analytic_hz
87 freqs_hz = np.sort(freqs_hz[freqs_hz > 0.05 * f_min_analytic])[:n_compare]
89 for mc, f_fem
in zip(candidates, freqs_hz):
90 mc.f_fem_hz = float(f_fem)
List[ModeComparison] run_case(*, float c, float L, float R, int m, int nx, int nr, int n_radial_max=2, int k_max=2, int n_compare=4)