HILA
Loading...
Searching...
No Matches
conjugate_gradient.h
1#ifndef CG_ALG
2#define CG_ALG
3
4///////////////////////////////////////////////////////
5/// Generalized Conjugate gradient algorithm for fields
6///
7/// Idea is to solve for field2 in the equation
8/// field1 = operator * field2 where operator can be a
9/// staggered dirac operator or something else.
10///////////////////////////////////////////////////////
11
12#include <sstream>
13#include <iostream>
14
15constexpr int CG_DEFAULT_MAXITERS = 10000;
16constexpr double CG_DEFAULT_ACCURACY = 1e-12;
17
18/// The conjugate gradient operator. Applies the inverse square of an operator on a vector
19template <typename Op> class CG {
20 private:
21 // The operator to invert
22 Op &M;
23 // desired relative accuracy
24 double accuracy = CG_DEFAULT_ACCURACY;
25 // maximum number of iterations
26 double maxiters = CG_DEFAULT_MAXITERS;
27
28 public:
29 /// Get the type the operator applies to
30 using vector_type = typename Op::vector_type;
31
32 /// Constructor: initialize the operator
33 CG(Op &op) : M(op){};
34 /// Constructor: operator and accuracy
35 CG(Op &op, double _accuracy) : M(op) { accuracy = _accuracy; };
36 /// Constructor: operator, accuracy and maximum number of iterations
37 CG(Op &op, double _accuracy, int _maxiters) : M(op) {
38 accuracy = _accuracy;
39 maxiters = _maxiters;
40 };
41
42 /// The apply() -member runs the full conjugate gradient
43 /// The operators themselves have the same structure.
44 /// The conjugate gradient operator is Hermitean, so there is
45 /// no dagger().
47 int i;
48 struct timeval start, end;
49 Field<vector_type> r, p, Dp, DDp;
51 p.copy_boundary_condition(in);
52 Dp.copy_boundary_condition(in);
53 DDp.copy_boundary_condition(in);
54 out.copy_boundary_condition(in);
55 double pDp = 0, rr = 0, rrnew = 0, rr_start = 0;
56 double alpha, beta;
57 double target_rr, source_norm = 0;
58
59 gettimeofday(&start, NULL);
60
61 onsites(M.par) { source_norm += squarenorm(in[X]); }
62
63 target_rr = accuracy * accuracy * source_norm;
64
65 M.apply(out, Dp);
66 M.dagger(Dp, DDp);
67 onsites(M.par) {
68 r[X] = in[X] - DDp[X];
69 p[X] = r[X];
70 }
71
72 onsites(M.par) { rr += squarenorm(r[X]); }
73 rr_start = rr;
74
75 for (i = 0; i < maxiters; i++) {
76 pDp = rrnew = 0;
77 M.apply(p, Dp);
78 M.dagger(Dp, DDp);
79 onsites(M.par) { pDp += squarenorm(Dp[X]); }
80
81 alpha = rr / pDp;
82
83 onsites(M.par) {
84 out[X] = out[X] + alpha * p[X];
85 r[X] = r[X] - alpha * DDp[X];
86 }
87 onsites(M.par) { rrnew += squarenorm(r[X]); }
88#ifdef DEBUG_CG
89 hila::out0 << "CG step " i << ", residue " << sqrt(rrnew / target_rr) << "\n";
90#endif
91 if (rrnew < target_rr)
92 break;
93 beta = rrnew / rr;
94 p[M.par] = beta * p[X] + r[X];
95 rr = rrnew;
96 }
97
98 gettimeofday(&end, NULL);
99 double timing =
100 1e-3 * (end.tv_usec - start.tv_usec) + 1e3 * (end.tv_sec - start.tv_sec);
101
102 hila::out0 << "Conjugate Gradient: " << i << " steps in " << timing << "ms, ";
103 hila::out0 << "relative residue:" << rrnew / source_norm << "\n";
104 }
105};
106
107#endif
hila::arithmetic_type< T > squarenorm(const Array< n, m, T > &rhs)
Return square norm of Array.
Definition array.h:957
The conjugate gradient operator. Applies the inverse square of an operator on a vector.
CG(Op &op, double _accuracy)
Constructor: operator and accuracy.
CG(Op &op, double _accuracy, int _maxiters)
Constructor: operator, accuracy and maximum number of iterations.
void apply(Field< vector_type > &in, Field< vector_type > &out)
CG(Op &op)
Constructor: initialize the operator.
typename Op::vector_type vector_type
Get the type the operator applies to.
The field class implements the standard methods for accessing Fields. Hilapp replaces the parity acce...
Definition field.h:61
void copy_boundary_condition(const Field< A > &rhs)
Copy the boundary condition from another field.
Definition field.h:650
std::ostream out0
This writes output only from main process (node 0)