CHROMA
minvmr_array.cc
Go to the documentation of this file.
1 /*! \file
2  * \brief Multishift Minimal-residual algorithm for a Linear Operator
3  */
4 
5 #error "THIS ROUTINE IS NOT FULLY CONVERTED"
6 
7 #include "linearop.h"
9 
10 namespace Chroma
11 {
12 
13  //! Multishift Conjugate-Gradient (CG1) algorithm for a Linear Operator
14  /*! \ingroup invert
15  *
16  * This subroutine uses the Conjugate Gradient (CG) algorithm to find
17  * the solution of the set of linear equations
18  * Method used is described in Jegerlehner, hep-lat/9708029
19 
20  * We are searching in a subspace orthogonal to the eigenvectors EigVec
21  * of A. The source chi is assumed to already be orthogonal!
22 
23  * Chi = A . Psi
24 
25  * Algorithm:
26 
27  * Psi[0] := 0; Zeroed
28  * r[0] := Chi; Initial residual
29  * p[1] := Chi ; Initial direction
30  * b[0] := |r[0]|**2 / <p[0],Ap[0]> ;
31  * z[0] := 1 / (1 - (shift - shift(0))*b)
32  * bs[0] := b[0] * z[0]
33  * r[1] += b[k] A . p[0] ; New residual
34  * Psi[1] = - b[k] p[k] ; Starting solution std::vector
35  * IF |r[0]| <= RsdCG |Chi| THEN RETURN; Converged?
36  * FOR k FROM 1 TO MaxCG DO CG iterations
37  * a[k] := |r[k]|**2 / |r[k-1]|**2 ;
38  * p[k] := r[k] + a[k] p[k-1]; New direction
39  * b[k+1] := |r[k]|**2 / <p[k],Ap[k]> ;
40  * r[k+1] += b[k+1] A . p[k] ; New residual
41  * Psi[k+1] -= b[k+1] p[k] ; New solution std::vector
42  * IF |[k+1]| <= RsdCG |Chi| THEN RETURN; Converged?
43 
44  * Arguments:
45 
46  * A Hermitian linear operator (Read)
47  * Chi Source (Read)
48  * Psi array of solutions (Write)
49  * shifts shifts of form A + mass (Read)
50  * RsdCG residual accuracy (Read/Write)
51  * n_count Number of CG iteration (Write)
52 
53  * Local Variables:
54 
55  * p Direction std::vector
56  * r Residual std::vector
57  * cp | r[k] |**2
58  * c | r[k-1] |**2
59  * k CG iteration counter
60  * a a[k]
61  * b b[k+1]
62  * d < p[k], A.p[k] >
63  * Ap Temporary for M.p
64 
65  * MaxCG Maximum number of CG iterations allowed
66 
67  * Subroutines:
68  * A Apply matrix hermitian A to std::vector
69  *
70  * @{
71  */
72 
73  template<typename T>
74  void MInvMR_a(const LinearOperator<T>& A,
75  const T& chi,
76  multi1d<T>& psi,
77  const multi1d<Real>& shifts,
78  const multi1d<Real>& RsdMR,
79  int MaxMR,
80  int& n_count)
81  {
82  START_CODE();
83 
84  const Subset& sub = A.subset();
85 
86  if (shifts.size() != RsdMR.size())
87  {
88  QDPIO::cerr << "MInvMR: number of shifts and residuals must match" << std::endl;
89  QDP_abort(1);
90  }
91 
92  int n_shift = shifts.size();
93 
94  if (n_shift == 0)
95  {
96  QDPIO::cerr << "MInvMR: You must supply at least 1 mass: mass.size() = "
97  << n_shift << std::endl;
98  QDP_abort(1);
99  }
100 
101  multi1d<LatticeFermion> ltmp(Ncb);
102  multi1d<LatticeFermion> r(Ncb);
103  multi1d<LatticeFermion> Ar(Ncb);
104  multi1d<LatticeComplex> lc(Ncb);
105  Complex a;
106  Complex as;
107  Complex atmp;
108  Complex atmp2;
109  DComplex b;
110  DComplex c;
111  Double d;
112  Double one;
113  Double dd;
114  Double cp;
115  Double cs;
116  Real ones;
117  Real asq;
118  multi1d<Real> ass(Nmass);
119  multi1d<Complex> rhos(Nmass);
120  Boolean btmp;
121  Boolean convP;
122  multi1d<Boolean> convsP(Nmass);
123  int iz;
124  int k;
125  int cb;
126  int s;
127  multi1d<Real> rsdmr_sq(Nmass);
128 /* Real rsd_sq; */
129 
130  one = 1;
131  ones = 1;
132 
133  /* If exactly 0 norm, then solution must be 0 (for pos. def. operator) */
134  if (chi_norm == 0.0)
135  {
136  n_count = 0;
137  psi = zero;
138  END_CODE();
139  return;
140  }
141 
142  cp = chi_norm * chi_norm;
143  rsdmr_sq = localNorm2(RsdMR);
144 /* rsd_sq = cp * rsdmr_sq; */
145 
146 
147  /* Psi[0] := 0; */
148  /* r[0] := Chi */
149  psi = zero;
150  r = chi;
151  FILL(convP,FALSE);
152  FILL(convsP,FALSE);
153  rhos = 1;
154 
155  /* FOR k FROM 1 TO MaxMR DO */
156  /* IF |psi[k+1] - psi[k]| <= RsdMR |psi[k+1]| THEN RETURN; */
157  for(k = 1; k <= MaxMR && ! convP ; ++k)
158  {
159  /* cp = |r[k-1]|^2 */
160  cp = zero;
161  for(cb = 0; cb < Ncb; ++cb)
162  cp += norm2(r[cb]); /* 2 Nc Ns flops */
163 
164  /* a[k-1] := < A.r[k-1], r[k-1] >/ < A.r[k-1], A.r[k-1] > ; */
165  /* Ar = A * r */
166  A (A, r, Ar, Ncb, PLUS);
167 
168  for(cb = 0; cb < Ncb; ++cb)
169  Ar[cb] += r[cb] * mass[isz];
170 
171  /* c = < A.r, r > */
172  lc = trace(adj[Ar] * r);
173  c = zero;
174  for(cb = 0; cb < Ncb; ++cb)
175  c += sum(lc[cb]); /* ?? flops */
176 
177  /* d = | A.r | ** 2 */
178  d = zero;
179  for(cb = 0; cb < Ncb; ++cb)
180  d += norm2(Ar[cb]); /* 2 Nc Ns flops */
181 
182  /* a = c / d */
183  /*#b = c / d; */
184  dd = one / d;
185  b = c * dd;
186  a = FLOAT(b);
187 
188  /* Compute the shifted as and rhos */
189  /* Psi[k+1] += a[k] r[k] ; */
190  for(s = 0; s < Nmass; ++s)
191  {
192  if (convsP[s]) continue;
193 
194  atmp = 1;
195  asq = mass[s] - mass[isz];
196  atmp += adj(a) * asq;
197  asq = localNorm2(atmp);
198  asq = ones / asq;
199  atmp = atmp * asq;
200 
201  atmp2 = a * atmp;
202  as = rhos[s] * atmp2;
203  atmp2 = rhos[s] * atmp;
204  rhos[s] = atmp2;
205 
206  ass[s] = localNorm2(as);
207 
208  for(cb = 0; cb < Ncb; ++cb)
209  psi[s][cb] += r[cb] * as; /* 2 Nc Ns flops */
210  }
211 
212  /* r[k] -= a[k-1] M . r[k-1] ; */
213  for(cb = 0; cb < Ncb; ++cb)
214  r[cb] -= Ar[cb] * a; /* 2 Nc Ns flops */
215 
216 #if 0
217  /* Project out eigenvectors */
218  GramSchm (r, 1, OperEigVec, NOperEig, Ncb);
219  GramSchm (psi, Nmass, OperEigVec, NOperEig, Ncb);
220 #endif
221 
222  /* IF |psi[k+1] - psi[k]| <= RsdMR |psi[k+1]| THEN RETURN; */
223  for(s = 0; s < Nmass; ++s)
224  {
225  if (convsP[s]) continue;
226 
227  d = zero;
228  for(cb = 0; cb < Ncb; ++cb)
229  {
230  d += norm2(psi[s][cb]); /* 2 Nc Ns flops */
231  }
232 
233  d *= rsdmr_sq[s];
234  cs = FLOAT(ass[s]);
235  cs = cs * cp;
236  convsP[s] = cs < d;
237 
238 #if 0
239  PRINTF("MInvMR: k = %d s = %d r = %g d = %g\n",k,s,sqrt(cs),sqrt(d));
240  FLUSH_WRITE_NAMELIST(stdout);
241 #endif
242  }
243  /* Final convergence is determined by smallest shift */
244  convP = convsP[isz];
245 
246  n_count = k;
247  }
248 
249 #if 0
250  /* HACK **/
251  for(s = 0; s < Nmass; ++s)
252  {
253  for(cb = 0; cb < Ncb; ++cb)
254  ltmp[cb] = psi[s][cb];
255  A (A, ltmp, Ar, Ncb, PLUS);
256  for(cb = 0; cb < Ncb; ++cb)
257  Ar[cb] += psi[s][cb] * mass[s];
258 
259  Ar -= chi;
260 
261  cp = zero;
262  for(cb = 0; cb < Ncb; ++cb)
263  cp += norm2(Ar[cb]); /* 2 Nc Ns flops */
264 
265  PRINTF("MInvMR (conv): s = %d r = %g m = %g\n",s,sqrt(cp),mass[s]);
266  }
267  PRINTF("\n");
268  /* end */
269 #endif
270 
271  if (n_count == MaxMR)
272  QDP_error_exit("too many MR iterations", n_count, rsdmr_sq[isz]);
273  END_CODE();
274  return;
275  }
276 
277 
278 
279  /*! \ingroup invert */
280  template<>
281  void MInvMR(const LinearOperator<LatticeFermion>& M,
282  const LatticeFermion& chi,
283  multi1d<LatticeFermion>& psi,
284  const multi1d<Real>& shifts,
285  const multi1d<Real>& RsdMR,
286  int MaxMR,
287  int &n_count)
288  {
289  MInvMR_a(M, chi, psi, shifts, RsdMR, MaxMR, n_count);
290  }
291 
292 
293  /*! \ingroup invert */
294  template<>
295  void MInvMR(const DiffLinearOperator<LatticeFermion,
296  multi1d<LatticeColorMatrix>,
297  multi1d<LatticeColorMatrix> >& M,
298  const LatticeFermion& chi,
299  multi1d<LatticeFermion>& psi,
300  const multi1d<Real>& shifts,
301  const multi1d<Real>& RsdMR,
302  int MaxMR,
303  int &n_count)
304  {
305  MInvMR_a(M, chi, psi, shifts, RsdMR, MaxMR, n_count);
306  }
307 
308  /*! @} */ // end of group invert
309 
310 } // end namespace Chroma
int NOperEig
void GramSchm(multi1d< LatticeFermion > &psi, const int Npsi, const multi1d< LatticeFermion > &vec, const int Nvec, const Subset &sub)
Gramm-Schmidt orthogonolization.
Definition: gramschm.cc:127
void MInvMR_a(const LinearOperator< T > &A, const T &chi, multi1d< T > &psi, const multi1d< Real > &shifts, const multi1d< Real > &RsdMR, int MaxMR, int &n_count)
Multishift Conjugate-Gradient (CG1) algorithm for a Linear Operator.
Definition: minvmr.cc:74
void MInvMR(const LinearOperator< LatticeFermion > &M, const LatticeFermion &chi, multi1d< LatticeFermion > &psi, const multi1d< Real > &shifts, const multi1d< Real > &RsdMR, int MaxMR, int &n_count)
Multishift Conjugate-Gradient (CG1) algorithm for a Linear Operator.
Definition: minvmr.cc:258
Linear Operators.
int iz
Definition: meslate.cc:32
Multishift Conjugate-Gradient algorithm for a Linear Operator.
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
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)
int n_count
Definition: invbicg.cc:78
Double one
Definition: invbicg.cc:105
Double c
Definition: invbicg.cc:108
Double mass
Definition: pbg5p_w.cc:54
@ PLUS
Definition: chromabase.h:45
Double cp
Definition: invbicg.cc:107
multi1d< LatticeFermion > chi(Ncb)
Complex a
Definition: invbicg.cc:95
LatticeFermion psi
Definition: mespbg5p_w.cc:35
DComplex d
Definition: invbicg.cc:99
multi1d< LatticeComplex > lc(Ncb)
START_CODE()
A(A, psi, r, Ncb, PLUS)
Complex b
Definition: invbicg.cc:96
int cb
Definition: invbicg.cc:120
int Ncb
Definition: invbicg.cc:80
Double chi_norm
Definition: invbicg.cc:79
Double zero
Definition: invbicg.cc:106
int k
Definition: invbicg.cc:119
multi1d< LatticeFermion > s(Ncb)
FloatingPoint< double > Double
Definition: gtest.h:7351
int isz
Definition: pade_trln_w.cc:151
RsdMR
Definition: pade_trln_w.cc:26
PRINTF("TrLnSolve: n_count = %d, RsdMR = %16.8e, MaxRsd = %16.8e\n", n_count, RsdMR, MaxRsd)
FILL(ltmp_1, itmp)
Double sum
Definition: qtopcor.cc:37
LatticeFermion T
Definition: t_clover.cc:11