49 std::optional<GmresErrorEstimates<R>>
errors = {};
57template <
class P,
class V>
59 {
p.apply(output, input) } -> std::same_as<void>;
66 template <
class V>
void apply(V& output, V
const& input) {
ops.copy(output, input); }
83 throw std::invalid_argument(
"GMRES requires a positive restart and finite nonnegative tolerances");
88 throw std::invalid_argument(
"GMRES tolerance is not representable at working precision");
89 return {relative, absolute};
104 auto zero = scalar_at_precision<S>(0,
p);
105 auto rzero = scalar_at_precision<R>(0,
p);
106 auto rone = scalar_at_precision<R>(1,
p);
107 if (g == zero)
return {rone, zero, f};
109 if (f == zero)
return {rzero,
uni20::conj(g) / ag, scalar_at_precision<S>(ag,
p)};
122template <RealOrComplex S,
class Ops,
class V> std::optional<make_real_t<S>>
norm(Ops& ops, V
const& v,
Precision p)
127 R
value = scalar_at_precision<R>(ops.norm(v),
p);
133 S
square = scalar_at_precision<S>(ops.inner_product(v, v),
p);
142 auto one = scalar_at_precision<R>(1,
p);
143 R inverse = one / length;
145 ops.scal(v, scalar_at_precision<S>(inverse,
p));
150 S factor = scalar_at_precision<S>(one /
math::sqrt(length),
p);
156template <Real R>
bool reached(R
const& residual, R
const& rhs, R
const& relative, R
const& absolute)
159 return residual <= absolute || (relative > 0 && rhs > 0 && residual / rhs <= relative);
178template <RealOrComplex S,
class Ops,
class Op,
class P,
class V>
179 requires KrylovVectorOps<Ops, V, S> && KrylovOperator<Op, V> && KrylovPreconditioner<P, V>
184 require_precision<S>(precision);
186 std::size_t n = ops.problem_dimension();
187 if (ops.vector_dimension(x) != n || ops.vector_dimension(b) != n)
188 throw std::invalid_argument(
"GMRES vectors do not belong to the operator space");
191 auto zero = scalar_at_precision<S>(0, precision);
192 auto one = scalar_at_precision<S>(1, precision);
194 auto dgks =
math::sqrt(scalar_at_precision<R>(2, precision));
196 auto norm = [&](V
const& v) {
return gmres_detail::norm<S>(ops, v, precision); };
198 info.status = status;
201 auto bnorm =
norm(b);
202 auto xnorm =
norm(x);
204 auto diagnose = [&](R
const& residual_norm, R
const& solution_norm) {
210 auto rhs = ops.allocate_like(b);
212 auto residual = ops.allocate_like(b);
213 auto work = ops.allocate_like(b);
214 auto evaluate = [&](V
const& candidate) {
215 ++info.operator_applications;
216 op.matvec(work, candidate);
217 ops.copy(residual, rhs);
218 ops.axpy(residual, -one, work);
219 return norm(residual);
221 auto beta = evaluate(x);
223 diagnose(*
beta, *xnorm);
226 if (options.max_iterations == 0)
return info;
228 auto z = ops.allocate_like(b);
229 auto delta = ops.allocate_like(b);
230 auto candidate = ops.allocate_like(b);
231 std::size_t m = std::min({options.restart, options.max_iterations, n});
232 std::vector<S> h((m + 1) * m, zero), g(m + 1, zero);
233 auto H = [&](std::size_t
row, std::size_t col) -> S& {
return h[col * (m + 1) +
row]; };
234 while (info.iterations < options.max_iterations)
237 std::vector<V> basis;
238 basis.reserve(m + 1);
239 basis.push_back(ops.allocate_like(b));
240 ops.copy(basis.back(), residual);
241 gmres_detail::normalize<S>(ops, basis.back(), *
beta, precision);
242 std::fill(h.begin(), h.end(), zero);
243 std::fill(g.begin(), g.end(), zero);
244 g[0] = scalar_at_precision<S>(*
beta, precision);
245 std::vector<gmres_detail::Rotation<S>> rotations;
246 rotations.reserve(m);
247 std::size_t columns = 0;
249 for (std::size_t j = 0; j < m && info.iterations < options.max_iterations; ++j)
252 ++info.preconditioner_applications;
253 preconditioner.apply(z, basis[j]);
255 ++info.operator_applications;
257 auto before =
norm(work);
259 auto orthogonalize = [&] {
260 for (std::size_t k = 0; k <= j; ++k)
262 S
dot = scalar_at_precision<S>(ops.inner_product(basis[k], work), precision);
265 ops.axpy(work, -
dot, basis[k]);
270 auto after =
norm(work);
272 if (*after < *before / dgks)
278 H(j + 1, j) = scalar_at_precision<S>(*after, precision);
280 if (!
breakdown && j + 1 < m && info.iterations < options.max_iterations)
282 basis.push_back(ops.allocate_like(b));
283 ops.copy(basis.back(), work);
284 gmres_detail::normalize<S>(ops, basis.back(), *after, precision);
286 for (std::size_t k = 0; k < j; ++k)
291 if (rotation.r == zero)
296 H(j, j) = rotation.r;
298 rotations.push_back(rotation);
304 std::vector<S> y(g.begin(), g.begin() + columns);
305 for (std::size_t
row = columns;
row-- > 0;)
307 for (std::size_t col =
row + 1; col < columns; ++col)
308 y[
row] -= H(
row, col) * y[col];
313 for (std::size_t j = 0; j < columns; ++j)
314 ops.axpy(delta, y[j], basis[j]);
315 ++info.preconditioner_applications;
316 preconditioner.apply(z, delta);
318 ops.copy(candidate, x);
319 ops.axpy(candidate, one, z);
320 auto candidate_norm =
norm(candidate);
322 ops.copy(delta, candidate);
323 ops.axpy(delta, -one, x);
324 auto change =
norm(delta);
326 beta = evaluate(candidate);
328 ops.copy(x, candidate);
329 diagnose(*
beta, *candidate_norm);
338template <RealOrComplex S,
class Ops,
class Op,
class V>
339 requires KrylovVectorOps<Ops, V, S> && KrylovOperator<Op, V>
343 return gmres_with_info<S>(ops, op, identity, x, b, options,
p);
347template <RealOrComplex S,
class Ops,
class Op,
class P,
class V>
348 requires(!has_runtime_precision_v<S>) && KrylovVectorOps<Ops, V, S> && KrylovOperator<Op, V> &&
349 KrylovPreconditioner<P, V>
353 return gmres_with_info<S>(ops, op, preconditioner, x, b, options, native_precision<S>());
357template <RealOrComplex S,
class Ops,
class Op,
class V>
358 requires(!has_runtime_precision_v<S>) && KrylovVectorOps<Ops, V, S> && KrylovOperator<Op, V>
361 return gmres_with_info<S>(ops, op, x, b, options, native_precision<S>());
AsyncTask square(ReadBuffer< int > in, WriteBuffer< int > out)
Definition async_tbb_reduction_example.cpp:39
Exact arithmetic or an explicit binary working precision.
Definition core/precision.hpp:13
constexpr bit_count_type bit_count() const
Number of binary significand bits.
Definition core/precision.hpp:43
Optional customization point for direct vector norms.
Definition matrix_free.hpp:437
Fixed linear inverse-preconditioner application, output <- M^{-1} input.
Definition gmres.hpp:58
locale_t value
Definition data_table.cpp:49
Optional Euclidean-norm error diagnostics for matrix-free solves.
uni20::complex< T > conj(detail::standard_complex< T > x)
Returns the complex conjugate for complex-valued scalars.
Definition math.hpp:70
typename make_real< T >::type make_real_t
Alias for the underlying real-valued type of T.
Definition scalar_traits.hpp:168
constexpr bool isfinite(I const &x) noexcept
Returns whether an integer scalar is finite.
Definition math.hpp:121
bool reached(R const &residual, R const &rhs, R const &relative, R const &absolute)
Definition gmres.hpp:156
std::optional< GmresErrorEstimates< R > > error_estimates(GmresResidual< R > const &residual, GmresOperatorEstimates< R > const &properties)
Definition gmres_diagnostics.hpp:132
void rotate(Rotation< S > const &rotation, S &x, S &y)
Definition gmres.hpp:115
Rotation< S > rotation(S const &f, S const &g, Precision p)
Definition gmres.hpp:101
void normalize(Ops &ops, V &v, make_real_t< S > const &length, Precision p)
Definition gmres.hpp:139
Tolerances< R > tolerances(GmresOptions< R > const &options, Precision precision)
Definition gmres.hpp:77
GmresOperatorEstimates< R > operator_estimates_at_precision(GmresOperatorEstimates< R > const &input, Precision p)
Definition gmres_diagnostics.hpp:73
std::optional< make_real_t< S > > norm(Ops &ops, V const &v, Precision p)
Definition gmres.hpp:122
DiagnosticMagnitude< R > magnitude(R const &value)
Definition gmres_diagnostics.hpp:98
Definition block_tensor_vector.hpp:23
GmresStatus
Numerical termination of a matrix-free linear solve.
Definition gmres.hpp:16
Scalar dot(std::span< Scalar const > x, std::span< Scalar const > y)
Compute a BLAS-style real dot product.
Definition dense_linalg.hpp:240
GmresInfo< make_real_t< S > > gmres_with_info(Ops &ops, Op &op, P &preconditioner, V &x, V const &b, GmresOptions< make_real_t< S > > const &options, Precision precision)
Solve A*x=b with restarted GMRES and a fixed right preconditioner.
Definition gmres.hpp:180
constexpr detail::scalar_math::sqrt_fn sqrt
Square root; exact inputs requiring approximation need an explicit finite precision.
Definition math.hpp:461
constexpr detail::scalar_math::abs_fn abs
Absolute value or complex magnitude, preserving the selected scalar implementation.
Definition math.hpp:459
constexpr detail::scalar_math::real_fn real
Read the real component by value; real and integral scalars retain their type.
Definition math.hpp:671
constexpr detail::scalar_math::hypot_fn hypot
Euclidean length with scalar-specific overflow and underflow handling.
Definition math.hpp:507
Definition data_table.cpp:8
mpreal norm(mpcomplex const &z)
Definition mpcomplex.hpp:494
mpreal epsilon(Precision precision)
Spacing above one for a specified binary working precision.
Definition mpreal.hpp:805
mpreal beta(mpreal const &a, mpreal const &x)
Real Beta function; positive rational/integer pairs retain exact values.
Definition mpreal_special.hpp:164
Recoverable solve outcome; counters include attempted operator calls.
Definition gmres.hpp:42
std::optional< GmresResidual< R > > residual
Definition gmres.hpp:48
GmresStatus status
Definition gmres.hpp:43
std::size_t iterations
Definition gmres.hpp:44
std::size_t operator_applications
Definition gmres.hpp:46
std::size_t preconditioner_applications
Definition gmres.hpp:47
std::size_t cycles
Definition gmres.hpp:45
std::optional< GmresErrorEstimates< R > > errors
Definition gmres.hpp:49
bool succeeded() const noexcept
Definition gmres.hpp:50
Optional properties of the original operator in the vector space's 2-norm.
Definition gmres_diagnostics.hpp:38
Residual stopping policy and storage/iteration limits.
Definition gmres.hpp:27
std::size_t max_iterations
Definition gmres.hpp:32
std::optional< R > relative_tolerance
Absent means sqrt(epsilon) at the GMRES working precision.
Definition gmres.hpp:29
std::size_t restart
Definition gmres.hpp:31
GmresOperatorEstimates< R > operator_estimates
Definition gmres.hpp:33
R absolute_tolerance
Definition gmres.hpp:30
Recomputed Euclidean norms for the published iterate.
Definition gmres_diagnostics.hpp:46
Identity preconditioner using the supplied vector copy operation.
Definition gmres.hpp:64
void apply(V &output, V const &input)
Definition gmres.hpp:66
Ops & ops
Definition gmres.hpp:65
S s
Definition gmres.hpp:95
S r
Definition gmres.hpp:96
make_real_t< S > c
Definition gmres.hpp:94
R absolute
Definition gmres.hpp:74
R relative
Definition gmres.hpp:73
Project-level numeric limits customization point.
Definition numeric_limits.hpp:16