CHROMA
invbicgstab_array.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 namespace Chroma {
9 
10 template<typename T>
11 SystemSolverResults_t
13  const multi1d<T> & chi,
14  multi1d<T>& psi,
15  const Real& RsdBiCGStab,
16  int MaxBiCGStab)
17 {
19 
20  const int N = psi.size();
21 
22  const Subset& s = A.subset();
23 
24  // Not converged
25  bool convP = false;
26 
27  // || chi ||^2
28  Real chi_sq = norm2(chi,s);
29 
30  // Target residuum ( epsilon*|| chi || )^2
31  Real rsd_sq = RsdBiCGStab*RsdBiCGStab*chi_sq;
32 
33  // First get r = r0 = chi - A psi
34  multi1d<T> r(N);
35  multi1d<T> r0(N);
36 
37  // Get A psi, use r0 as a temporary
38  A(r0, psi, PLUS);
39 
40  // now work out r= chi - Apsi = chi - r0
41  for(int n=0; n < N; n++) {
42  r[n][s] = chi[n] - r0[n];
43 
44  // Also copy back to r0. We are no longer in need of the
45  // nth component
46  r0[n][s] = r[n];
47  }
48 
49  // Now we have r = r0 = chi - Mpsi
50 
51  // Now initialise v = p = 0
52  multi1d<T> p(N);
53  multi1d<T> v(N);
54 
55  for(int n = 0; n < N; n++) {
56  p[n][s] = zero;
57  v[n][s] = zero;
58  }
59 
60  // Create a temporary std::vector for later use
61  T tmp;
62 
63  // Search std::vector for t = Ms step.
64  multi1d<T> t(N);
65 
66  Complex rho, rho_prev, alpha, omega;
67 
68  // rho_0 := alpha := omega = 1
69  // Iterations start at k=1, so rho_0 is in rho_prev
70  rho_prev = Real(1);
71  alpha = Real(1);
72  omega = Real(1);
73 
74  // The iterations
75  for(int k = 1; k <= MaxBiCGStab && !convP ; k++) {
76 
77  // rho_{k+1} = < r_0 | r >
78  rho = Double(0);
79  for(int n=0; n < N; n++) {
80  rho += innerProduct(r0[n],r[n],s);
81  }
82 
83 
84  if( toBool( real(rho) == 0 ) && toBool( imag(rho) == 0 ) ) {
85  QDPIO::cout << "BiCGStab breakdown: rho = 0" << std::endl;
86  QDP_abort(1);
87  }
88 
89  // beta = ( rho_{k+1}/rho_{k})(alpha/omega)
90  Complex beta;
91  beta = ( rho / rho_prev ) * (alpha/omega);
92 
93 
94  // p = r + beta(p - omega v)
95 
96  // first work out p - omega v
97  // into tmp
98  // then do p = r + beta tmp
99  for(int n=0; n < N; n++) {
100  tmp[s] = p[n] - omega*v[n];
101  p[n][s] = r[n] + beta*tmp;
102  }
103 
104  // v = Ap
105  A(v,p,PLUS);
106 
107  // alpha = rho_{k+1} / < r_0 | v >
108 
109  // put <r_0 | v > into ctmp
110  Complex ctmp=Real(0);
111  for(int n = 0; n < N; n++) {
112  ctmp += innerProduct(r0[n],v[n],s);
113  }
114 
115  if( toBool( real(ctmp) == 0 ) && toBool( imag(ctmp) == 0 ) ) {
116  QDPIO::cout << "BiCGStab breakdown: <r_0|v> = 0" << std::endl;
117  QDP_abort(1);
118  }
119 
120  alpha = rho / ctmp;
121 
122  // Done with rho now, so save it into rho_prev
123  rho_prev = rho;
124 
125  // s = r - alpha v
126  // I can overlap s with r, because I recompute it at the end.
127  for(int n = 0; n < N; n++) {
128  r[n][s] -= alpha*v[n];
129  }
130 
131  // t = As = Ar
132  A(t,r,PLUS);
133 
134  // omega = < t | s > / < t | t > = < t | r > / norm2(t);
135 
136  // This does the full 5D norm
137  Real t_norm = norm2(t,s);
138 
139  if( toBool(t_norm == 0) ) {
140  QDPIO::cerr << "Breakdown || Ms || = || t || = 0 " << std::endl;
141  QDP_abort(1);
142  }
143 
144  // accumulate <t | s > = <t | r> into omega
145  omega = Real(0);
146  for(int n = 0; n < N; n++) {
147  omega += innerProduct(t[n],r[n],s);
148  }
149 
150  omega /= t_norm;
151 
152  // psi = psi + omega s + alpha p
153  // = psi + omega r + alpha p
154  //
155  // use tmp to compute psi + omega r
156  // then add in the alpha p
157  for(int n=0; n < N; n++) {
158  tmp[s] = psi[n] + omega*r[n];
159  psi[n][s] = tmp + alpha*p[n];
160  }
161 
162  // r = s - omega t = r - omega t => r -= omega_t
163  for(int n=0; n < N; n++){
164  r[n][s] -= omega*t[n];
165  }
166 
167  // Check convergence
168  Double r_norm = norm2(r, s);
169 
170  QDPIO::cout << "Iteration " << k << " : r = " << r_norm << std::endl;
171  if( toBool(r_norm < rsd_sq ) ) {
172  convP = true;
173  ret.resid = sqrt(r_norm);
174  ret.n_count = k;
175  }
176  else {
177  convP = false;
178  }
179  }
180 
181  if ( ret.n_count == MaxBiCGStab ) {
182  QDPIO::cerr << "Nonconvergence of BiCGStab. MaxIters reached " << std::endl;
183  }
184 
185  return ret;
186 }
187 
188 
189 // Fix here for now
190 template<>
191 SystemSolverResults_t
193  const multi1d<LatticeFermion>& chi,
194  multi1d<LatticeFermion>& psi,
195  const Real& RsdBiCGStab,
196  int MaxBiCGStab)
197 
198 
199 {
200  return InvBiCGStab_a(A, chi, psi, RsdBiCGStab, MaxBiCGStab);
201 }
202 
203 } // end namespace Chroma
Primary include file for CHROMA library code.
Linear Operator to arrays.
Definition: linearop.h:61
Conjugate-Gradient algorithm for a generic Linear Operator.
unsigned n
Definition: ldumul_w.cc:36
int t
Definition: meslate.cc:37
BinaryReturn< C1, C2, FnInnerProduct >::Type_t innerProduct(const QDPSubType< T1, C1 > &s1, const QDPType< T2, C2 > &s2)
static const LatticeInteger & beta(const int dim)
Definition: stag_phases_s.h:47
static const LatticeInteger & alpha(const int dim)
Definition: stag_phases_s.h:43
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
LatticeFermion tmp
Definition: mespbg5p_w.cc:36
LinOpSysSolverMGProtoClover::T T
SystemSolverResults_t InvBiCGStab(const LinearOperator< LatticeFermionF > &A, const LatticeFermionF &chi, LatticeFermionF &psi, const Real &RsdBiCGStab, int MaxBiCGStab, enum PlusMinus isign)
Definition: invbicgstab.cc:222
Real rsd_sq
Definition: invbicg.cc:121
@ PLUS
Definition: chromabase.h:45
multi1d< LatticeFermion > chi(Ncb)
Complex omega
Definition: invbicg.cc:97
LatticeFermion psi
Definition: mespbg5p_w.cc:35
SystemSolverResults_t InvBiCGStab_a(const LinearOperator< T > &A, const T &chi, T &psi, const Real &RsdBiCGStab, int MaxBiCGStab, enum PlusMinus isign)
Definition: invbicgstab.cc:12
A(A, psi, r, Ncb, PLUS)
Double zero
Definition: invbicg.cc:106
int k
Definition: invbicg.cc:119
multi1d< LatticeFermion > s(Ncb)
FloatingPoint< double > Double
Definition: gtest.h:7351
Double r_norm
Definition: pade_trln_w.cc:86
int r0
Definition: qtopcor.cc:41
Holds return info from SystemSolver call.
Definition: syssolver.h:17