Configure stopping criteria#
Every iterative solver in Ginkgo takes one or more stopping criterion
factories through with_criteria(...). The solver stops when any
criterion fires (a logical OR). This page covers the common
combinations and the choices behind them.
The two most-used criteria#
auto factory = gko::solver::Cg<double>::build()
.with_criteria(gko::stop::max_iters(1000u),
gko::stop::relative_residual_norm(1e-8))
.on(exec); // stops at ||r|| <= 1e-8 ||b||
stop::Iteration: hard cap on iterations. Always include one; it guards against runaway loops if convergence never triggers.stop::ResidualNorm: stops when \(\lVert r_k \rVert \le \tau \, \beta\), where \(\tau\) isreduction_factorand the baseline \(\beta\) defaults to \(\lVert b \rVert\) (mode::rhs_norm).
These two together (a max-iter cap and a relative residual target) cover most use cases.
Criterion helpers#
The helper functions need neither an executor nor a value type, and can be passed straight to
with_criteria:
Helper |
Stops when |
|---|---|
|
after |
|
\(\lVert r \rVert \le \tau \, \lVert b \rVert\) |
|
\(\lVert r \rVert \le \tau \, \lVert r_0 \rVert\) |
|
\(\lVert r \rVert \le \tau\) |
|
the same baselines, using the solver’s implicit norm estimate |
|
the wall-clock time |
|
|
min_iters wraps the criteria that must wait for a minimum amount of work:
auto solver_factory =
gko::solver::Gmres<double>::build()
.with_criteria(
gko::stop::min_iters(10u, gko::stop::relative_residual_norm(1e-10)),
gko::stop::max_iters(1000u))
.on(exec);
The explicit builders (Iteration::build().with_max_iters(...), ResidualNorm<ValueType>::build()...)
produce the same criteria, and the examples below use them where the builder
parameters matter.
Relative vs absolute residual#
using BaseMode = gko::stop::mode;
gko::stop::ResidualNorm<double>::build()
.with_baseline(BaseMode::rhs_norm) // default: relative to ||b||
.with_reduction_factor(1e-8)
.on(exec);
gko::stop::ResidualNorm<double>::build()
.with_baseline(BaseMode::initial_resnorm) // relative to ||r_0||
.with_reduction_factor(1e-8)
.on(exec);
gko::stop::ResidualNorm<double>::build()
.with_baseline(BaseMode::absolute) // absolute: ||r_k|| <= tol
.with_reduction_factor(1e-8)
.on(exec);
reduction_factor is the value compared against the chosen
baseline:
|
Stops when |
|---|---|
|
\(\lVert r_k \rVert \le \tau \, \lVert b \rVert\) |
|
\(\lVert r_k \rVert \le \tau \, \lVert r_0 \rVert\) |
|
\(\lVert r_k \rVert \le \tau\) |
Pick rhs_norm when you want a tolerance that’s independent of the
initial guess. The initial_resnorm baseline is fixed once per solve
to \(\lVert b - A x_0 \rVert\), so when you chain warm-started solves
and feed each previous solution back as \(x_0\), \(\lVert r_0 \rVert\)
shrinks and the implied stopping target \(\tau \, \lVert r_0 \rVert\)
shrinks with it, sometimes well below what the solver can actually
reach in finite precision. rhs_norm fixes the baseline to
\(\lVert b \rVert\), which stays constant across the chain.
Implicit vs explicit residual#
ResidualNorm uses the residual norm the solver hands over, or computes the 2-norm of the
solver’s residual vector, which costs one global reduction per check.
ImplicitResidualNorm reads the squared-norm estimate the solver already maintains (CG, BiCG,
BiCGSTAB, CGS, FCG, MINRES, PipeCG), which saves that reduction.
gko::stop::ResidualNorm<double>::build()
.with_reduction_factor(1e-8)
.with_baseline(gko::stop::mode::initial_resnorm)
.on(exec);
gko::stop::ImplicitResidualNorm<double>::build()
.with_reduction_factor(1e-8)
.on(exec);
The estimate is updated by recurrence and can drift from the true residual on long runs, so
pair ImplicitResidualNorm with an iteration cap. Prefer ResidualNorm when the tolerance must
refer to the unpreconditioned residual. For MINRES and Multigrid, ResidualNorm computes
\(b - A x\) at each check, which costs an extra SpMV per check.
Combine criteria#
with_criteria takes any number of factories. Stop on whichever
fires first:
auto factory = gko::solver::Cg<double>::build()
.with_criteria(gko::stop::max_iters(500u),
gko::stop::relative_residual_norm(1e-10),
gko::stop::time_limit(std::chrono::seconds{30}))
.on(exec);
stop::Time (time_limit) ends the solve after a wall-clock budget, useful for
real-time / latency-bounded applications.
Custom criteria#
When the built-ins don’t fit, subclass gko::stop::Criterion and
provide a Factory. The check method receives the current iterate
and decides whether to stop. See include/ginkgo/core/stop/criterion.hpp
for the interface.
Common pitfalls#
One
with_criteriacall overrides previous ones. Pass all criteria in a singlewith_criteria(...)invocation, not multiple.Don’t forget the iteration cap. Without one, a non-convergent problem loops forever.
Preconditioner choice changes the residual. GMRES and BiCGSTAB use right preconditioning (\(A M^{-1} y = b\), recover \(x = M^{-1} y\)); CG and FCG apply \(M^{-1}\) to the residual. Regardless of placement,
ResidualNormalways refers to the unpreconditioned residual \(r = b - A x\), whileImplicitResidualNormuses the solver’s own estimate (a preconditioned quantity for CG-type solvers).
See also
Stopping criteria: the conceptual reference.
Log convergence: collect per-iteration data while solving.