CHROMA
inv_minres_array.cc
Go to the documentation of this file.
1 
2 
3 #include "chromabase.h"
5 
6 namespace Chroma {
7 
8 template<typename T>
10  const multi1d<T>& chi,
11  multi1d<T>& psi,
12  const Real& RsdCG,
13  int MaxCG,
14  int& n_count)
15 {
16  START_CODE();
17 
18  // Compute v_1 = b - A x_0
19  int N5 = A.size();
20  const Subset& s = A.subset();
21 
22  multi1d<T> v(N5);
23  multi1d<T> Av(N5);
24 
25  A(Av, psi, PLUS);
26 
27  for(int n=0; n < N5; n++) {
28  v[n][s] = chi[n] - Av[n];
29  }
30 
31  // beta_1 = || v_1 || ; eta = beta_1
32  Real beta = sqrt(norm2(v,s));
33 
34  // r_norm_i = || b - A x || = beta_1
35  Real r_norm = beta;
36  Real b_norm = sqrt(norm2(chi, s));
37 
38  Real eta = beta;
39 
40  // gamma_1 = gamma_0 = 1
41  Complex gamma, gamma_prev;
42  gamma = Real(1); gamma_prev = Real(1);
43 
44  // sigma1 = sigma_0 = 0;
45  Complex sigma , sigma_prev;
46  sigma = Real(0);
47  sigma_prev = Real(0);
48 
49  // v_0 = 0; w_0 = w_1 = 0
50  multi1d<T> v_prev(N5);
51 
52  multi1d<T> w_prev(N5);
53  multi1d<T> w_2prev(N5);
54 
55  for(int n = 0; n < N5; n++) {
56  v_prev[n][s] = zero;
57  w_prev[n][s] = zero;
58  w_2prev[n][s] = zero;
59  }
60 
61  bool convP = false;
62 
63  // Do the iteration proper
64  for(int k = 1; k < MaxCG && !convP; k++) {
65 
66  // v_i = 1 / beta_i
67  Real ffactor = Real(1)/beta;
68  for(int n=0; n < N5; n++) {
69  v[n][s] *= ffactor;
70  }
71 
72  // alpha_i = < v_i, A v_i >
73  A(Av, v, PLUS);
74 
75  Complex alpha = Real(0);
76  for(int n=0; n < N5; n++) {
77  alpha += innerProduct(v[n], Av[n], s);
78  }
79 
80 
81  // v_{i+1} = Av_{i} - alpha_i v_i - beta_i * v_{i-1}
82  multi1d<T> v_plus(N5);
83  for(int n=0; n < N5; n++) {
84  v_plus[n][s] = Av[n] - alpha*v[n];
85  v_plus[n][s] -= beta * v_prev[n];
86  }
87 
88  // beta_{i+1} = || v_{i+1} ||
89  // proper 5D norm I think
90  Real beta_plus = sqrt(norm2(v_plus, s));
91 
92 
93  // QR Part
94  Complex delta;
95 
96  // delta = gamma_i alpha_i - gamma_{i-1}*sigma_{i}*beta_{i}
97  delta = gamma * alpha - gamma_prev*sigma*beta;
98 
99  // rho_1 = sqrt( delta*2 + beta^2_{i+1}
100  Real rho_1;
101  rho_1 = sqrt( real(conj(delta)*delta) + beta_plus*beta_plus );
102 
103  // rho_2 = sigma_i*alpha_i + gamma_{i-1}*gamma_i*beta_i
104  Complex rho_2;
105  rho_2 = sigma*alpha + gamma_prev*gamma*beta;
106 
107  // rho_3 = sigma_{i-1} * beta_i
108  Complex rho_3;
109  rho_3 = sigma_prev * beta;
110 
111  Complex gamma_plus = delta / rho_1;
112  Real sigma_plus = beta_plus / rho_1;
113 
114  multi1d<T> w(N5);
115  // w_i = (v_i - rho_3*w_{i-2} - rho_2*w_{i-1})/rho_1
116  for(int n=0; n < N5; n++) {
117  w[n][s] = v[n] - rho_3*w_2prev[n];
118  w[n][s] -= rho_2*w_prev[n];
119  ffactor = Real(1)/rho_1;
120  w[n][s] *= ffactor;
121  }
122 
123  // x_{i} = x_{i-1} + gamma_{i+1}*eta* w_[i}
124  // x in this case is psi
125  Complex factor = gamma_plus*eta;
126  for(int n=0; n < N5; n++) {
127  psi[n][s] += factor*w[n];
128  }
129 
130  // || r_i || = | sigma_plus | || r_{i-1} ||
131  r_norm *= fabs(sigma_plus) ;
132 
133 
134  // Check convergence
135  // QDPIO::cout << "MINRES: iter " << k << " || r || = " << r_norm << std::endl;
136  if( toBool( r_norm < RsdCG*b_norm ) ) {
137  convP = true;
138  END_CODE();
139  return;
140  }
141 
142  // eta = -sigma_{i+1}*eta
143  eta *= -sigma_plus;
144 
145  // Now back everything up
146  // v_prev = v
147  // w_2prev = w_prev
148  // w_prev = w
149  //
150  for(int n=0; n < N5; n++) {
151  v_prev[n][s] = v[n];
152  v[n][s] = v_plus[n];
153  w_2prev[n][s] = w_prev[n];
154  w_prev[n][s] = w[n];
155  }
156 
157  // beta_i <- beta_{i+1}
158  beta = beta_plus;
159 
160  // gamma_{i-1} <- gamma_{i}
161  gamma_prev = gamma;
162 
163  // gamma_{i} <- gamma_{i+1}
164  gamma = gamma_plus;
165 
166  // sigma_{i-1} <- sigma_{i}
167  sigma_prev = sigma;
168 
169  // sigma_{i} <- sigma_{i+1}
170  sigma = sigma_plus;
171 
172  n_count = k;
173  }
174 
175  END_CODE();
176 }
177 
178 
179 template<>
181  const multi1d<LatticeFermion>& chi,
182  multi1d<LatticeFermion>& psi,
183  const Real& RsdCG,
184  int MaxCG,
185  int& n_count)
186 {
188 }
189 
190 } // end namespace Chroma
Primary include file for CHROMA library code.
Linear Operator to arrays.
Definition: linearop.h:61
unsigned n
Definition: ldumul_w.cc:36
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
const WilsonTypeFermAct< multi1d< LatticeFermion > > Handle< const ConnectState > const multi1d< Real > enum InvType invType const multi1d< Real > & RsdCG
Definition: pbg5p_w.cc:30
void InvMINRES(const LinearOperatorArray< LatticeFermion > &A, const multi1d< LatticeFermion > &chi, multi1d< LatticeFermion > &psi, const Real &RsdCG, int MaxCG, int &n_count)
int n_count
Definition: invbicg.cc:78
const WilsonTypeFermAct< multi1d< LatticeFermion > > Handle< const ConnectState > const multi1d< Real > enum InvType invType const multi1d< Real > int MaxCG
Definition: pbg5p_w.cc:32
@ PLUS
Definition: chromabase.h:45
multi1d< LatticeFermion > chi(Ncb)
LatticeFermion psi
Definition: mespbg5p_w.cc:35
LatticeFermion eta
Definition: mespbg5p_w.cc:37
START_CODE()
A(A, psi, r, Ncb, PLUS)
void InvMINRES_a(const LinearOperatorArray< T > &A, const multi1d< T > &chi, multi1d< T > &psi, const Real &RsdCG, int MaxCG, int &n_count)
Double zero
Definition: invbicg.cc:106
int k
Definition: invbicg.cc:119
multi1d< LatticeFermion > s(Ncb)
Double r_norm
Definition: pade_trln_w.cc:86