Pick a solver / preconditioner pair#
Use this page as a decision tree. The conceptual page Solver taxonomy explains the why; this page just says what to build.
Decide by matrix property#
Matrix property |
Solver |
Preconditioner |
Notes |
|---|---|---|---|
SPD, well-conditioned |
|
|
The textbook default. |
SPD, ill-conditioned, large |
|
Incomplete Cholesky: the factorization comes from |
|
SPD, very large, mesh-based |
|
|
AMG; pick the coarsening per level: |
SPD, singular (e.g. pure Neumann) |
|
any (wrapped in |
Converges to the minimum-norm solution; set |
Symmetric indefinite |
|
|
Three-term recurrence like CG, no breakdown on indefinite systems. |
Non-symmetric, general |
|
Restart with |
|
Non-symmetric, memory-tight |
|
|
Bounded memory unlike GMRES. |
Variable preconditioner (inner Krylov, adaptive AMG) |
|
(anything) |
FGMRES. |
Many small independent systems |
|
|
Fused-kernel batched path. |
Distributed (MPI) SPD |
|
|
Schwarz is the canonical distributed preconditioner. |
Sparse direct, one-off |
|
— |
Reorder first; see Tune a sparse direct solve. |
Sparse direct, NVIDIA GPU |
|
— |
Vendor-tuned with |
The shape of the construction#
Every iterative solver follows the same pattern:
auto solver_factory =
gko::solver::Cg<double>::build()
.with_criteria(gko::stop::max_iters(1000u),
gko::stop::relative_residual_norm(1e-8))
.with_preconditioner(
gko::preconditioner::Jacobi<double, int>::build())
.on(exec);
auto solver = solver_factory->generate(system_matrix);
solver->apply(b, x);
Swap Cg and Jacobi for the solver and preconditioner from the table.
The two factory parameters every iterative solver needs are
with_criteria (one or more stopping criteria; see
Configure stopping criteria) and
optionally with_preconditioner. Solvers without a preconditioner
factory default to identity (no preconditioning).
Worked example: ILU-preconditioned GMRES#
auto gmres = gko::solver::Gmres<double>::build()
.with_krylov_dim(50u)
.with_criteria(gko::stop::max_iters(1000u),
gko::stop::relative_residual_norm(1e-8))
.with_preconditioner(gko::preconditioner::Ilu<>::build())
.on(exec)
->generate(system_matrix);
gmres->apply(b, x);
Quick rules of thumb#
Start simple. Jacobi preconditioner first; upgrade only if convergence is too slow.
Direct solvers scale further than you might expect when paired with a fill-reducing reordering; see Tune a sparse direct solve.
GMRES restart length (
krylov_dim) is usually the most impactful knob on non-symmetric problems. Default is 100; smaller reduces memory at the cost of convergence speed.with_restart_ratio(r)adds a residual-based restart: a cycle ends once the residual drops tortimes its value at the start of the cycle (typically 1e-3 to 1e-1);krylov_dimthen acts as the memory cap.0(the default) keeps fixed-length restarts. See GMRES.Repeated setups with an unchanged sparsity pattern.
Multigridfactories withPgmlevels supportgenerate_reuse, which reuses the hierarchy data between setups; see Multigrid.Distributed solvers require an MPI build; see Use an existing MPI communicator.
Attention
The generate_reuse interface is experimental and may change.
See also
Solver taxonomy: the design rationale.
Preconditioner taxonomy: placement (left/right/split) and family details.