CHROMA
invcg1.cc
Go to the documentation of this file.
1 /*! \file
2  * \brief Conjugate-Gradient algorithm for a generic Linear Operator
3  */
4 
5 #include "chromabase.h"
7 
8 using namespace QDP::Hints;
9 
10 namespace Chroma {
11 
12 //! Conjugate-Gradient (CGNE) algorithm for a generic Linear Operator
13 /*! \ingroup invert
14  * This subroutine uses the Conjugate Gradient (CG) algorithm to find
15  * the solution of the set of linear equations
16  *
17  * Chi = A . Psi
18  *
19  * where A is Hermitian Positive Definite
20  *
21  * Algorithm:
22 
23  * Psi[0] := initial guess; Linear interpolation (argument)
24  * r[0] := Chi - A. Psi[0] ; Initial residual
25  * p[1] := r[0] ; Initial direction
26  * IF |r[0]| <= RsdCG |Chi| THEN RETURN; Converged?
27  * FOR k FROM 1 TO MaxCG DO CG iterations
28  * a[k] := |r[k-1]|**2 / <p[k],Ap[k]> ;
29  * Psi[k] += a[k] p[k] ; New solution std::vector
30  * r[k] -= a[k] A. p[k] ; New residual
31  * IF |r[k]| <= RsdCG |Chi| THEN RETURN; Converged?
32  * b[k+1] := |r[k]|**2 / |r[k-1]|**2 ;
33  * p[k+1] := r[k] + b[k+1] p[k]; New direction
34  *
35  * Arguments:
36  *
37  * \param M Linear Operator (Read)
38  * \param chi Source (Read)
39  * \param psi Solution (Modify)
40  * \param RsdCG CG residual accuracy (Rea/Write)
41  * \param MaxCG Maximum CG iterations (Read)
42  * \return res System solver results
43  *
44  * Local Variables:
45  *
46  * p Direction std::vector
47  * r Residual std::vector
48  * cp | r[k] |**2
49  * c | r[k-1] |**2
50  * k CG iteration counter
51  * a a[k]
52  * b b[k+1]
53  * d < p[k], A.p[k] >
54  * ap Temporary for A.p
55  *
56  * Subroutines:
57  * +
58  * A Apply matrix M or M to std::vector
59  *
60  * Operations:
61  *
62  * 2 A + 2 Nc Ns + N_Count ( 2 A + 10 Nc Ns )
63  */
64 
65 
66 
67 template<typename T>
68 SystemSolverResults_t
70  const T& chi,
71  T& psi,
72  const Real& RsdCG,
73  int MaxCG, int MinCG=0)
74 {
75  START_CODE();
76 
77  const Subset& s = A.subset();
78 
80 
81  T p; moveToFastMemoryHint(p);
82  T ap; moveToFastMemoryHint(ap);
83 
84  // Hint for psi to be moved with copy
85  moveToFastMemoryHint(psi,true);
86 
87  T r; moveToFastMemoryHint(r);
88  T chi_internal; moveToFastMemoryHint(chi_internal);
89 
90  // Can't move chi to fast space, because its const.
91  chi_internal[s]=chi;
92 
93  Real rsd_sq = (RsdCG * RsdCG) * Real(norm2(chi_internal,s));
94 
95  //
96  // r[0] := Chi - A . Psi[0]
97 
98  //
99  // r := [ Chi - A . psi ]
100 
101 
102  // A is Hermitian
103  A(ap, psi, PLUS);
104 
105 
106  r[s] = chi_internal - ap;
107 
108  // p[1] := r[0]
109  p[s] = r;
110 
111  // Cp = |r[0]|^2
112  Double cp = norm2(r, s); /* 2 Nc Ns flops */
113 
114 #if 0
115  QDPIO::cout << "InvCG1: k = 0 cp = " << cp << " rsd_sq = " << rsd_sq
116 << std::endl;
117 #endif
118 
119  // IF |r[0]| <= RsdCG |Chi| THEN RETURN;
120  if ( toBool(cp <= rsd_sq) )
121  {
122  res.n_count = 0;
123  res.resid = sqrt(cp);
124  revertFromFastMemoryHint(psi, true); // Revert psi, and copy contents
125  END_CODE();
126  return res;
127  }
128 
129  //
130  // FOR k FROM 1 TO MaxCG DO
131  //
132  Real b;
133  Double c;
134  Complex a;
135  Real d;
136 
137  for(int k = 1; k <= MaxCG; ++k)
138  {
139  // c = | r[k-1] |**2
140  c = cp;
141 
142  // a[k] := | r[k-1] |**2 / < p[k], Ap[k] > ;
143  // +
144  // First compute d = < p, A.p >
145 
146 
147  // SCRAP THIS IDEA FOR NOW AND DO <p, A.p> TO KEEP TRACK OF
148  // "PRECONDITIONING" So ap =MdagMp
149 
150  A(ap, p, PLUS);
151 
152  // d = <p,A.p>
153  d = innerProductReal(p, ap, s);
154 
155  // a = Real(c);
156  a = Real(c)/d;
157 
158 
159  // Psi[k] += a[k] p[k]
160  psi[s] += a * p; /* 2 Nc Ns flops */
161 
162  // r[k] -= a[k] A . p[k] ;
163  //
164  // r = r - a A p
165 
166  r[s] -= a * ap;
167 
168 
169 
170  // IF |r[k]| <= RsdCG |Chi| THEN RETURN;
171 
172  // cp = | r[k] |**2
173  cp = norm2(r, s); /* 2 Nc Ns flops */
174 
175 #if 0
176  QDPIO::cout << "InvCG1: k = " << k << " cp = " << cp << std::endl;
177 #endif
178 
179  if ( toBool(cp <= rsd_sq) && (toBool(MinCG <= 0 ) || toBool( k >= MinCG )))
180  {
181  res.n_count = k;
182  res.resid = sqrt(cp);
183 
184  // Compute the actual residual
185  {
186  A(ap, psi, PLUS);
187  Double actual_res = norm2(chi - ap,s);
188  res.resid = sqrt(actual_res);
189 #if 0
190  QDPIO::cout << "InvCG1: true residual: " << res.resid << std::endl;
191 #endif
192  }
193  revertFromFastMemoryHint(psi,true); // Get back psi, copy contents.
194  END_CODE();
195  return res;
196  }
197 
198  // b[k+1] := |r[k]|**2 / |r[k-1]|**2
199  b = Real(cp) / Real(c);
200 
201  // p[k+1] := r[k] + b[k+1] p[k]
202  p[s] = r + b*p; /* Nc Ns flops */
203  }
204  res.n_count = MaxCG;
205  res.resid = sqrt(cp);
206  QDP_error_exit("too many CG iterations: count = %d", res.n_count);
207  revertFromFastMemoryHint(psi,true);
208  END_CODE();
209  return res;
210 }
211 
212 // Fix here for now
213 template<>
214 SystemSolverResults_t
216  const LatticeFermion& chi,
217  LatticeFermion& psi,
218  const Real& RsdCG,
219  int MaxCG,int MinCG)
220 {
221  return InvCG1_a(A, chi, psi, RsdCG, MaxCG,MinCG);
222 }
223 
224 template<>
225 SystemSolverResults_t
227  const LatticeStaggeredFermion& chi,
228  LatticeStaggeredFermion& psi,
229  const Real& RsdCG,
230  int MaxCG,int MinCG)
231 {
232  return InvCG1_a(A, chi, psi, RsdCG, MaxCG,MinCG);
233 }
234 
235 } // end namespace Chroma
Primary include file for CHROMA library code.
#define END_CODE()
Definition: chromabase.h:65
#define START_CODE()
Definition: chromabase.h:64
Linear Operator.
Definition: linearop.h:27
EXTERN int MaxCG
SystemSolverResults_t InvCG1_a(const LinearOperator< T > &A, const T &chi, T &psi, const Real &RsdCG, int MaxCG, int MinCG=0)
Conjugate-Gradient (CGNE) algorithm for a generic Linear Operator.
Definition: invcg1.cc:69
Conjugate-Gradient algorithm for a generic Linear Operator.
unsigned s
Definition: ldumul_w.cc:37
int c
Definition: meslate.cc:61
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
const WilsonTypeFermAct< multi1d< LatticeFermion > > Handle< const ConnectState > const multi1d< Real > enum InvType invType const multi1d< Real > & RsdCG
Definition: pbg5p_w.cc:30
QDP_error_exit("too many BiCG iterations", n_count, rsd_sq, cp, c, re_rvr, im_rvr, re_a, im_a, re_b, im_b)
LinOpSysSolverMGProtoClover::T T
Real rsd_sq
Definition: invbicg.cc:121
@ PLUS
Definition: chromabase.h:45
SystemSolverResults_t InvCG1(const LinearOperator< LatticeStaggeredFermion > &A, const LatticeStaggeredFermion &chi, LatticeStaggeredFermion &psi, const Real &RsdCG, int MaxCG, int MinCG)
Definition: invcg1.cc:226
Double cp
Definition: invbicg.cc:107
Complex a
Definition: invbicg.cc:95
DComplex d
Definition: invbicg.cc:99
A(A, psi, r, Ncb, PLUS)
Complex b
Definition: invbicg.cc:96
int k
Definition: invbicg.cc:119
FloatingPoint< double > Double
Definition: gtest.h:7351
multi1d< LatticeFermion > r(Ncb)
chi
Definition: pade_trln_w.cc:24
psi
Definition: pade_trln_w.cc:191
Holds return info from SystemSolver call.
Definition: syssolver.h:17