Solvers

The solver section configures the nonlinear solve, the linear solve nested inside it, and the convergence criteria. It is required for quasi static and newmark, and ignored entirely by central difference, which is explicit.

solver:
  type: newton
  linear solver:
    type: cg
    preconditioner:
      type: jacobi
  termination:
    converge when any:
      - absolute residual: 1.0e-08
      - relative residual: 1.0e-12
    fail when any:
      - maximum iterations: 16

Nonlinear solvers

typeAliasesNeeds a linear solver?GPUDescription
newtonnewton raphson, newton-raphson, hessian minimizeryesvia linear solverNewton–Raphson. Quadratic convergence near the solution. The default choice.
nonlinear cgnlcg, conjugate gradientnoyesNonlinear CG. Matrix-free, linear convergence.
steepest descentgradient descent, sdnoyesPreconditioned steepest descent. Matrix-free, slowest, most robust.

type is required; there is no default. hessian minimizer is accepted for Norma compatibility and builds a plain NewtonSolver.

Anything else aborts with the list above. In particular lbfgs is not a nonlinear solver type — it is a linear solver, selected with solver.linear solver.type: lbfgs. That mistake used to fall through to Newton silently, producing a run that looked fine but was not the algorithm requested:

ERROR: Unknown solver.type = "lbfgs". Supported: "newton" (aliases ...).
       L-BFGS is a linear solver: set solver.linear solver.type = "lbfgs".

For newton, a linear solver sub-section is required. For the two matrix-free solvers it is optional and defaults to type: none.

Keys common to all nonlinear solvers

KeyDefaultDescription
minimum iterations0Lower bound on iterations.
maximum iterations20Upper bound. Overridden by a maximum iterations test in termination if one is present.
absolute tolerance1e-10Used only when termination is absent.
relative tolerance1e-14Used only when termination is absent.
use line searchtrueArmijo backtracking on ½‖R‖². Applies to newton only.
line search backtrack factor0.5Step reduction per backtrack.
line search decrease factor1e-4Armijo sufficient-decrease parameter.
line search maximum iterations10Maximum backtracking steps.
Line search defaults to ON

At large Δt or load increments the predictor can take element-inverting full steps; Armijo backtracking guards against that. It costs roughly one extra residual evaluation per iteration when the full step is already good (α = 1 is accepted immediately). Set use line search: false to disable.

use line search reaches newton only. NLCG and steepest descent always run their own line search, but they do honour the three line search * tuning keys.

Nonlinear CG only

KeyDefaultDescription
orthogonality tolerance0.5Restart when consecutive gradients lose orthogonality.
restart interval0Force a restart every N iterations. 0 disables.
preconditionernonetype: jacobi (the default when the section is present) or type: none.

Steepest descent accepts preconditioner with the same meaning. Jacobi is the only preconditioner implemented at this level; asking for anything else (chebyshev, ic, amg) is a hard error rather than silently running Jacobi.

Termination criteria

Carina accepts three syntaxes. Prefer the first.

Preferred: converge when / fail when

  termination:
    converge when any:
      - absolute residual: 1.0e-08
      - relative residual: 1.0e-12
    fail when any:
      - maximum iterations: 16
      - divergence: 1.0e6

Four block keys are recognised, each taking a list:

Block keyCombines with
converge when anyOR
converge when allAND
fail when anyOR
fail when allAND

Each list item is a single-key mapping of test name: value. Groups nest via any: / all: inside a list:

  termination:
    converge when all:
      - minimum iterations: 2
      - any:
          - absolute residual: 1.0e-08
          - relative residual: 1.0e-12

Legacy: typed list

Still supported. Each entry carries an explicit type, with the value under tolerance, value, threshold, or window depending on the test, and combo/tests for nesting:

  termination:
    - type: combo
      combo: and
      tests:
        - type: absolute residual
          tolerance: 1.0e-06
        - type: relative update
          tolerance: 1.0e-12
    - type: maximum iterations
      value: 16

combo must be and or or; the default when it is omitted is or. Any other value is an error — it previously fell through to or, which inverted the meaning of the group without saying so.

Oldest: flat tolerances

