numerics 0.1.0
Loading...
Searching...
No Matches
cg.hpp
Go to the documentation of this file.
1/// @file cg.hpp
2/// @brief Conjugate gradient solvers.
3///
4/// Solves \f$Ax=b\f$ for symmetric positive definite \f$A\f$ using
5/// \f$\mathcal{K}_k(A,r_0)=\mathrm{span}\{r_0,Ar_0,\ldots,A^{k-1}r_0\}\f$.
6#pragma once
7#include "core/matrix.hpp"
8#include "core/policy.hpp"
9#include "core/vector.hpp"
12#include "core/concepts.hpp"
13#include <cmath>
14#include <stdexcept>
15
16namespace num {
17
18SolverResult cg(const Matrix& A,
19 const Vector& b,
20 Vector& x,
21 real tol = 1e-10,
22 idx max_iter = 1000,
23 Backend backend = default_backend);
24
26 const Vector& b,
27 Vector& x,
28 real tol = 1e-10,
29 idx max_iter = 1000,
30 Backend backend = default_backend) {
31 return cg(A.base(), b, x, tol, max_iter, backend);
32}
33
34namespace detail {
35
36template<class Op>
37 requires LinearOperator<Op, Vector, Vector>
39 const Vector& b,
40 Vector& x,
41 real tol,
42 idx max_iter,
43 Backend backend) {
44 const idx n = b.size();
45 if (A.rows() != n || A.cols() != n || x.size() != n) {
46 throw std::invalid_argument("Dimension mismatch in operator CG solver");
47 }
48
49 Vector r(n), p(n), Ap(n);
50 A.apply(x, r);
51 for (idx i = 0; i < n; ++i) {
52 r[i] = b[i] - r[i];
53 p[i] = r[i];
54 }
55
56 real rsold = dot(r, r, backend);
57 SolverResult result{0, std::sqrt(rsold), false};
58
59 for (idx iter = 0; iter < max_iter; ++iter) {
60 result.iterations = iter + 1;
61 A.apply(p, Ap);
62
63 const real pAp = dot(p, Ap, backend);
64 if (std::abs(pAp) < real(1e-15)) {
65 break;
66 }
67 const real alpha = rsold / pAp;
68
69 axpy(alpha, p, x, backend);
70 axpy(-alpha, Ap, r, backend);
71
72 const real rsnew = dot(r, r, backend);
73 result.residual = std::sqrt(rsnew);
74 if (result.residual < tol) {
75 result.converged = true;
76 break;
77 }
78
79 const real beta = rsnew / rsold;
80 scale(p, beta, backend);
81 axpy(real(1), r, p, backend);
82 rsold = rsnew;
83 }
84 return result;
85}
86
87} // namespace detail
88
89/// @brief Operator CG for a declared SPD operator.
90template<class Op>
91 requires SPDLinearOperator<Op, Vector, Vector>
92SolverResult cg(const Op& A,
93 const Vector& b,
94 Vector& x,
95 real tol = 1e-10,
96 idx max_iter = 1000,
97 Backend backend = default_backend) {
98 return detail::cg_operator_impl(A, b, x, tol, max_iter, backend);
99}
100
101} // namespace num
constexpr idx size() const noexcept
Definition vector.hpp:83
const Mat & base() const noexcept
Storage and operator concepts for numerical routines.
Backend enum and default backend selection.
Dense row-major matrix templated over scalar type T.
Declared mathematical properties for stored matrices.
SolverResult cg_operator_impl(const Op &A, const Vector &b, Vector &x, real tol, idx max_iter, Backend backend)
Definition cg.hpp:38
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
BasicMatrix< real > Matrix
Double-precision dense matrix with full backend dispatch (CPU + GPU).
Definition matrix.hpp:127
real dot(const Vector &x, const Vector &y, Backend b=default_backend)
Compute .
Definition vector.cpp:65
constexpr real e
Definition math.hpp:44
BasicVector< real > Vector
Real-valued dense vector with full backend dispatch (CPU + GPU)
Definition vector.hpp:129
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
SolverResult cg(const Matrix &A, const Vector &b, Vector &x, real tol=1e-10, idx max_iter=1000, Backend backend=default_backend)
Definition cg.cpp:8
Common result type shared by all iterative solvers.
idx iterations
Number of iterations performed.
Dense vector storage and operations.