numerics 0.1.0
Loading...
Searching...
No Matches
minres.hpp
Go to the documentation of this file.
1/// @file solvers/minres.hpp
2/// @brief Minimum residual iteration for symmetric linear systems.
3/// @todo Replace the projection-based implementation with the standard
4/// short-recurrence MINRES iteration.
5#pragma once
6
7#include "core/policy.hpp"
8#include "core/vector.hpp"
11#include "core/concepts.hpp"
12#include <algorithm>
13#include <cmath>
14#include <stdexcept>
15#include <utility>
16#include <vector>
17
18namespace num {
19
20namespace detail {
21
22inline Vector minres_projected_solve(const std::vector<real>& alpha,
23 const std::vector<real>& beta,
24 real beta0,
25 idx m,
26 Backend backend) {
27 Matrix H(m + 1, m, 0.0);
28 for (idx j = 0; j < m; ++j) {
29 H(j, j) = alpha[j];
30 if (j > 0) {
31 H(j - 1, j) = beta[j - 1];
32 }
33 H(j + 1, j) = beta[j];
34 }
35
36 Vector rhs(m + 1, 0.0);
37 rhs[0] = beta0;
38 QRResult qrf = qr(H, backend);
39 Vector y(m, 0.0);
40 qr_solve(qrf, rhs, y);
41 return y;
42}
43
44} // namespace detail
45
46template<class Op>
47 requires SymmetricLinearOperator<Op, Vector, Vector>
48SolverResult minres(const Op& A,
49 const Vector& b,
50 Vector& x,
51 real tol = 1e-10,
52 idx max_iter = 1000,
53 Backend backend = default_backend) {
54 const idx n = b.size();
55 if (A.rows() != n || A.cols() != n || x.size() != n) {
56 throw std::invalid_argument("minres: dimension mismatch");
57 }
58
59 Vector r0(n), Ax(n);
60 A.apply(x, Ax);
61 for (idx i = 0; i < n; ++i) {
62 r0[i] = b[i] - Ax[i];
63 }
64
65 const real beta0 = norm(r0, backend);
66 SolverResult result{0, beta0, beta0 < tol};
67 if (result.converged) {
68 return result;
69 }
70
71 const idx mmax = std::min(max_iter, n);
72 std::vector<Vector> V;
73 V.reserve(mmax + 1);
74 V.emplace_back(n, 0.0);
75 for (idx i = 0; i < n; ++i) {
76 V[0][i] = r0[i] / beta0;
77 }
78
79 std::vector<real> alpha;
80 std::vector<real> beta;
81 alpha.reserve(mmax);
82 beta.reserve(mmax);
83
84 Vector w(n), q_prev(n, 0.0);
85 for (idx j = 0; j < mmax; ++j) {
86 result.iterations = j + 1;
87 A.apply(V[j], w);
88 if (j > 0) {
89 axpy(-beta[j - 1], q_prev, w, backend);
90 }
91
92 const real a = dot(V[j], w, backend);
93 alpha.push_back(a);
94 axpy(-a, V[j], w, backend);
95
96 const real bnext = norm(w, backend);
97 beta.push_back(bnext);
98
99 Vector y = detail::minres_projected_solve(alpha, beta, beta0, j + 1, backend);
100 Vector x_candidate = x;
101 for (idx col = 0; col <= j; ++col) {
102 axpy(y[col], V[col], x_candidate, backend);
103 }
104
105 A.apply(x_candidate, Ax);
106 real rsq = 0.0;
107 for (idx i = 0; i < n; ++i) {
108 const real ri = b[i] - Ax[i];
109 rsq += ri * ri;
110 }
111 result.residual = std::sqrt(rsq);
112 if (result.residual < tol) {
113 x = std::move(x_candidate);
114 result.converged = true;
115 break;
116 }
117
118 if (bnext < real(1e-15)) {
119 x = std::move(x_candidate);
120 break;
121 }
122
123 q_prev = V[j];
124 scale(w, real(1) / bnext, backend);
125 V.push_back(w);
126
127 if (j + 1 == mmax) {
128 x = std::move(x_candidate);
129 }
130 }
131
132 return result;
133}
134
135} // namespace num
constexpr idx size() const noexcept
Definition vector.hpp:83
Storage and operator concepts for numerical routines.
Backend enum and default backend selection.
Vector minres_projected_solve(const std::vector< real > &alpha, const std::vector< real > &beta, real beta0, idx m, Backend backend)
Definition minres.hpp:22
double real
Definition types.hpp:10
void qr_solve(const QRResult &f, const Vector &b, Vector &x)
Solve .
Definition qr.cpp:19
Backend
Definition policy.hpp:7
QRResult qr(const Matrix &A, Backend backend=lapack_backend)
Factor as .
Definition qr.cpp:10
real beta(real a, real b)
B(a, b) – beta function.
Definition math.hpp:248
std::size_t idx
Definition types.hpp:11
SolverResult minres(const Op &A, const Vector &b, Vector &x, real tol=1e-10, idx max_iter=1000, Backend backend=default_backend)
Definition minres.hpp:48
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
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
QR factorization via Householder reflections.
Common result type shared by all iterative solvers.
QR factorization .
Definition qr.hpp:11
Dense vector storage and operations.