numerics 0.1.0
Loading...
Searching...
No Matches
lanczos.hpp
Go to the documentation of this file.
1/// @file eigen/lanczos.hpp
2/// @brief Lanczos eigensolver for symmetric operators.
3///
4/// Builds an orthonormal basis \f$Q_m\f$ such that
5/// \f$Q_m^T A Q_m = T_m\f$, with \f$T_m\f$ tridiagonal.
6#pragma once
7
8#include "core/matrix.hpp"
9#include "core/policy.hpp"
10#include "core/vector.hpp"
11#include "kernel/subspace.hpp"
15#include <algorithm>
16#include <cmath>
17#include <stdexcept>
18
19namespace num {
20
27
28/// @brief Operator Lanczos for any symmetric \f$y=A x\f$ adapter.
29template<class Op>
32 idx k,
33 real tol = 1e-10,
34 idx max_steps = 0,
35 Backend backend = Backend::seq) {
36 (void)backend;
37 const idx n = A.rows();
38 if (A.cols() != n) {
39 throw std::invalid_argument("lanczos: operator must be square");
40 }
41 if (k == 0 || k > n) {
42 throw std::invalid_argument("lanczos: k must satisfy 0 < k <= n");
43 }
44
45 if (max_steps == 0) {
46 max_steps = std::min(3 * k, n);
47 }
48 max_steps = std::min(max_steps, n);
49
50 Matrix V(n, max_steps, 0.0);
51 Vector alpha(max_steps, 0.0);
52 Vector beta(max_steps, 0.0);
53
54 for (idx i = 0; i < n; ++i) {
55 V(i, 0) = (i == 0) ? 1.0 : 0.0;
56 }
57
58 idx steps = 0;
59
60 for (idx j = 0; j < max_steps; ++j) {
61 Vector vj(n);
62 for (idx i = 0; i < n; ++i) {
63 vj[i] = V(i, j);
64 }
65
66 Vector w(n, 0.0);
67 A.apply(vj, w);
68
69 const real a = dot(vj, w);
70 alpha[j] = a;
71
72 axpy(-a, vj, w);
73 if (j > 0) {
74 for (idx i = 0; i < n; ++i) {
75 w[i] -= beta[j - 1] * V(i, j - 1);
76 }
77 }
78
79 const real b = kernel::subspace::mgs_orthogonalize(V, j + 1, w);
80 ++steps;
81
82 if (b < real(1e-12)) {
83 break;
84 }
85
86 beta[j] = b;
87
88 if (j + 1 < max_steps) {
89 for (idx i = 0; i < n; ++i) {
90 V(i, j + 1) = w[i] / b;
91 }
92 }
93 }
94
95 const idx m = steps;
96 Matrix T(m, m, 0.0);
97 for (idx j = 0; j < m; ++j) {
98 T(j, j) = alpha[j];
99 if (j + 1 < m) {
100 T(j, j + 1) = beta[j];
101 T(j + 1, j) = beta[j];
102 }
103 }
104
105 EigenResult teig = eig_sym(T, tol * real(1e-2));
106 const idx nret = std::min(k, m);
107
108 Matrix ritz_vecs(n, nret, 0.0);
109 for (idx i = 0; i < nret; ++i) {
110 const idx ti = m - nret + i;
111 for (idx j = 0; j < m; ++j) {
112 const real coeff = teig.vectors(j, ti);
113 for (idx r = 0; r < n; ++r) {
114 ritz_vecs(r, i) += coeff * V(r, j);
115 }
116 }
117 }
118
119 Vector ritz_vals(nret);
120 for (idx i = 0; i < nret; ++i) {
121 ritz_vals[i] = teig.values[m - nret + i];
122 }
123
124 bool all_converged = true;
125 for (idx i = 0; i < nret; ++i) {
126 Vector u(n);
127 for (idx r = 0; r < n; ++r) {
128 u[r] = ritz_vecs(r, i);
129 }
130
131 Vector Au(n, 0.0);
132 A.apply(u, Au);
133
134 real res = 0;
135 const real lam = ritz_vals[i];
136 for (idx r = 0; r < n; ++r) {
137 const real d = Au[r] - lam * u[r];
138 res += d * d;
139 }
140 if (std::sqrt(res) > tol) {
141 all_converged = false;
142 break;
143 }
144 }
145
146 return {ritz_vals, ritz_vecs, steps, all_converged};
147}
148
149LanczosResult lanczos(const Matrix& A,
150 idx k,
151 real tol = 1e-10,
152 idx max_steps = 0,
153 Backend backend = Backend::seq);
154
155LanczosResult lanczos(const SparseMatrix& A,
156 idx k,
157 real tol = 1e-10,
158 idx max_steps = 0,
159 Backend backend = Backend::seq);
160
161} // namespace num
Compile-time contract for y = A*x.
Definition concepts.hpp:19
Backend enum and default backend selection.
Full symmetric eigendecomposition via cyclic Jacobi sweeps.
Compressed Sparse Row (CSR) matrix and operations.
Dense row-major matrix templated over scalar type T.
real mgs_orthogonalize(const std::vector< Vector > &basis, Vector &v, std::vector< real > &h, idx k)
Modified Gram-Schmidt against basis[0..k-1].
Definition subspace.cpp:9
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
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
LanczosResult lanczos(const Op &A, idx k, real tol=1e-10, idx max_steps=0, Backend backend=Backend::seq)
Operator Lanczos for any symmetric adapter.
Definition lanczos.hpp:31
void axpy(real alpha, const Vector &x, Vector &y, Backend b=default_backend)
Compute .
Definition vector.cpp:44
EigenResult eig_sym(const Matrix &A, real tol=1e-12, idx max_sweeps=100, Backend backend=lapack_backend)
Definition eig.cpp:11
Umbrella include for operator concepts and adapters.
Symmetric eigendecomposition .
Subspace construction and orthogonalization kernels.
Dense vector storage and operations.