CHROMA
unprec_ovext_linop_array_w.cc
Go to the documentation of this file.
1 /* $Id: unprec_ovext_linop_array_w.cc,v 3.0 2006-04-03 04:58:52 edwards Exp $
2 * \file
3 * \brief Unpreconditioned extended-Overlap (5D) (Naryanan&Neuberger) linear operator
4 */
5 
6 #include "chromabase.h"
9 namespace Chroma
10 {
11  //! Creation routine
12  /*! \ingroup fermact
13  *
14  * \param u_ gauge field (Read)
15  * \param WilsonMass_ DWF height (Read)
16  * \param m_q_ quark mass (Read)
17  */
18  void
20  const int Npoles_,
21  const Real& coeffP_,
22  const multi1d<Real>& resP_,
23  const multi1d<Real>& rootQ_,
24  const multi1d<Real>& beta_,
25  const Real& OverMass_,
26  const Real& Mass_,
27  const Real& b5_,
28  const Real& c5_)
29  {
30  Npoles = Npoles_;
31  N5 = 2*Npoles_ + 1;
32  R = (Real(1) + Mass_)/(Real(1)-Mass_);
33  alpha = b5_ + c5_;
34  a5 = b5_ - c5_;
35 
36  Dw.create(state, -OverMass_);
37  fbc = state->getFermBC();
38  coeffP = coeffP_;
39 
40  p_by_beta_sqrt.resize(Npoles);
41  q_sqrt.resize(Npoles);
42  beta.resize(Npoles);
43 
44  for(int i=0; i < Npoles; i++) {
45  beta[i] = beta_[i];
46  q_sqrt[i] = sqrt(rootQ_[i]*beta[i]);
47  p_by_beta_sqrt[i] = sqrt(resP_[i]*beta[i]);
48  }
49 
50 
51  }
52 
53 
54  //! Apply the operator onto a source std::vector
55  /*!
56  * The operator acts on the entire lattice
57  *
58  * \param psi Pseudofermion field (Read)
59  * \param isign Flag ( PLUS | MINUS ) (Read)
60  */
61  void
62  UnprecOvExtLinOpArray::operator() (multi1d<LatticeFermion>& chi,
63  const multi1d<LatticeFermion>& psi,
64  enum PlusMinus isign) const
65  {
66  START_CODE();
67 
68  if( chi.size() != N5 ) chi.resize(N5);
69  int G5 = Ns*Ns - 1;
70 
71  LatticeFermion tmp4; moveToFastMemoryHint(tmp4);
72 
73  Real q_sqrt_afive, two_q_sqrt, ftmp, Two;
74  Two = Real(2);
75 
76  switch (isign) {
77  case PLUS:
78  {
79  multi1d<LatticeFermion> tmp5(N5);
80  moveToFastMemoryHint(tmp5);
81 
82 
83  // Get a std::vector of wilson dirac op applications
84  for(int i=0; i < N5; i++) {
85  Dw(tmp5[i], psi[i], PLUS);
86  }
87 
88  // Start off Chi[N5-1]
89  // = [ 2 R gamma_5 + (R a5 + p0 alpha )gamma_5 Dw ] psi[N5-1]
90 
91  // 2 R gamma_5 psi_[N5-1]
92  chi[N5-1] = Gamma(G5)*psi[N5-1];
93  ftmp = Two*R;
94  chi[N5-1] *= ftmp;
95 
96  // gamma_5 Dw psi[N5-1]
97  tmp4 = Gamma(G5)*tmp5[N5-1];
98 
99  // (R a5 + p0) gamma_5 Dw psi[N5-1]
100  ftmp=(R*a5 + coeffP*alpha);
101  chi[N5-1] += ftmp*tmp4;
102 
103 
104 
105  // Loop through the length of the 5th D in steps of 2
106  // Keep count of the pole we are on with p
107  int p=0;
108  for(int i=0; i < N5-2; p++, i+=2) {
109 
110  q_sqrt_afive = q_sqrt[p]*a5;
111  two_q_sqrt = Two*q_sqrt[p];
112 
113  // first row of block
114  // chi[i] = -beta_p alpha H_w psi_i + sqrt(q_p)(2+a5 D_w) psi_i+1
115  // = 2 sqrt(q_p) psi_{i+1}
116  // + a5 sqrt(q_p) Dw psi{i+1}
117  // - beta_{i} alpha gamma_5 Dw psi{i}
118 
119  // First this part:
120  // = 2 sqrt(q_p) psi_{i+1}
121  // + a5 sqrt(q_p) Dw psi{i+1}
122  chi[i] = two_q_sqrt*psi[i+1] + q_sqrt_afive * tmp5[i+1];
123 
124  // Now - beta_{p} alpha gamma_5 Dw psi{i}
125  ftmp = alpha;
126  tmp4 = Gamma(G5)*tmp5[i];
127  chi[i] -= ftmp*tmp4;
128 
129 
130  // Second row of block:
131 
132  // chi[i+1] = sqrt(q_p)(2 + a5 D) psi_i
133  // + (alpha/beta) g5 D psi_{i+1}
134  // + sqrt(p_p/beta_p)(2 + a5 Dw) psi_{N5-1}
135  //
136  // = 2 sqrt(q_p) psi_i + 2 sqrt(p_p/beta_p)psi_{N5-1}
137  // + a5 sqrt(q_p) Dpsi_i + a5 sqrt(p_p/beta_p) Dpsi_{N5-1}
138  // + alpha/beta_p gamma_5 Dpsi_{i+1}
139 
140  // sqrt(p_p/beta_p) precomputed in p_by_beta_sqrt
141 
142  // First: 2 sqrt(q_p) psi_i + 2 sqrt(p_p/beta_p)psi_{N5-1}
143  ftmp = Two*p_by_beta_sqrt[p];
144  chi[i+1] = two_q_sqrt * psi[i] + ftmp*psi[N5-1];
145 
146  // Second: a5 sqrt(q_p) Dpsi_i + a5 sqrt(p_p/beta_p) Dpsi_{N5-1}
147  chi[i+1] += q_sqrt_afive*tmp5[i];
148  ftmp = a5*p_by_beta_sqrt[p];
149  chi[i+1] += ftmp*tmp5[N5-1];
150 
151  // Third: alpha/beta_p gamma_5 Dpsi_{i+1}
152  ftmp = alpha*beta[p];
153  tmp4 = Gamma(G5)*tmp5[i+1];
154  chi[i+1] += ftmp*tmp4;
155 
156 
157  // Update last row: -sqrt(p_p/beta_p)*(2+a5Dw)psi[i+1]
158  // = -2 sqrt(p_p/beta_p) psi_[i+1]
159  // -a5 sqrt(p_p/beta_p) Dw psi[i+1];
160  ftmp = Two*p_by_beta_sqrt[p];
161  chi[N5-1] -= ftmp*psi[i+1];
162  ftmp = a5*p_by_beta_sqrt[p];
163  chi[N5-1] -= ftmp*tmp5[i+1];
164 
165  }
166  }
167  break;
168 
169  case MINUS:
170  {
171  multi1d<LatticeFermion> tmp5_1(N5);
172  multi1d<LatticeFermion> tmp5_2(N5);
173 
174  moveToFastMemoryHint(tmp5_1);
175  moveToFastMemoryHint(tmp5_2);
176 
177  // Will need to multiply by D^{dagger]. Pull it outside.
178  // We collect 2 5D vectors. One to be multiplied by Dw^{dag}
179  // and one not.
180 
181  // We start with the N5-1th term.
182  // this is:
183  //
184  // [ R(2 + a5 Dw^dag)g5 + p0 alpha Hw = R(2 + a5D^dag)g5 + p0 alpha Dw^dag g5 ] psi[N5-1]
185  // = 2Rg5 psi[N5-1] + Dw^{dag}( R a5 + p0 alpha ) g5 psi[N5-1];
186  // tmp5_1[N5-1] = 2Rg5 psi[N5-1]
187  // tmp5_2[N5-1] = (R a5 + p0 alpha) g5 psi[N5-1]
188  tmp5_1[N5-1] = Gamma(G5)*psi[N5-1];
189  tmp5_2[N5-1] = tmp5_1[N5-1];
190  ftmp = Two*R;
191  tmp5_1[N5-1] *= ftmp;
192  ftmp = (R*a5 + coeffP*alpha);
193  tmp5_2[N5-1] *= ftmp;
194 
195  int p = 0;
196  for(int i=0; i < N5-1; i+=2, p++) {
197 
198  // first row: (chi[i] = tmp5_1_i + D^dag tmp5_2_i)
199  // chi[i] = -beta_p alpha Hw psi_i
200  // + sqrt(q_p)*(2 + a5 D^dag) psi_i+1
201  //
202  // = -beta_p alpha Ddag g_5 psi_i
203  // + 2 sqrt(q_p) psi_{i+1}
204  // + D^dag ( sqrt(q_p)*a5 * psi_{i+1} )
205 
206  // tmp5_1 [i] = 2 sqrt(q_p) psi_{i+1}
207  // tmp5_2 [i] = -beta_p alpha g_5 psi_i
208  // + a5 sqrt(q_p) psi[i+1]
209  //
210  two_q_sqrt = Two * q_sqrt[p];
211  q_sqrt_afive = a5* q_sqrt[p];
212 
213  tmp5_1[i] = two_q_sqrt*psi[i+1];
214 
215  tmp4 = Gamma(G5)*psi[i];
216  ftmp = alpha;
217  tmp5_2[i] = q_sqrt_afive*psi[i+1] - ftmp*tmp4;
218 
219 
220  // second row of block:
221  //
222  // chi[i+1] = sqrt(q_p) ( 2 + a5 D^dag) psi_i
223  // + alpha/beta_p H psi_{i+1}
224  // - sqrt(p_p/beta_p)( 2 + a5 D^dag) psi_N5-1
225  //
226  // = 2 sqrt(q_p) psi_i - 2 sqrt(p_p/beta_p)psi_N5-1
227  // + D^dag{ a5 sqrt(q_p) psi_i - a5 sqrt(p_p/beta_p) psi_N5-1
228  // + alpha/beta_p gamma_5 psi_{i+1}
229  //
230  // tmp5_1[i+1] = 2 sqrt(q_p) psi_i - 2 sqrt(p_p/beta_p) psi[N5-1]
231  //
232  // tmp5_2[i+1] = a5 sqrt(q_p) psi_i - a5 sqrt(p_p/beta_p) psi_N5-1
233  // + alpha/beta_p gamma_5 psi_{i+1}
234 
235  ftmp = Two*p_by_beta_sqrt[p];
236  tmp5_1[i+1] = two_q_sqrt * psi[i] - ftmp * psi[N5-1];
237 
238  ftmp = a5*p_by_beta_sqrt[p];
239  tmp5_2[i+1] = q_sqrt_afive*psi[i] - ftmp*psi[N5-1];
240  tmp4 = Gamma(G5)*psi[i+1];
241  ftmp = alpha*beta[p];
242  tmp5_2[i+1] += ftmp*tmp4;
243 
244  // Coupling term: sqrt(p_p/beta_p)(2 + a5 Ddag) psi[i+1]
245  //
246  // = 2 sqrt(p_p/beta_p) psi[i+1]
247  // + Ddag ( a5 sqrt(p_p/beta_p) ) psi_{i+1}
248  //
249  // tmp5_1[N5-1] = 2 sqrt(p_p/beta_p) psi[i+1]
250  // tmp5_2[N5-1] = a5 sqrt(p_p/beta_p) psi_{i+1}
251  ftmp = Two*p_by_beta_sqrt[p];
252  tmp5_1[N5-1] += ftmp*psi[i+1];
253 
254  ftmp = a5*p_by_beta_sqrt[p];
255  tmp5_2[N5-1] += ftmp *psi[i+1];
256  }
257 
258  // Vector Dirac op on tmp5_2
259  for(int i=0; i < N5; i++) {
260  Dw(chi[i], tmp5_2[i], MINUS);
261  chi[i]+=tmp5_1[i];
262  }
263 
264  }
265  break;
266  default:
267  QDPIO::cerr << "Unknown value for PLUS /MINUS: " << isign << std::endl;
268  QDP_abort(1);
269  };
270 
271  getFermBC().modifyF(chi);
272 
273  END_CODE();
274  }
275 
276 
277  //! Derivative
278  void
279  UnprecOvExtLinOpArray::deriv(multi1d<LatticeColorMatrix>& ds_u,
280  const multi1d<LatticeFermion>& chi, const multi1d<LatticeFermion>& psi,
281  enum PlusMinus isign) const
282  {
283  START_CODE();
284  QDPIO::cout << "Not yet implemented " << std::endl;
285  QDP_abort(1);
286 
287  getFermBC().zero(ds_u);
288 
289  END_CODE();
290  }
291 } // End Namespace Chroma
292 
Primary include file for CHROMA library code.
Support class for fermion actions and linear operators.
Definition: state.h:94
Class for counted reference semantics.
Definition: handle.h:33
void deriv(multi1d< LatticeColorMatrix > &ds_u, const multi1d< LatticeFermion > &chi, const multi1d< LatticeFermion > &psi, enum PlusMinus isign) const
Derivative.
const FermBC< T, P, Q > & getFermBC() const
Return the fermion BC object for this linear operator.
void operator()(multi1d< LatticeFermion > &chi, const multi1d< LatticeFermion > &psi, enum PlusMinus isign) const
Apply the operator onto a source std::vector.
void create(Handle< FermState< T, P, Q > > fs, const Real &Mass_)
Creation routine.
void create(Handle< FermState< T, P, Q > > fs, const int Npoles_, const Real &coeffP_, const multi1d< Real > &resP_, const multi1d< Real > &rootQ_, const multi1d< Real > &beta_, const Real &OverMass_, const Real &m_q_, const Real &b5_, const Real &c5_)
Creation routine.
Asqtad Staggered-Dirac operator.
Definition: klein_gord.cc:10
int G5
Definition: pbg5p_w.cc:57
int i
Definition: pbg5p_w.cc:55
@ MINUS
Definition: chromabase.h:45
@ PLUS
Definition: chromabase.h:45
multi1d< LatticeFermion > chi(Ncb)
LatticeFermion psi
Definition: mespbg5p_w.cc:35
START_CODE()
const WilsonTypeFermAct< multi1d< LatticeFermion > > Handle< const ConnectState > state
Definition: pbg5p_w.cc:28
Unpreconditioned extended-Overlap (5D) (Naryanan&Neuberger) linear operator.
Unpreconditioned Wilson fermion linear operator.