numerics 0.1.0
Loading...
Searching...
No Matches
cg.cpp
Go to the documentation of this file.
3#include <cmath>
4#include <stdexcept>
5
6namespace num {
7
9 const Vector& b,
10 Vector& x,
11 real tol,
12 idx max_iter,
13 Backend backend) {
14 idx n = b.size();
15 if (A.rows() != n || A.cols() != n || x.size() != n)
16 throw std::invalid_argument("Dimension mismatch in CG solver");
17
18 // GPU path: transfer all data to device first
19 if (backend == Backend::gpu) {
20 const_cast<Matrix&>(A).to_gpu();
21 const_cast<Vector&>(b).to_gpu();
22 x.to_gpu();
23 }
24
25 Vector r(n), p(n), Ap(n);
26 if (backend == Backend::gpu) {
27 r.to_gpu();
28 p.to_gpu();
29 Ap.to_gpu();
30 }
31
32 matvec(A, x, r, backend);
33 if (backend == Backend::gpu) {
34 scale(r, -1.0, backend);
35 axpy(1.0, b, r, backend);
36 cuda::to_device(p.gpu_data(), r.gpu_data(), n);
37 } else {
38 for (idx i = 0; i < n; ++i)
39 r[i] = b[i] - r[i];
40 for (idx i = 0; i < n; ++i)
41 p[i] = r[i];
42 }
43
44 real rsold = dot(r, r, backend);
45 SolverResult result{0, std::sqrt(rsold), false};
46
47 for (idx iter = 0; iter < max_iter; ++iter) {
48 result.iterations = iter + 1;
49 matvec(A, p, Ap, backend);
50
51 real pAp = dot(p, Ap, backend);
52 if (std::abs(pAp) < 1e-15)
53 break;
54 real alpha = rsold / pAp;
55
56 axpy(alpha, p, x, backend);
57 axpy(-alpha, Ap, r, backend);
58
59 real rsnew = dot(r, r, backend);
60 result.residual = std::sqrt(rsnew);
61
62 if (result.residual < tol) {
63 result.converged = true;
64 break;
65 }
66
67 real beta = rsnew / rsold;
68 scale(p, beta, backend);
69 axpy(1.0, r, p, backend);
70 rsold = rsnew;
71 }
72
73 if (backend == Backend::gpu)
74 x.to_cpu();
75 return result;
76}
77
79 const Vector& b,
80 Vector& x,
81 real tol,
82 idx max_iter) {
83 idx n = b.size();
84 Vector r(n), p(n), Ap(n);
85
86 matvec_fn(x, r);
87 for (idx i = 0; i < n; ++i)
88 r[i] = b[i] - r[i];
89 for (idx i = 0; i < n; ++i)
90 p[i] = r[i];
91
92 real rsold = dot(r, r, Backend::seq);
93 SolverResult result{0, std::sqrt(rsold), false};
94
95 for (idx iter = 0; iter < max_iter; ++iter) {
96 result.iterations = iter + 1;
97 matvec_fn(p, Ap);
98
99 real pAp = dot(p, Ap, Backend::seq);
100 if (std::abs(pAp) < 1e-15)
101 break;
102 real alpha = rsold / pAp;
103
104 axpy(alpha, p, x, Backend::seq);
105 axpy(-alpha, Ap, r, Backend::seq);
106
107 real rsnew = dot(r, r, Backend::seq);
108 result.residual = std::sqrt(rsnew);
109 if (result.residual < tol) {
110 result.converged = true;
111 break;
112 }
113
114 real beta = rsnew / rsold;
116 axpy(1.0, r, p, Backend::seq);
117 rsold = rsnew;
118 }
119 return result;
120}
121
122} // namespace num
Conjugate gradient solvers (dense and matrix-free)
constexpr idx size() const noexcept
Definition vector.hpp:80
Dense row-major matrix with optional GPU storage.
Definition matrix.hpp:12
constexpr idx rows() const noexcept
Definition matrix.hpp:24
constexpr idx cols() const noexcept
Definition matrix.hpp:25
CUDA kernel wrappers.
void to_device(real *dst, const real *src, idx n)
Copy host to device.
double real
Definition types.hpp:10
Backend
Selects which backend handles a linalg operation.
Definition policy.hpp:19
@ gpu
CUDA – custom kernels or cuBLAS.
@ seq
Naive textbook loops – always available.
real beta(real a, real b)
B(a, b) – beta function.
Definition math.hpp:248
std::function< void(const Vector &, Vector &)> MatVecFn
Callable type for matrix-free matvec: computes y = A*x.
Definition cg.hpp:13
std::size_t idx
Definition types.hpp:11
void matvec(const Matrix &A, const Vector &x, Vector &y, Backend b=default_backend)
y = A * x
Definition matrix.cpp:120
void scale(Vector &v, real alpha, Backend b=default_backend)
v *= alpha
Definition vector.cpp:29
real dot(const Vector &x, const Vector &y, Backend b=default_backend)
dot product
Definition vector.cpp:79
constexpr real e
Definition math.hpp:43
void axpy(real alpha, const Vector &x, Vector &y, Backend b=default_backend)
y += alpha * x
Definition vector.cpp:58
SolverResult cg_matfree(MatVecFn matvec, const Vector &b, Vector &x, real tol=1e-6, idx max_iter=1000)
Matrix-free conjugate gradient for Ax = b where A is SPD.
Definition cg.cpp:78
SolverResult cg(const Matrix &A, const Vector &b, Vector &x, real tol=1e-10, idx max_iter=1000, Backend backend=default_backend)
Conjugate gradient solver for Ax = b.
Definition cg.cpp:8
idx iterations
Number of iterations performed.