numerics 0.1.0
Loading...
Searching...
No Matches
pcg.hpp
Go to the documentation of this file.
1/// @file solvers/pcg.hpp
2/// @brief Preconditioned conjugate gradient.
3#pragma once
4
5#include "core/policy.hpp"
6#include "core/vector.hpp"
9#include "core/concepts.hpp"
10#include <cmath>
11#include <stdexcept>
12
13namespace num {
14
15template<class Op, class M>
16 requires SPDLinearOperator<Op, Vector, Vector> && Preconditioner<M>
17SolverResult pcg(const Op& A,
18 const M& M_op,
19 const Vector& b,
20 Vector& x,
21 real tol = 1e-10,
22 idx max_iter = 1000,
23 Backend backend = default_backend) {
24 const idx n = b.size();
25 if (A.rows() != n || A.cols() != n || M_op.rows() != n || M_op.cols() != n
26 || x.size() != n) {
27 throw std::invalid_argument("pcg: dimension mismatch");
28 }
29
30 Vector r(n), z(n), p(n), Ap(n);
31 A.apply(x, r);
32 for (idx i = 0; i < n; ++i) {
33 r[i] = b[i] - r[i];
34 }
35 M_op.apply(r, z);
36 p = z;
37
38 real rzold = dot(r, z, backend);
39 SolverResult result{0, norm(r, backend), false};
40
41 for (idx iter = 0; iter < max_iter; ++iter) {
42 result.iterations = iter + 1;
43 A.apply(p, Ap);
44
45 const real pAp = dot(p, Ap, backend);
46 if (std::abs(pAp) < real(1e-15)) {
47 break;
48 }
49
50 const real alpha = rzold / pAp;
51 axpy(alpha, p, x, backend);
52 axpy(-alpha, Ap, r, backend);
53
54 result.residual = norm(r, backend);
55 if (result.residual < tol) {
56 result.converged = true;
57 break;
58 }
59
60 M_op.apply(r, z);
61 const real rznew = dot(r, z, backend);
62 const real beta = rznew / rzold;
63 scale(p, beta, backend);
64 axpy(real(1), z, p, backend);
65 rzold = rznew;
66 }
67
68 return result;
69}
70
71} // namespace num
constexpr idx size() const noexcept
Definition vector.hpp:83
Storage and operator concepts for numerical routines.
Backend enum and default backend selection.
double real
Definition types.hpp:10
Backend
Definition policy.hpp:7
real beta(real a, real b)
B(a, b) – beta function.
Definition math.hpp:248
std::size_t idx
Definition types.hpp:11
void scale(Vector &v, real alpha, Backend b=default_backend)
Compute .
Definition vector.cpp:15
real dot(const Vector &x, const Vector &y, Backend b=default_backend)
Compute .
Definition vector.cpp:65
constexpr real e
Definition math.hpp:44
real norm(const Vector &x, Backend b=default_backend)
Compute .
Definition vector.cpp:83
SolverResult pcg(const Op &A, const M &M_op, const Vector &b, Vector &x, real tol=1e-10, idx max_iter=1000, Backend backend=default_backend)
Definition pcg.hpp:17
void axpy(real alpha, const Vector &x, Vector &y, Backend b=default_backend)
Compute .
Definition vector.cpp:44
constexpr Backend default_backend
Definition policy.hpp:53
Preconditioner concept and diagonal preconditioners.
Common result type shared by all iterative solvers.
idx iterations
Number of iterations performed.
Dense vector storage and operations.