Linear-solver backends ====================== Every analysis path that factors a sparse symmetric matrix — static (:math:`\mathbf{K}\mathbf{u} = \mathbf{f}`), modal (shift-invert :math:`(\mathbf{K} - \sigma \mathbf{M})`), cyclic (per-harmonic factor) — dispatches the factorisation through the **linear-solver registry** in :mod:`femorph_solver.solvers.linear`. The registry caches a preferred-order chain so a missing dependency cleanly falls through to the next backend without user code changes. Auto-chain dispatch order ------------------------- When the caller passes ``linear_solver="auto"`` (the default for every solver entry point), the registry walks the chain **Pardiso → CHOLMOD → MUMPS → UMFPACK → SuperLU** and uses the first backend whose Python bindings + native library are both importable at runtime. Backend-by-backend ------------------ * **Pardiso** (Intel MKL) — multi-threaded supernodal LDLᵀ. The fastest SPD path on x86_64 with MKL installed. Used via ``pypardiso``. Cite: Schenk, O. and Gärtner, K. (2004) *Solving unsymmetric sparse systems of linear equations with PARDISO*, Future Generation Computer Systems 20 (3), 475–487. * **CHOLMOD** (SuiteSparse) — supernodal Cholesky for SPD systems. The standard scientific-Python SPD backend ( ``scikit-sparse``); BSD-3. Cite: Chen, Y., Davis, T. A., Hager, W. W. and Rajamanickam, S. (2008) "Algorithm 887: CHOLMOD, supernodal sparse Cholesky factorization and update / downdate," *ACM TOMS* 35 (3), Article 22. * **MUMPS** (Multifrontal Massively Parallel Sparse) — multifrontal direct solver with a redistributable license (CeCILL-C). Useful as a Pardiso fallback when MKL isn't available; ships out-of-core for very large problems (TA-roadmap). Cite: Amestoy, P. R., Duff, I. S., L'Excellent, J.-Y. and Koster, J. (2001) "A fully asynchronous multifrontal solver using distributed dynamic scheduling," *SIAM J. Matrix Anal. Appl.* 23 (1), 15–41. * **UMFPACK** (SuiteSparse) — multifrontal LU for general sparse systems. Used via ``scikit-umfpack``; useful fallback for non-SPD systems (e.g., the future contact-coupled stiffness). * **SuperLU** — ``scipy``'s built-in LU solver. The guaranteed-available terminal fallback; pure-Python wheels carry it everywhere SciPy ships. Selecting an explicit backend ----------------------------- Every solver entry point that factors a matrix accepts a ``linear_solver`` keyword: .. code-block:: python res = model.solve(linear_solver="pardiso") modal = model.modal_solve(linear_solver="cholmod") If the named backend isn't installed, the call raises a clear ``RuntimeError`` listing the backends that **are** installed plus a ``pip install`` hint for the missing one. Inspecting the registry ----------------------- .. code-block:: python from femorph_solver.solvers.linear import list_linear_solvers print(list_linear_solvers()) # → {"pardiso": True, "cholmod": True, "mumps": False, # "umfpack": False, "superlu": True} Symmetric vs general -------------------- The current static / modal / cyclic paths assemble symmetric (usually positive-definite) matrices, so the SPD-capable backends (Pardiso, CHOLMOD) win on memory and FLOPs. General- purpose LU backends (UMFPACK, SuperLU) work too — they're a ~2× memory and FLOP overhead on a symmetric problem because they store both triangles + the L / U factor pair, but they're the right choice for non-symmetric problems (contact, large- displacement consistent stiffness — both roadmap). Implementation: :mod:`femorph_solver.solvers.linear` (registry + auto-chain) plus per-backend wrappers in :mod:`femorph_solver.solvers.linear._pardiso`, :mod:`femorph_solver.solvers.linear._cholmod`, etc. References ---------- * Davis, T. A. (2006) *Direct Methods for Sparse Linear Systems*, SIAM (foundational treatment of multifrontal / supernodal methods). * Saad, Y. (2003) *Iterative Methods for Sparse Linear Systems*, 2nd ed., SIAM, §3 (sparse direct solvers). * George, A. and Liu, J. W. H. (1981) *Computer Solution of Large Sparse Positive Definite Systems*, Prentice-Hall (envelope / Cholesky theory). (Per-backend citations live in each wrapper module's ``References`` block; the top-level cites here orient the user across the whole chain.)