QUDA  0.9.0
dirac_clover.cpp
Go to the documentation of this file.
1 #include <iostream>
2 #include <dirac_quda.h>
3 #include <blas_quda.h>
4 #include <multigrid.h>
5 
6 namespace quda {
7 
10  {
11 #ifdef DYNAMIC_CLOVER
12  warningQuda("Dynamic clover generation/inversion is currently not supported for pure Wilson-Clover dslash.\n");
13 #endif
14  }
15 
18  {
19 #ifdef DYNAMIC_CLOVER
20  warningQuda("Dynamic clover generation/inversion is currently not supported for pure Wilson-Clover dslash.\n");
21 #endif
22  }
23 
25 
27  {
28  if (&dirac != this) {
30  clover = dirac.clover;
31  }
32  return *this;
33  }
34 
36  {
38 
39  if (out.Volume() != clover.VolumeCB()) {
40  errorQuda("Parity spinor volume %d doesn't match clover checkboard volume %d",
41  out.Volume(), clover.VolumeCB());
42  }
43  }
44 
47  const QudaParity parity, const ColorSpinorField &x,
48  const double &k) const
49  {
52 
54  FullClover cs(clover);
55  asymCloverDslashCuda(&static_cast<cudaColorSpinorField&>(out), *gauge, cs,
56  &static_cast<const cudaColorSpinorField&>(in), parity, dagger,
57  &static_cast<const cudaColorSpinorField&>(x), k, commDim, profile);
58  } else {
59  errorQuda("Not implemented");
60  }
61 
62  flops += 1872ll*in.Volume();
63  }
64 
65  // Public method to apply the clover term only
67  {
69  ApplyClover(out, in, clover, false, parity);
70  flops += 504ll*in.Volume();
71  }
72 
74  {
75  ColorSpinorField *In = &const_cast<ColorSpinorField&>(in);
76  if (in.Location() == QUDA_CPU_FIELD_LOCATION) {
79  param.fieldOrder = param.precision == QUDA_DOUBLE_PRECISION ? QUDA_FLOAT2_FIELD_ORDER :
81  param.gammaBasis = QUDA_UKQCD_GAMMA_BASIS;
83  *In = in;
84  }
85 
86  ColorSpinorField *Out = &out;
87  if (out.Location() == QUDA_CPU_FIELD_LOCATION) {
90  param.fieldOrder = param.precision == QUDA_DOUBLE_PRECISION ? QUDA_FLOAT2_FIELD_ORDER :
92  param.gammaBasis = QUDA_UKQCD_GAMMA_BASIS;
94  }
95 
96  checkFullSpinor(*Out, *In);
97  DslashXpay(Out->Odd(), In->Even(), QUDA_ODD_PARITY, In->Odd(), -kappa);
98  DslashXpay(Out->Even(), In->Odd(), QUDA_EVEN_PARITY, In->Even(), -kappa);
99 
100  if (in.Location() == QUDA_CPU_FIELD_LOCATION) delete In;
101  if (out.Location() == QUDA_CPU_FIELD_LOCATION) {
102  out = *Out;
103  delete Out;
104  }
105  }
106 
108  {
110 
111  bool reset = newTmp(&tmp1, in);
113 
114  M(*tmp1, in);
115  Mdag(out, *tmp1);
116 
117  deleteTmp(&tmp1, reset);
118  }
119 
122  const QudaSolutionType solType) const
123  {
124  if (solType == QUDA_MATPC_SOLUTION || solType == QUDA_MATPCDAG_MATPC_SOLUTION) {
125  errorQuda("Preconditioned solution requires a preconditioned solve_type");
126  }
127 
128  src = &b;
129  sol = &x;
130  }
131 
133  const QudaSolutionType solType) const
134  {
135  // do nothing
136  }
137 
138  void DiracClover::createCoarseOp(GaugeField &Y, GaugeField &X, GaugeField &Xinv, GaugeField &Yhat, const Transfer &T, double kappa, double mu, double mu_factor) const {
139  double a = 2.0 * kappa * mu * T.Vectors().TwistFlavor();
141  }
142 
145  {
146  // For the preconditioned operator, we need to check that the inverse of the clover term is present
147  if (!clover.cloverInv) errorQuda("Clover inverse required for DiracCloverPC");
148  }
149 
151 
153 
155  {
156  if (&dirac != this) {
158  }
159  return *this;
160  }
161 
162  // Public method
164  const QudaParity parity) const
165  {
167  ApplyClover(out, in, clover, true, parity);
168  flops += 504ll*in.Volume();
169  }
170 
171  // apply hopping term, then clover: (A_ee^-1 D_eo) or (A_oo^-1 D_oe),
172  // and likewise for dagger: (A_ee^-1 D^dagger_eo) or (A_oo^-1 D^dagger_oe)
173  // NOTE - this isn't Dslash dagger since order should be reversed!
175  const QudaParity parity) const
176  {
179 
181  FullClover cs(clover, true);
182  cloverDslashCuda(&static_cast<cudaColorSpinorField&>(out), *gauge, cs,
183  &static_cast<const cudaColorSpinorField&>(in), parity, dagger, 0, 0.0, commDim, profile);
184  } else {
185  errorQuda("Not supported");
186  }
187 
188  flops += 1824ll*in.Volume();
189  }
190 
191  // xpay version of the above
193  const QudaParity parity, const ColorSpinorField &x,
194  const double &k) const
195  {
198 
200  FullClover cs(clover, true);
201  cloverDslashCuda(&static_cast<cudaColorSpinorField&>(out), *gauge, cs,
202  &static_cast<const cudaColorSpinorField&>(in), parity, dagger,
203  &static_cast<const cudaColorSpinorField&>(x), k, commDim, profile);
204  } else {
205  errorQuda("Not supported");
206  }
207 
208  flops += 1872ll*in.Volume();
209  }
210 
211  // Apply the even-odd preconditioned clover-improved Dirac operator
213  {
214  double kappa2 = -kappa*kappa;
215  bool reset1 = newTmp(&tmp1, in);
216 
217  bool symmetric =(matpcType == QUDA_MATPC_EVEN_EVEN || matpcType == QUDA_MATPC_ODD_ODD) ? true : false;
218  int odd_bit = (matpcType == QUDA_MATPC_ODD_ODD || matpcType == QUDA_MATPC_ODD_ODD_ASYMMETRIC) ? 1 : 0;
219  QudaParity parity[2] = {static_cast<QudaParity>((1 + odd_bit) % 2), static_cast<QudaParity>((0 + odd_bit) % 2)};
220 
221  if (!symmetric) {
222  // DiracCloverPC::Dslash applies A^{-1}Dslash
223  Dslash(*tmp1, in, parity[0]);
224  // DiracClover::DslashXpay applies (A - kappa^2 D)
225  DiracClover::DslashXpay(out, *tmp1, parity[1], in, kappa2);
226  } else if (!dagger) { // symmetric preconditioning
227  Dslash(*tmp1, in, parity[0]);
228  DslashXpay(out, *tmp1, parity[1], in, kappa2);
229  } else { // symmetric preconditioning, dagger
230  CloverInv(out, in, parity[1]);
231  Dslash(*tmp1, out, parity[0]);
232  DiracWilson::DslashXpay(out, *tmp1, parity[1], in, kappa2);
233  }
234 
235  deleteTmp(&tmp1, reset1);
236  }
237 
239  {
240  // need extra temporary because of symmetric preconditioning dagger
241  // and for multi-gpu the input and output fields cannot alias
242  bool reset = newTmp(&tmp2, in);
243  M(*tmp2, in);
244  Mdag(out, *tmp2);
245  deleteTmp(&tmp2, reset);
246  }
247 
250  const QudaSolutionType solType) const
251  {
252  // we desire solution to preconditioned system
253  if (solType == QUDA_MATPC_SOLUTION || solType == QUDA_MATPCDAG_MATPC_SOLUTION) {
254  src = &b;
255  sol = &x;
256  return;
257  }
258 
259  bool reset = newTmp(&tmp1, b.Even());
260 
261  // we desire solution to full system
263  // src = A_ee^-1 (b_e + k D_eo A_oo^-1 b_o)
264  src = &(x.Odd());
265  CloverInv(*src, b.Odd(), QUDA_ODD_PARITY);
268  sol = &(x.Even());
269  } else if (matpcType == QUDA_MATPC_ODD_ODD) {
270  // src = A_oo^-1 (b_o + k D_oe A_ee^-1 b_e)
271  src = &(x.Even());
272  CloverInv(*src, b.Even(), QUDA_EVEN_PARITY);
275  sol = &(x.Odd());
277  // src = b_e + k D_eo A_oo^-1 b_o
278  src = &(x.Odd());
279  CloverInv(*tmp1, b.Odd(), QUDA_ODD_PARITY); // safe even when *tmp1 = b.odd
281  sol = &(x.Even());
283  // src = b_o + k D_oe A_ee^-1 b_e
284  src = &(x.Even());
285  CloverInv(*tmp1, b.Even(), QUDA_EVEN_PARITY); // safe even when *tmp1 = b.even
287  sol = &(x.Odd());
288  } else {
289  errorQuda("MatPCType %d not valid for DiracCloverPC", matpcType);
290  }
291 
292  // here we use final solution to store parity solution and parity source
293  // b is now up for grabs if we want
294 
295  deleteTmp(&tmp1, reset);
296 
297  }
298 
300  const QudaSolutionType solType) const
301  {
302  if (solType == QUDA_MATPC_SOLUTION || solType == QUDA_MATPCDAG_MATPC_SOLUTION) {
303  return;
304  }
305 
306  checkFullSpinor(x, b);
307 
308  bool reset = newTmp(&tmp1, b.Even());
309 
310  // create full solution
311 
314  // x_o = A_oo^-1 (b_o + k D_oe x_e)
316  CloverInv(x.Odd(), *tmp1, QUDA_ODD_PARITY);
317  } else if (matpcType == QUDA_MATPC_ODD_ODD ||
319  // x_e = A_ee^-1 (b_e + k D_eo x_o)
321  CloverInv(x.Even(), *tmp1, QUDA_EVEN_PARITY);
322  } else {
323  errorQuda("MatPCType %d not valid for DiracCloverPC", matpcType);
324  }
325 
326  deleteTmp(&tmp1, reset);
327 
328  }
329 
330  void DiracCloverPC::createCoarseOp(GaugeField &Y, GaugeField &X, GaugeField &Xinv, GaugeField &Yhat, const Transfer &T, double kappa, double mu, double mu_factor) const {
331  double a = - 2.0 * kappa * mu * T.Vectors().TwistFlavor();
332  CoarseOp(Y, X, Xinv, Yhat, T, *gauge, &clover, kappa, a, -mu_factor, QUDA_CLOVERPC_DIRAC, matpcType);
333  }
334 
335 } // namespace quda
unsigned long long flops
Definition: dirac_quda.h:100
double mu
Definition: test_util.cpp:1643
virtual void prepare(ColorSpinorField *&src, ColorSpinorField *&sol, ColorSpinorField &x, ColorSpinorField &b, const QudaSolutionType) const
const void * src
#define errorQuda(...)
Definition: util_quda.h:90
cudaGaugeField * gauge
Definition: dirac_quda.h:95
virtual void reconstruct(ColorSpinorField &x, const ColorSpinorField &b, const QudaSolutionType) const
double mu_factor[QUDA_MAX_MG_LEVEL]
Definition: test_util.cpp:1659
virtual void checkFullSpinor(const ColorSpinorField &, const ColorSpinorField &) const
Definition: dirac.cpp:129
virtual void MdagM(ColorSpinorField &out, const ColorSpinorField &in) const
const ColorSpinorField & Even() const
void deleteTmp(ColorSpinorField **, const bool &reset) const
Definition: dirac.cpp:64
const ColorSpinorField & Odd() const
static ColorSpinorField * Create(const ColorSpinorParam &param)
TimeProfile profile
Definition: dirac_quda.h:112
virtual void M(ColorSpinorField &out, const ColorSpinorField &in) const
DiracWilson & operator=(const DiracWilson &dirac)
void MdagM(ColorSpinorField &out, const ColorSpinorField &in) const
void cloverDslashCuda(cudaColorSpinorField *out, const cudaGaugeField &gauge, const FullClover &cloverInv, const cudaColorSpinorField *in, const int oddBit, const int daggerBit, const cudaColorSpinorField *x, const double &k, const int *commDim, TimeProfile &profile)
virtual ~DiracClover()
virtual void DslashXpay(ColorSpinorField &out, const ColorSpinorField &in, const QudaParity parity, const ColorSpinorField &x, const double &k) const
QudaGaugeParam param
Definition: pack_test.cpp:17
bool newTmp(ColorSpinorField **, const ColorSpinorField &) const
Definition: dirac.cpp:53
#define b
int commDim[QUDA_MAX_DIM]
Definition: dirac_quda.h:110
void reconstruct(ColorSpinorField &x, const ColorSpinorField &b, const QudaSolutionType) const
DiracClover & operator=(const DiracClover &dirac)
const ColorSpinorField & Vectors(QudaFieldLocation location=QUDA_CPU_FIELD_LOCATION) const
Definition: transfer.h:195
VOLATILE spinorFloat kappa
void asymCloverDslashCuda(cudaColorSpinorField *out, const cudaGaugeField &gauge, const FullClover &cloverInv, const cudaColorSpinorField *in, const int oddBit, const int daggerBit, const cudaColorSpinorField *x, const double &k, const int *commDim, TimeProfile &profile)
void Clover(ColorSpinorField &out, const ColorSpinorField &in, const QudaParity parity) const
cudaCloverField & clover
Definition: dirac_quda.h:236
void checkSpinorAlias(const ColorSpinorField &, const ColorSpinorField &) const
Definition: dirac.cpp:137
cpuColorSpinorField * in
virtual void DslashXpay(ColorSpinorField &out, const ColorSpinorField &in, const QudaParity parity, const ColorSpinorField &x, const double &k) const
#define warningQuda(...)
Definition: util_quda.h:101
#define checkLocation(...)
enum QudaSolutionType_s QudaSolutionType
QudaDagType dagger
Definition: dirac_quda.h:99
enum QudaParity_s QudaParity
void createCoarseOp(GaugeField &Y, GaugeField &X, GaugeField &Xinv, GaugeField &Yhat, const Transfer &T, double kappa, double mu=0., double mu_factor=0.) const
Create the coarse even-odd preconditioned clover operator. Unlike the Wilson operator, the coarsening of the preconditioned clover operator differs from that of the unpreconditioned clover operator, so we need to specialize it.
DiracCloverPC(const DiracParam &param)
void createCoarseOp(GaugeField &Y, GaugeField &X, GaugeField &Xinv, GaugeField &Yhat, const Transfer &T, double kappa, double mu=0., double mu_factor=0.) const
Create the coarse clover operator.
void DslashXpay(ColorSpinorField &out, const ColorSpinorField &in, const QudaParity parity, const ColorSpinorField &x, const double &k) const
double kappa
Definition: dirac_quda.h:96
QudaMatPCType matpcType
Definition: dirac_quda.h:98
DiracClover(const DiracParam &param)
Definition: dirac_clover.cpp:8
void Mdag(ColorSpinorField &out, const ColorSpinorField &in) const
Definition: dirac.cpp:73
QudaFieldLocation location
Definition: quda.h:27
GaugeCovDev * dirac
Definition: covdev_test.cpp:75
cpuColorSpinorField * out
void ApplyClover(ColorSpinorField &out, const ColorSpinorField &in, const CloverField &clover, bool inverse, int parity)
Apply clover-matrix field to a color-spinor field.
Definition: dslash_quda.cu:557
void M(ColorSpinorField &out, const ColorSpinorField &in) const
int VolumeCB() const
QudaTwistFlavorType TwistFlavor() const
void Dslash(ColorSpinorField &out, const ColorSpinorField &in, const QudaParity parity) const
void CoarseOp(GaugeField &Y, GaugeField &X, GaugeField &Xinv, GaugeField &Yhat, const Transfer &T, const cudaGaugeField &gauge, const cudaCloverField *clover, double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc)
Coarse operator construction from a fine-grid operator (Wilson / Clover)
Definition: coarse_op.cu:170
virtual void checkParitySpinor(const ColorSpinorField &, const ColorSpinorField &) const
Definition: dirac.cpp:89
DiracCloverPC & operator=(const DiracCloverPC &dirac)
void CloverInv(ColorSpinorField &out, const ColorSpinorField &in, const QudaParity parity) const
void prepare(ColorSpinorField *&src, ColorSpinorField *&sol, ColorSpinorField &x, ColorSpinorField &b, const QudaSolutionType) const
QudaParity parity
Definition: covdev_test.cpp:53
ColorSpinorField * tmp2
Definition: dirac_quda.h:102
#define a
void checkParitySpinor(const ColorSpinorField &, const ColorSpinorField &) const
ColorSpinorField * tmp1
Definition: dirac_quda.h:101