Solvers#
This section summarizes the linear and nonlinear solver APIs in FluxFEM and how they are typically used in workflows.
Linear solves#
FluxFEM provides a lightweight LinearSolver wrapper that can solve either
dense arrays or FluxSparseMatrix objects, with optional Dirichlet handling.
Typical usage:
import fluxfem as ff
# assemble K and F (e.g., weak-form or tensor-based assembly)
solver = ff.LinearSolver(method="spsolve")
u, info = solver.solve(
K,
F,
dirichlet=(dir_dofs, dir_vals),
dirichlet_mode="condense", # or "enforce"
)
Common options:
method="spsolve": direct solve on CPU.method="cg": conjugate gradient (JAX-based).dirichlet_mode="condense": eliminate Dirichlet DOFs (smaller system).dirichlet_mode="enforce": enforce constraints in the full system.
Nonlinear solves (Newton)#
For nonlinear problems, FluxFEM uses a Newton loop with configurable tolerances, line search, and linear solver settings.
Example:
analysis = ff.NonlinearAnalysis(
space=space,
residual_form=ff.neo_hookean_residual_form,
params={"lam": lam, "mu": mu},
base_external_vector=F_ext,
dirichlet=(dir_dofs, None),
jacobian_pattern=ff.make_sparsity_pattern(space, with_idx=False),
dtype=jnp.float64,
)
newton_cfg = ff.NewtonLoopConfig(
tol=1e-6,
atol=1e-10,
maxiter=50,
line_search=False,
linear_solver="cg",
linear_preconditioner="jacobi",
linear_tol=None,
n_steps=1,
)
runner = ff.NewtonSolveRunner(analysis, newton_cfg)
u, history = runner.run(u0=jnp.zeros(space.n_dofs, dtype=jnp.float64))
Runner usage#
NewtonSolveRunner orchestrates load steps and keeps a history of iterations.
Use it when you need load stepping, convergence history, or callbacks.
def on_newton_step(cb):
# cb may include residual norms, iteration counters, and load step info.
pass
runner = ff.NewtonSolveRunner(analysis, newton_cfg)
u, history = runner.run(u0=u0, newton_callback=on_newton_step)
The returned history is important for judging whether the analysis is
actually converging (residual norms, iteration counts, and load-step progress).
It also provides a structured signal for future automation workflows, including
AI/LLM agents that monitor and adapt solver behavior.
Typical fields include residual norms, iteration counters, and per-step summaries. These are commonly used for early stopping, adaptive stepping, or logging/alerts.
Inputs overview#
NonlinearAnalysis expects the following core inputs:
Field |
Description |
|---|---|
|
|
|
Nonlinear residual kernel |
|
Material/physics parameters (dict-like or custom object). |
|
External force vector (optional). |
|
Dirichlet DOFs and values, e.g. |
|
Sparsity pattern (use |
|
Computation dtype (e.g., |
NewtonLoopConfig overview#
Key configuration fields:
Field |
Description |
|---|---|
|
Converges when the residual norm falls below |
|
Max Newton iterations per load step. |
|
Enable/disable line search. |
|
Backend for linear solves (e.g., |
|
Preconditioner for |
|
Optional tolerance override for linear solves. |
|
Number of load steps in the analysis. |
Choosing a linear solver#
spsolve: robust for small-to-medium problems on CPU.cg: scalable iterative solver; use preconditioners for better convergence.spdirect_solve_gpu: direct solver when running on GPU (when available).
Dirichlet handling#
Dirichlet constraints can be handled in two ways:
condense: removes constrained DOFs from the system (smaller, faster).
enforce: keeps the system size but overwrites rows/cols to impose constraints.
For large systems, condense is typically preferred.