HILA
Loading...
Searching...
No Matches
MRE_guess.h
1#ifndef MRE_GUESS_H
2#define MRE_GUESS_H
3
4#include "gauge_field.h"
5#include "dirac/Hasenbusch.h"
6#include <cmath>
7
8/// Builds an initial guess for a matrix inverter given a set of basis vectors
9template <typename vector_type, typename DIRAC_OP>
10void MRE_guess(Field<vector_type> &psi, Field<vector_type> &chi, DIRAC_OP D,
11 std::vector<Field<vector_type>> old_chi_inv) {
12 int MRE_size = old_chi_inv.size();
13 double M[MRE_size][MRE_size];
14 double v[MRE_size];
15 Field<vector_type> basis[MRE_size];
17
18 // Build an orthogonal basis from the previous solutions
19 for (int i = 0; i < MRE_size; i++) {
20 // Start with the original solution vector
21 basis[i][ALL] = old_chi_inv[i][X];
22 // Remove the projected components of all previous vectors
23 for (int j = 0; j < i; j++) {
24 double vdot = 0, norm = 0;
25 onsites(D.par) {
26 norm += basis[i][X].rdot(basis[i][X]);
27 vdot += basis[j][X].rdot(basis[i][X]);
28 }
29 if (norm * norm > 1e-32) {
30 onsites(D.par) { basis[i][X] = basis[i][X] - vdot / norm * basis[j][X]; }
31 }
32 }
33 }
34
35 // Build the projected matrix, M[i][j] = v[i].v[j]
36 for (int i = 0; i < MRE_size; i++) {
37 Field<vector_type> Dchi, DDchi;
38 D.apply(basis[i], Dchi);
39 D.dagger(Dchi, DDchi);
40 for (int j = 0; j < MRE_size; j++) {
41 double sum = 0;
42 onsites(D.par) { sum += basis[j][X].rdot(DDchi[X]); }
43 M[j][i] = sum;
44 }
45 }
46 // And the projected vector
47 for (int i = 0; i < MRE_size; i++) {
48 double sum = 0;
49 onsites(D.par) { sum += basis[i][X].rdot(chi[X]); }
50 v[i] = sum;
51 }
52
53 // Now invert the small matrix M (Gaussian elimination)
54 for (int i = 0; i < MRE_size; i++) {
55 // Check that the diagonal element is nonzero
56 if (M[i][i] * M[i][i] > 1e-32) {
57 // Normalize the i:th row
58 double diag_inv = 1.0 / M[i][i];
59 for (int j = 0; j < MRE_size; j++) {
60 M[i][j] *= diag_inv;
61 }
62 v[i] *= diag_inv;
63 // Subtract from all other rows
64 for (int k = 0; k < MRE_size; k++)
65 if (k != i) {
66 double weight = M[k][i];
67 for (int j = 0; j < MRE_size; j++) {
68 M[k][j] -= weight * M[i][j];
69 }
70 v[k] -= weight * v[i];
71 }
72 } else {
73 // In the matrix element is too small, just remove it from the basis
74 v[i] = 0;
75 for (int j = 0; j < MRE_size; j++) {
76 M[j][i] = 0;
77 }
78 }
79 }
80
81 // Construct the solution in the original basis
82 psi[ALL] = 0;
83 for (int i = 0; i < MRE_size; i++)
84 if (!isnan(v[i])) {
85 onsites(D.par) { psi[X] = basis[i][X] + v[i] * basis[i][X]; }
86 }
87}
88
89#endif
The field class implements the standard methods for accessing Fields. Hilapp replaces the parity acce...
Definition field.h:61
Field< A > dagger() const
Returns dagger or Hermitian conjugate of Field depending on how it is defined for Field type T.
Definition field.h:1123
constexpr Parity ALL
bit pattern: 011
double weight(double OP)
process 0 interface to "weight function" for the user accessing the weights.