If termination is absent entirely, Carina builds OR(absolute residual, relative residual, finite value) from the flat absolute tolerance (default 1e-10) and relative tolerance (default 1e-14) keys.

Available tests

Test nameAliasesValue meansSignals
absolute residualabs_residualtoleranceConverged when ‖R‖ < tol
relative residualrel_residualtoleranceConverged when ‖R‖/‖R₀‖ < tol
absolute updateabs_updatetoleranceConverged when ‖ΔU‖ < tol
relative updaterel_updatetoleranceConverged when ‖ΔU‖/‖U‖ < tol
maximum iterationsmax iterationsiteration countFailed when iter ≥ value
minimum iterationsmin iterationsiteration countConverged when iter ≥ value
finite valuenan check(ignored)Failed when ‖R‖ is not finite
divergencethresholdFailed when ‖R‖ > threshold·‖R₀‖
stagnationwindowFailed on insufficient residual reduction

Points worth knowing:

  • minimum iterations is a convergence test, not a floor. It reports Converged once the iteration count is reached. Placed in a converge when any block it will force convergence on that iteration. It is only meaningful inside an all group, where it prevents premature convergence.
  • Relative tests normalise differently. relative residual divides by the initial residual ‖R₀‖; relative update divides by the current solution norm ‖U‖. Each is inert while its denominator is zero — a relative update test cannot converge on the first iteration from a zero initial guess.
  • divergence compares against ‖R₀‖, not the previous iterate, so it detects net growth from the start rather than a single bad step.
  • stagnation uses its value twice: as the lookback distance and as the number of consecutive stagnant iterations required to fail. With the default window of 5 it needs at least 11 iterations before it can trigger. Its internal ratio floor is 0.95 — i.e. failure when ‖Rk‖/‖R{k−window}‖ > 0.95 — settable only through the legacy syntax's tolerance key.
  • A finite value test is appended automatically to every termination tree, in all three syntaxes. You do not need to add one.
  • maximum iterations in the tree wins. If the tree contains a maximum iterations test, its value replaces the flat maximum iterations key as the solver loop bound.
  • In an OR group, Converged beats Failed. If one sub-test converges while another fails on the same iteration, the result is Converged. An AND group short-circuits on the first Failed.

Linear solvers

Configured under solver.linear solver.

typeAliasesCPUGPUDescription
directyesnoSparse LU. Robust, no tuning.
iterativecg, krylov, minres, conjugate gradientyesyesConjugate gradient. All aliases produce CG — the stiffness is SPD.
lbfgsyesyesL-BFGS quasi-Newton. Matrix-free.
noneyesyesNo linear solve; for NLCG / steepest descent.

Selecting direct on a GPU backend is a hard error:

solver.linear_solver.type = "direct" is CPU-only.

Iterative keys

KeyDefaultDescription
maximum iterations1000CG iteration cap.
tolerance1e-8Relative residual tolerance.
preconditionernoneSee below.

L-BFGS keys

KeyDefaultDescription
history size10Stored gradient pairs. More is a better inverse-Hessian approximation at higher memory cost.

The L-BFGS path always builds a Jacobi preconditioner regardless of any preconditioner sub-section.

L-BFGS does not work for quasi-static

Use it for implicit dynamics only. On quasi-static problems it stalls roughly seven orders short of tolerance and the step fails — on CPU and GPU alike, so this is not a device limitation and no amount of history size fixes it.

L-BFGS models the inverse tangent from its last few secant pairs. Implicit dynamics adds the mass shift c_M = 1/(βΔt²), which at small Δt leaves the effective operator strongly diagonally dominant and easy to model at low rank — there L-BFGS is the fastest option Carina has on GPU. Quasi-static has no such term: the same system takes 787 AMG iterations to solve, and a rank-10 model cannot represent it. Use cg + amg for quasi-static.

`assembled` defaults from the backend

assembled defaults to true on CPU and false on GPU. Setting assembled: false on the CPU forces the matrix-free operator path (the same operators the GPU runs); assembled: true on a GPU backend is a hard error — there is no device sparse matrix to assemble.

Preconditioners

Configured under solver.linear solver.preconditioner.

