Grid 0.7.0
Forecast.h
Go to the documentation of this file.
1/*************************************************************************************
2
3Grid physics library, www.github.com/paboyle/Grid
4
5Source file: ./lib/algorithms/approx/Forecast.h
6
7Copyright (C) 2015
8
9Author: Peter Boyle <paboyle@ph.ed.ac.uk>
10Author: paboyle <paboyle@ph.ed.ac.uk>
11Author: David Murphy <dmurphy@phys.columbia.edu>
12
13This program is free software; you can redistribute it and/or modify
14it under the terms of the GNU General Public License as published by
15the Free Software Foundation; either version 2 of the License, or
16(at your option) any later version.
17
18This program is distributed in the hope that it will be useful,
19but WITHOUT ANY WARRANTY; without even the implied warranty of
20MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21GNU General Public License for more details.
22
23You should have received a copy of the GNU General Public License along
24with this program; if not, write to the Free Software Foundation, Inc.,
2551 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26
27See the full license in the file "LICENSE" in the top level distribution directory
28*************************************************************************************/
29 /* END LEGAL */
30
31#ifndef INCLUDED_FORECAST_H
32#define INCLUDED_FORECAST_H
33
35
36// Abstract base class.
37// Takes a matrix (Mat), a source (phi), and a vector of Fields (chi)
38// and returns a forecasted solution to the system D*psi = phi (psi).
39template<class Matrix, class Field>
41{
42public:
43 virtual Field operator()(Matrix &Mat, const Field& phi, const std::vector<Field>& chi) = 0;
44};
45
46// Implementation of Brower et al.'s chronological inverter (arXiv:hep-lat/9509012),
47// used to forecast solutions across poles of the EOFA heatbath.
48//
49// Modified from CPS (cps_pp/src/util/dirac_op/d_op_base/comsrc/minresext.C)
50template<class Matrix, class Field>
51class ChronoForecast : public Forecast<Matrix,Field>
52{
53public:
54 Field operator()(Matrix &Mat, const Field& phi, const std::vector<Field>& prev_solns)
55 {
56 int degree = prev_solns.size();
57 Field chi(phi); // forecasted solution
58
59 // Trivial cases
60 if(degree == 0){ chi = Zero(); return chi; }
61 else if(degree == 1){ return prev_solns[0]; }
62
63 // RealD dot;
64 ComplexD xp;
65 Field r(phi); // residual
66 Field Mv(phi);
67 std::vector<Field> v(prev_solns); // orthonormalized previous solutions
68 std::vector<Field> MdagMv(degree,phi);
69
70 // Array to hold the matrix elements
71 std::vector<std::vector<ComplexD>> G(degree, std::vector<ComplexD>(degree));
72
73 // Solution and source vectors
74 std::vector<ComplexD> a(degree);
75 std::vector<ComplexD> b(degree);
76
77 // Orthonormalize the vector basis
78 for(int i=0; i<degree; i++){
79 v[i] *= 1.0/std::sqrt(norm2(v[i]));
80 for(int j=i+1; j<degree; j++){ v[j] -= innerProduct(v[i],v[j]) * v[i]; }
81 }
82
83 // Perform sparse matrix multiplication and construct rhs
84 for(int i=0; i<degree; i++){
85 b[i] = innerProduct(v[i],phi);
86 Mat.M(v[i],Mv);
87 Mat.Mdag(Mv,MdagMv[i]);
88 G[i][i] = innerProduct(v[i],MdagMv[i]);
89 }
90
91 // Construct the matrix
92 for(int j=0; j<degree; j++){
93 for(int k=j+1; k<degree; k++){
94 G[j][k] = innerProduct(v[j],MdagMv[k]);
95 G[k][j] = conjugate(G[j][k]);
96 }}
97
98 // Gauss-Jordan elimination with partial pivoting
99 for(int i=0; i<degree; i++){
100
101 // Perform partial pivoting
102 int k = i;
103 for(int j=i+1; j<degree; j++){ if(abs(G[j][j]) > abs(G[k][k])){ k = j; } }
104 if(k != i){
105 xp = b[k];
106 b[k] = b[i];
107 b[i] = xp;
108 for(int j=0; j<degree; j++){
109 xp = G[k][j];
110 G[k][j] = G[i][j];
111 G[i][j] = xp;
112 }
113 }
114
115 // Convert matrix to upper triangular form
116 for(int j=i+1; j<degree; j++){
117 xp = G[j][i]/G[i][i];
118 b[j] -= xp * b[i];
119 for(int k=0; k<degree; k++){ G[j][k] -= xp*G[i][k]; }
120 }
121 }
122
123 // Use Gaussian elimination to solve equations and calculate initial guess
124 chi = Zero();
125 r = phi;
126 for(int i=degree-1; i>=0; i--){
127 a[i] = 0.0;
128 for(int j=i+1; j<degree; j++){ a[i] += G[i][j] * a[j]; }
129 a[i] = (b[i]-a[i])/G[i][i];
130 chi += a[i]*v[i];
131 r -= a[i]*MdagMv[i];
132 }
133
134 RealD true_r(0.0);
135 ComplexD tmp;
136 for(int i=0; i<degree; i++){
137 tmp = -b[i];
138 for(int j=0; j<degree; j++){ tmp += G[i][j]*a[j]; }
139 tmp = conjugate(tmp)*tmp;
140 true_r += std::sqrt(tmp.real());
141 }
142
143 RealD error = std::sqrt(norm2(r)/norm2(phi));
144 std::cout << GridLogMessage << "ChronoForecast: |res|/|src| = " << error << std::endl;
145
146 return chi;
147 };
148};
149
151
152#endif
accelerator_inline Grid_simd< S, V > abs(const Grid_simd< S, V > &r)
Lattice< vobj > conjugate(const Lattice< vobj > &lhs)
ComplexD innerProduct(const Lattice< vobj > &left, const Lattice< vobj > &right)
RealD norm2(const Lattice< vobj > &arg)
GridLogger GridLogMessage(1, "Message", GridLogColours, "NORMAL")
#define NAMESPACE_BEGIN(A)
Definition Namespace.h:35
#define NAMESPACE_END(A)
Definition Namespace.h:36
std::complex< RealD > ComplexD
Definition Simd.h:79
double RealD
Definition Simd.h:61
Field operator()(Matrix &Mat, const Field &phi, const std::vector< Field > &prev_solns)
Definition Forecast.h:54
virtual Field operator()(Matrix &Mat, const Field &phi, const std::vector< Field > &chi)=0
Definition Simd.h:194