CHROMA
unprec_graphene_linop_w.cc
Go to the documentation of this file.
1 /*! \file
2  * \brief Unpreconditioned Graphene fermion linear operator.
3  *
4  * This formulation follows Borici's variant of Creutz's graphene
5  * fermion construction. Borici's variant is described in
6  * arXiv:0712.4401 and Cruetz's original construction is described
7  * in arXiv:0712.1201
8  */
9 
10 #include "chromabase.h"
12 
13 using namespace QDP::Hints;
14 
15 namespace Chroma
16 {
17  //! Creation routine
18  /*!
19  * \param u_ gauge field (Read)
20  * \param Mass_ fermion kappa (Read)
21  */
22  void UnprecGrapheneLinOp::create(Handle< FermState<T,P,Q> > fs,
23  const Real& Mass_)
24  {
25  AnisoParam_t anisoParam;
26  create(fs, Mass_, anisoParam);
27  }
28 
29 
30  //! Creation routine with Anisotropy
31  /*!
32  * \param u_ gauge field (Read)
33  * \param Mass_ fermion kappa (Read)
34  * \param aniso anisotropy struct (Read)
35  */
36  void UnprecGrapheneLinOp::create(Handle< FermState<T,P,Q> > fs,
37  const Real& Mass_,
38  const AnisoParam_t& aniso_)
39  {
40  START_CODE();
41 
42  Mass = Mass_;
43  anisoParam = aniso_;
44  fbc = fs->getFermBC();
45  u = fs->getLinks();
46 
47  // Sanity checks
48  if (fbc.operator->() == 0)
49  {
50  QDPIO::cerr << "GrapheneLinOp: error: fbc is null" << std::endl;
51  QDP_abort(1);
52  }
53 
54  // Insist on this for graphene
55  if (QDP::Nd != 4 || QDP::Ns != 4)
56  {
57  QDPIO::cerr << "GrapheneLinOp: requires Nd=4 and Ns=4" << std::endl;
58  QDP_abort(1);
59 
60  }
61 
62  // For the moment, I'm hesitant to turn on anisotropy. I think the
63  // construction of graphene goes through in this case. The point
64  // is that the *fermion* anisotropy (really gamma_f=xi_0/nu in my
65  // new language) is what is tuned so the spatial and temporal lattice
66  // spacing are equal once the anisotropy factor is restored. However,
67  // this all could stand some more thought, so disable it here.
68  if (anisoParam.anisoP)
69  {
70  QDPIO::cerr << "UnprecGraphene: not fully supporting anisotropy at this moment" << std::endl;
71  QDPIO::cerr << "UnprecGraphene: only this one check is stopping it from functioning; otherwise, the code is in place." << std::endl;
72  QDP_abort(1);
73  }
74 
75  Real ff;
76  if (anisoParam.anisoP)
77  ff = anisoParam.nu / anisoParam.xi_0;
78  else
79  ff = Real(1);
80 
81  if (anisoParam.anisoP)
82  {
83  // Rescale the u fields by the anisotropy
84  for(int mu=0; mu < u.size(); ++mu)
85  {
86  if (mu != anisoParam.t_dir)
87  u[mu] *= ff;
88  }
89  }
90 
91  // This is Borici's "alpha" matrix. Here, Nd must be 4.
92  alpha.resize(Nd,Nd);
93 
94  for(int mu=0; mu < Nd; ++mu)
95  {
96  for(int nu=0; nu < Nd; ++nu)
97  {
98  alpha(mu,nu) = (mu == nu) ? 1 : -1;
99  }
100  }
101 
102  END_CODE();
103  }
104 
105 
106  // Form gamma_mu * psi
107  void UnprecGrapheneLinOp::gammaMults(multi1d<LatticeFermion>& gams,
108  const LatticeFermion& psi) const
109  {
110  gams.resize(Nd); moveToFastMemoryHint(gams);
111 
112  // Build gamma matrix multiplied pieces
113  gams[0] = GammaConst<Ns,1>()*psi;
114  gams[1] = GammaConst<Ns,2>()*psi;
115  gams[2] = GammaConst<Ns,4>()*psi;
116  gams[3] = GammaConst<Ns,8>()*psi;
117  }
118 
119 
120  // Hop terms
121  void UnprecGrapheneLinOp::iGamMu(LatticeFermion& iGam,
122  const multi1d<LatticeFermion>& gams,
123  int mu) const
124  {
125  LatticeFermion tmp2; moveToFastMemoryHint(tmp2);
126 
127  // The Gamma piece. This will be shift later. Unroll the loop.
128  // Flops could be saved here since some pieces are re-added again
129  // because of the similar sign structure of alpha.
130  tmp2 = Real(alpha(mu,0))*gams[0];
131  for(int nu=1; nu < Nd; ++nu)
132  tmp2 += Real(alpha(mu,nu))*gams[nu];
133 
134  // i*Gamma_mu * psi
135  iGam = timesI(tmp2);
136  }
137 
138 
139  //! Apply unpreconditioned Graphene fermion linear operator
140  /*!
141  * \ingroup linop
142  *
143  * The operator acts on the entire lattice
144  *
145  * \param chi Pseudofermion field (Read)
146  * \param psi Pseudofermion field (Read)
147  * \param isign Flag ( PLUS | MINUS ) (Read)
148  */
149  void UnprecGrapheneLinOp::operator() (LatticeFermion& chi, const LatticeFermion& psi,
150  enum PlusMinus isign) const
151  {
152  START_CODE();
153 
154  //
155  // Chi = (Nd+Mass)*Psi - (1/2) * D' Psi
156  //
157  multi1d<LatticeFermion> gams;
158  LatticeFermion tmp2; moveToFastMemoryHint(tmp2);
159  LatticeFermion tmp3; moveToFastMemoryHint(tmp3);
160  LatticeFermion iGam; moveToFastMemoryHint(iGam);
161  Real half = 0.5;
162 
163  // Build gamma matrix multiplied pieces
164  gammaMults(gams, psi);
165 
166  // Mass term piece. Unroll.
167  tmp2 = gams[0];
168  for(int mu=1; mu < Nd; ++mu)
169  tmp2 += gams[mu];
170 
171  chi = timesI(tmp2);
172 
173  // Hop pieces
174  for(int mu=0; mu < Nd; ++mu)
175  {
176  // Unshifted hop terms
177  iGamMu(iGam, gams, mu);
178 
179  // Forward piece.
180  tmp2 = iGam + gams[mu];
181  tmp3 = u[mu] * shift(tmp2, FORWARD, mu);
182  chi += half * tmp3;
183 
184  // Backward piece.
185  tmp2 = iGam - gams[mu];
186  tmp3 = adj(u[mu]) * tmp2;
187  chi += half * shift(tmp3, BACKWARD, mu);
188  }
189 
190  if (isign == MINUS)
191  chi = -chi;
192 
193  chi += Mass*psi;
194 
195  getFermBC().modifyF(chi);
196 
197  END_CODE();
198  }
199 
200 
201 
202  //! Derivative of unpreconditioned Graphene dM/dU
203  /*!
204  * \param chi left std::vector on cb (Read)
205  * \param psi right std::vector on 1-cb (Read)
206  * \param isign D'^dag or D' ( MINUS | PLUS ) resp. (Read)
207  * \param cb Checkerboard of chi std::vector (Read)
208  *
209  * \return Computes \f$\chi^\dag * \dot(D} * \psi\f$
210  */
211  void
212  UnprecGrapheneLinOp::deriv(multi1d<LatticeColorMatrix>& ds_u,
213  const LatticeFermion& chi, const LatticeFermion& psi,
214  enum PlusMinus isign) const
215  {
216  START_CODE();
217 
218  ds_u.resize(Nd);
219 
220  // Fold in the 1/2 from the front of the hop terms here.
221  multi1d<Real> anisoWeights(Nd);
222  anisoWeights = 0.5;
223 
224  Real ff = where(anisoParam.anisoP, anisoParam.nu / anisoParam.xi_0, Real(1));
225 
226  if (anisoParam.anisoP)
227  {
228  // Set the weights
229  for(int mu=0; mu < Nd; ++mu)
230  {
231  if (mu != anisoParam.t_dir)
232  anisoWeights[mu] *= ff;
233  }
234  }
235 
236  // Build gamma matrix multiplied pieces
237  multi1d<LatticeFermion> gams;
238  LatticeFermion tmp2; moveToFastMemoryHint(tmp2);
239  LatticeFermion iGam; moveToFastMemoryHint(iGam);
240 
241  gammaMults(gams, psi);
242 
243  for(int mu = 0; mu < Nd; ++mu)
244  {
245  // Unshifted hop terms
246  iGamMu(iGam, gams, mu);
247 
248  switch (isign)
249  {
250  case PLUS:
251  {
252  // Forward piece.
253  tmp2 = iGam + gams[mu];
254  }
255  break;
256 
257  case MINUS:
258  {
259  // Backward piece.
260  // NOTE: This is confusing. There is no derivative of the U^dag, just the U.
261  // However, we take D^dag here so this is gamma_5*D*gamma_5. For the non-mass
262  // term, this is just -D. So, the derivative still picks up just for the forward
263  // term, but with a minus sign.
264  tmp2 = iGam + gams[mu];
265  tmp2 = -tmp2;
266  }
267  break;
268 
269  default:
270  QDP_error_exit("unknown case");
271  }
272 
273  // This is the forward piece
274  LatticeFermion tmp3 = shift(tmp2, FORWARD, mu);
275 
276  // This step supposedly optimised in QDP++
277  LatticeColorMatrix temp_mat = traceSpin(outerProduct(tmp3,chi));
278 
279  // Just do the bit we need.
280  ds_u[mu] = anisoWeights[mu] * temp_mat;
281  }
282 
283  getFermBC().zero(ds_u);
284 
285  END_CODE();
286  }
287 
288 
289  //! Return flops performed by the operator()
290  unsigned long UnprecGrapheneLinOp::nFlops() const
291  {
292  // This is not quite right, but I don't think it's miles off.
293  unsigned long site_flops = 4*Nc*Ns + 2*(10*Nc*Ns+8*264);
294  return site_flops*Layout::sitesOnNode();
295  }
296 
297 } // End Namespace Chroma
Primary include file for CHROMA library code.
#define END_CODE()
Definition: chromabase.h:65
#define START_CODE()
Definition: chromabase.h:64
Support class for fermion actions and linear operators.
Definition: state.h:94
Class for counted reference semantics.
Definition: handle.h:33
int mu
Definition: cool.cc:24
int nu
Definition: cool.cc:25
Real Mass
Nd
Definition: meslate.cc:74
Double tmp2
Definition: mesq.cc:30
Double tmp3
Definition: mesq.cc:31
multi1d< Hadron2PtContraction_t > operator()(const multi1d< LatticeColorMatrix > &u)
static const LatticeInteger & alpha(const int dim)
Definition: stag_phases_s.h:43
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)
static multi1d< LatticeColorMatrix > u
@ MINUS
Definition: chromabase.h:45
@ PLUS
Definition: chromabase.h:45
chi
Definition: pade_trln_w.cc:24
psi
Definition: pade_trln_w.cc:191
#define FORWARD
Definition: primitives.h:82
#define BACKWARD
Definition: primitives.h:83
Parameters for anisotropy.
Definition: aniso_io.h:24
multi1d< LatticeColorMatrix > deriv(const EvenOddPrecLinearOperator< LatticeFermion, multi1d< LatticeColorMatrix >, multi1d< LatticeColorMatrix > > &AP, const LatticeFermion &chi, const LatticeFermion &psi, enum PlusMinus isign)
Apply the operator onto a source std::vector.
Unpreconditioned Graphene fermion linear operator.