typeAliasesCPUGPUCost per iterationDescription
jacobiyesyesone vector scaleDiagonal scaling. Cheap, weak, always available.
icincomplete cholesky, ildl, incomplete ldltyesnoone triangular solveIncomplete LDLᵀ. Strong for ill-conditioned systems.
chebyshevchebyshev polynomialyesyesk matvecsPolynomial preconditioner; needs only matvecs, so it works on GPU.
amgalgebraic multigrid, multigridyesyesone V-cycleSmoothed-aggregation AMG with rigid-body-mode near-nullspace. On GPU the hierarchy is built on the host and the V-cycle applies on the device.
(omitted)yesyesnoneNo preconditioning.

Chebyshev keys

KeyDefaultDescription
degree5Polynomial degree. Higher is stronger but costs degree matvecs per iteration.

AMG

  linear solver:
    type: cg
    tolerance: 1.0e-8
    maximum iterations: 500
    preconditioner:
      type: amg

AMG is the only preconditioner whose CG iteration count is nearly independent of the conditioning that defeats Jacobi — on a 530k-DOF torsion problem it holds 5–17 CG iterations across a range of Δt where Jacobi grows from 30 to

It runs on both CPU and GPU. On GPU the hierarchy is built on the host (the sparse pattern lives there anyway) and converted to device CSR; the V(2,2)-cycle then applies entirely on the device through KernelAbstractions kernels, with the fine level smoothed through the matrix-free stiffness action so the fine matrix is never formed on the device. It is the fastest quasi-static option Carina has — see benchmark_report.md.

Two behaviours worth knowing. The near-nullspace (six rigid-body modes) is rebuilt from the current nodal coordinates X + u at every hierarchy build, not frozen at the reference configuration — a frozen reference nullspace degrades badly once the body rotates substantially. And the hierarchy setup is expensive (seconds at 500k DOF), so it is lagged: built once, then rebuilt only when the effective-mass coefficient changes (a Δt change) or when CG iteration growth flags it as stale.

AMG targets SPD tangents — quasi-static and moderate-Δt dynamics. At very large Δt on violently dynamic problems the Newmark predictor can overshoot into near-inverted configurations whose tangent is indefinite, which breaks CG regardless of preconditioner; explicit integration is the right tool there.

An unrecognised type is a hard error listing the supported values:

Unknown preconditioner.type = "jacobbi". Supported: "jacobi", "ic" (aliases
"incomplete cholesky", "ildl", "incomplete ldlt"), "chebyshev", "amg"
(aliases "algebraic multigrid", "multigrid"), "none".

Omitting the preconditioner section entirely, or writing type: none, means no preconditioning — that remains a valid, unremarkable choice.

Choosing a combination

Integrator and nonlinear solver

NewtonNonlinear CGSteepest descent
Quasi-staticrecommendedokfallback
Newmarkrecommendedokfallback
Central differencen/a — explicitn/an/a

Newton, by device

directCGCG + JacobiCG + ICCG + ChebyshevCG + AMGL-BFGS
CPUbest (small–medium)weakokgoodokbest (large)dynamics only*
GPUunavailableweakgoodunavailableokbestdynamics only*

* L-BFGS is the fastest option for implicit dynamics on GPU, but fails on quasi-static on either device — see the warning above.

Practical guidance:

  • CPU, small to mediumdirect. No tuning, always converges.
  • CPU, largecg + amg, or cg + ic as a simpler alternative.
  • GPU, quasi-staticcg + amg. It is the only GPU option that both converges its linear systems and beats the CPU direct solver at scale, and at 1.57M DOF it is the fastest option on either device.
  • GPU, implicit dynamics at small Δtcg + jacobi. The mass term conditions the system, so AMG's iteration reduction does not repay its per-application cost; see benchmark_report.md.
  • Never run plain cg with no preconditioner on a real mesh. It is valid and very slow.

Combinations that fail or mislead

CombinationResult
GPU + directHard error at startup.
GPU + ic preconditionerRequires an assembled matrix; unavailable.
central difference + any solver blockSilently ignored; explicit has no nonlinear solve.
NLCG / SD + linear solverIgnored by design; these are matrix-free.
Large Δt + j2 plasticityPath-dependent; large steps miss the yield surface. Keep line search on and steps small.