QUDA  0.9.0
dirac_twisted_clover.cpp
Go to the documentation of this file.
1 #include <dirac_quda.h>
2 #include <blas_quda.h>
3 #include <iostream>
4 #include <multigrid.h>
5 
6 namespace quda {
7 
9  : DiracWilson(param, nDim), mu(param.mu), epsilon(param.epsilon), clover(*(param.clover)) { }
10 
12  : DiracWilson(dirac), mu(dirac.mu), epsilon(dirac.epsilon), clover(dirac.clover) { }
13 
15 
17  {
18  if (&dirac != this)
19  {
21  clover = dirac.clover;
22  }
23 
24  return *this;
25  }
26 
28  {
30 
31  if (out.Volume() != clover.VolumeCB())
32  errorQuda("Parity spinor volume %d doesn't match clover checkboard volume %d", out.Volume(), clover.VolumeCB());
33  }
34 
35  // Protected method for applying twist
37  {
39  ApplyTwistClover(out, in, clover, kappa, mu, 0.0, parity, dagger, twistType);
40 
41  if (twistType == QUDA_TWIST_GAMMA5_INVERSE) flops += 1056ll*in.Volume();
42  else flops += 552ll*in.Volume();
43  }
44 
45 
46  // Public method to apply the twist
48  {
50  }
51 
53  {
55  if (in.TwistFlavor() != out.TwistFlavor())
56  errorQuda("Twist flavors %d %d don't match", in.TwistFlavor(), out.TwistFlavor());
57 
58  if (in.TwistFlavor() == QUDA_TWIST_NO || in.TwistFlavor() == QUDA_TWIST_INVALID) {
59  errorQuda("Twist flavor not set %d\n", in.TwistFlavor());
60  }
61 
62  // We can eliminate this temporary at the expense of more kernels (like clover)
63  ColorSpinorField *tmp=0; // this hack allows for tmp2 to be full or parity field
64  if (tmp2) {
65  if (tmp2->SiteSubset() == QUDA_FULL_SITE_SUBSET) tmp = &(tmp2->Even());
66  else tmp = tmp2;
67  }
68  bool reset = newTmp(&tmp, in.Even());
69 
70  FullClover *cs = new FullClover(clover, false);
71  FullClover *cI = new FullClover(clover, true);
72 
73  if(in.TwistFlavor() == QUDA_TWIST_SINGLET){
74  double a = 2.0 * kappa * mu;//for direct twist (must be daggered separately)
75  twistedCloverDslashCuda(&static_cast<cudaColorSpinorField&>(out.Odd()),
76  *gauge, cs, cI, &static_cast<const cudaColorSpinorField&>(in.Even()),
77  QUDA_ODD_PARITY, dagger, &static_cast<const cudaColorSpinorField&>(in.Odd()),
79  twistedCloverDslashCuda(&static_cast<cudaColorSpinorField&>(out.Even()),
80  *gauge, cs, cI, &static_cast<const cudaColorSpinorField&>(in.Odd()),
81  QUDA_EVEN_PARITY, dagger, &static_cast<const cudaColorSpinorField&>(in.Even()),
83  flops += (1320ll+552ll)*in.Volume();
84  } else {
85  errorQuda("Non-deg twisted clover not implemented yet");
86  }
87  deleteTmp(&tmp, reset);
88  delete cs;
89  delete cI;
90  }
91 
93  {
95  bool reset = newTmp(&tmp1, in);
96 
97  M(*tmp1, in);
98  Mdag(out, *tmp1);
99 
100  deleteTmp(&tmp1, reset);
101  }
102 
105  const QudaSolutionType solType) const
106  {
107  if (solType == QUDA_MATPC_SOLUTION || solType == QUDA_MATPCDAG_MATPC_SOLUTION) {
108  errorQuda("Preconditioned solution requires a preconditioned solve_type");
109  }
110 
111  src = &b;
112  sol = &x;
113  }
114 
116  const QudaSolutionType solType) const
117  {
118  // do nothing
119  }
120 
121  void DiracTwistedClover::createCoarseOp(GaugeField &Y, GaugeField &X, GaugeField &Xinv, GaugeField &Yhat, const Transfer &T, double kappa, double mu, double mu_factor) const {
122  double a = 2.0 * kappa * mu * T.Vectors().TwistFlavor();
124  }
125 
127 
129 
131  {
132 
133  }
134 
136  {
137  if (&dirac != this) {
139  }
140  return *this;
141  }
142 
143  // Public method to apply the inverse twist
145  {
147  }
148 
149  // apply hopping term, then inverse twist: (A_ee^-1 D_eo) or (A_oo^-1 D_oe),
150  // and likewise for dagger: (D^dagger_eo D_ee^-1) or (D^dagger_oe A_oo^-1)
153  {
154  checkParitySpinor(in, out);
155  checkSpinorAlias(in, out);
156 
157  if (in.TwistFlavor() != out.TwistFlavor())
158  errorQuda("Twist flavors %d %d don't match", in.TwistFlavor(), out.TwistFlavor());
160  errorQuda("Twist flavor not set %d\n", in.TwistFlavor());
161 
162  FullClover *cs = new FullClover(clover, false);
163  FullClover *cI = new FullClover(clover, true);
164 
165  if (in.TwistFlavor() == QUDA_TWIST_SINGLET) {
166  double a = -2.0 * kappa * mu; //for invert twist (not daggered)
167  double b = 1.;// / (1.0 + a*a); //for invert twist
168  if (!dagger || matpcType == QUDA_MATPC_EVEN_EVEN_ASYMMETRIC || matpcType == QUDA_MATPC_ODD_ODD_ASYMMETRIC) {
169  twistedCloverDslashCuda(&static_cast<cudaColorSpinorField&>(out), *gauge, cs, cI,
170  &static_cast<const cudaColorSpinorField&>(in), parity, dagger, 0,
171  QUDA_DEG_DSLASH_CLOVER_TWIST_INV, a, b, 0.0, 0.0, commDim, profile);
172 
173  flops += 2376ll*in.Volume();
174  } else {
175  twistedCloverDslashCuda(&static_cast<cudaColorSpinorField&>(out), *gauge, cs, cI,
176  &static_cast<const cudaColorSpinorField&>(in), parity, dagger, 0,
177  QUDA_DEG_CLOVER_TWIST_INV_DSLASH, a, b, 0.0, 0.0, commDim, profile);
178  flops += 1320ll*in.Volume();
179  }
180  } else {//TWIST doublet :
181  errorQuda("Non-degenerate DiracTwistedCloverPC is not implemented \n");
182  }
183  delete cs;
184  delete cI;
185  }
186 
187  // xpay version of the above
189  (ColorSpinorField &out, const ColorSpinorField &in, const QudaParity parity, const ColorSpinorField &x, const double &k) const
190  {
191  checkParitySpinor(in, out);
192  checkSpinorAlias(in, out);
193  if (in.TwistFlavor() != out.TwistFlavor())
194  errorQuda("Twist flavors %d %d don't match", in.TwistFlavor(), out.TwistFlavor());
196  errorQuda("Twist flavor not set %d\n", in.TwistFlavor());
197 
198  FullClover *cs = new FullClover(clover, false);
199  FullClover *cI = new FullClover(clover, true);
200 
202  double a = -2.0 * kappa * in.TwistFlavor() * mu; //for invert twist
203  // double b = k / (1.0 + a*a); //for invert twist NO HABRÍA QUE APLICAR CLOVER_TWIST_INV???
204  double b = k; //for invert twist NO HABRÍA QUE APLICAR CLOVER_TWIST_INV???
205  if (!dagger) {
206  twistedCloverDslashCuda(&static_cast<cudaColorSpinorField&>(out), *gauge, cs, cI,
207  &static_cast<const cudaColorSpinorField&>(in), parity, dagger,
208  &static_cast<const cudaColorSpinorField&>(x),
209  QUDA_DEG_DSLASH_CLOVER_TWIST_INV, a, b, 0.0, 0.0, commDim, profile);
210 
211  flops += 2400ll*in.Volume();
212  } else { // tmp1 can alias in, but tmp2 can alias x so must not use this
213  twistedCloverDslashCuda(&static_cast<cudaColorSpinorField&>(out), *gauge, cs, cI,
214  &static_cast<const cudaColorSpinorField&>(in), parity, dagger,
215  &static_cast<const cudaColorSpinorField&>(x),
216  QUDA_DEG_CLOVER_TWIST_INV_DSLASH, a, b, 0.0, 0.0, commDim, profile);
217 
218  flops += 1344ll*in.Volume();
219  }
220  } else {//TWIST_DOUBLET:
221  errorQuda("Non-degenerate DiracTwistedCloverPC is not implemented \n");
222  }
223  delete cs;
224  delete cI;
225  }
226 
228  {
229  double kappa2 = -kappa*kappa;
230  bool reset = newTmp(&tmp1, in);
231 
232  bool symmetric =(matpcType == QUDA_MATPC_EVEN_EVEN || matpcType == QUDA_MATPC_ODD_ODD) ? true : false;
233  int odd_bit = (matpcType == QUDA_MATPC_ODD_ODD || matpcType == QUDA_MATPC_ODD_ODD_ASYMMETRIC) ? 1 : 0;
234  QudaParity parity[2] = {static_cast<QudaParity>((1 + odd_bit) % 2), static_cast<QudaParity>((0 + odd_bit) % 2)};
235 
236  FullClover *cs = new FullClover(clover, false);
237  FullClover *cI = new FullClover(clover, true);
238 
239  if (in.TwistFlavor() == QUDA_TWIST_SINGLET) {
240  if (symmetric) {
241  if (dagger) {
242  TwistCloverInv(*tmp1, in, parity[1]);
243  Dslash(out, *tmp1, parity[0]);
244  TwistCloverInv(*tmp1, out, parity[0]);
245  DslashXpay(out, *tmp1, parity[1], in, kappa2);
246  } else {
247  Dslash(*tmp1, in, parity[0]);
248  DslashXpay(out, *tmp1, parity[1], in, kappa2);
249  }
250  } else { // asymmetric preconditioning
251  double a = 2.0 * kappa * in.TwistFlavor() * mu;
252  Dslash(*tmp1, in, parity[0]);
253  twistedCloverDslashCuda(&static_cast<cudaColorSpinorField&>(out), *gauge, cs, cI,
254  static_cast<cudaColorSpinorField*>(tmp1), parity[1], dagger,
255  &static_cast<const cudaColorSpinorField&>(in),
256  QUDA_DEG_DSLASH_CLOVER_TWIST_XPAY, a, kappa2, 0.0, 0.0, commDim, profile);
257 
258  flops += (1320ll+96ll)*in.Volume();
259  }
260  } else { //Twist doublet
261  errorQuda("Non-degenerate DiracTwistedCloverPC is not implemented \n");
262  }
263 
264  deleteTmp(&tmp1, reset);
265  }
266 
268  {
269  // need extra temporary because of symmetric preconditioning dagger
270  bool reset = newTmp(&tmp2, in);
271  M(*tmp2, in);
272  Mdag(out, *tmp2);
273  deleteTmp(&tmp2, reset);
274  }
275 
278  const QudaSolutionType solType) const
279  {
280  // we desire solution to preconditioned system
281  if (solType == QUDA_MATPC_SOLUTION || solType == QUDA_MATPCDAG_MATPC_SOLUTION) {
282  src = &b;
283  sol = &x;
284  return;
285  }
286 
287  bool reset = newTmp(&tmp1, b.Even());
288 
289  // we desire solution to full system
290  if(b.TwistFlavor() == QUDA_TWIST_SINGLET) {
292  // src = A_ee^-1 (b_e + k D_eo A_oo^-1 b_o)
293  src = &(x.Odd());
297  sol = &(x.Even());
298  } else if (matpcType == QUDA_MATPC_ODD_ODD) {
299  // src = A_oo^-1 (b_o + k D_oe A_ee^-1 b_e)
300  src = &(x.Even());
304  sol = &(x.Odd());
306  // src = b_e + k D_eo A_oo^-1 b_o
307  src = &(x.Odd());
308  TwistCloverInv(*tmp1, b.Odd(), QUDA_ODD_PARITY); // safe even when *tmp1 = b.odd
310  sol = &(x.Even());
312  // src = b_o + k D_oe A_ee^-1 b_e
313  src = &(x.Even());
314  TwistCloverInv(*tmp1, b.Even(), QUDA_EVEN_PARITY); // safe even when *tmp1 = b.even
316  sol = &(x.Odd());
317  } else {
318  errorQuda("MatPCType %d not valid for DiracTwistedCloverPC", matpcType);
319  }
320  } else {//doublet:
321  errorQuda("Non-degenrate DiracTwistedCloverPC is not implemented \n");
322  }//end of doublet
323  // here we use final solution to store parity solution and parity source
324  // b is now up for grabs if we want
325 
326  deleteTmp(&tmp1, reset);
327  }
328 
330  const QudaSolutionType solType) const
331  {
332  if (solType == QUDA_MATPC_SOLUTION || solType == QUDA_MATPCDAG_MATPC_SOLUTION) {
333  return;
334  }
335 
336  checkFullSpinor(x, b);
337  bool reset = newTmp(&tmp1, b.Even());
338 
339  // create full solution
340  if(b.TwistFlavor() == QUDA_TWIST_SINGLET) {
342  // x_o = A_oo^-1 (b_o + k D_oe x_e)
346  // x_e = A_ee^-1 (b_e + k D_eo x_o)
349  } else {
350  errorQuda("MatPCType %d not valid for DiracTwistedCloverPC", matpcType);
351  }
352  } else { //twist doublet:
353  errorQuda("Non-degenrate DiracTwistedCloverPC is not implemented \n");
354  }//end of twist doublet...
355  deleteTmp(&tmp1, reset);
356  }
357 
358  void DiracTwistedCloverPC::createCoarseOp(GaugeField &Y, GaugeField &X, GaugeField &Xinv, GaugeField &Yhat, const Transfer &T, double kappa, double mu, double mu_factor) const {
359  double a = -2.0 * kappa * mu * T.Vectors().TwistFlavor();
361  }
362 } // namespace quda
virtual void prepare(ColorSpinorField *&src, ColorSpinorField *&sol, ColorSpinorField &x, ColorSpinorField &b, const QudaSolutionType) const
void M(ColorSpinorField &out, const ColorSpinorField &in) const
unsigned long long flops
Definition: dirac_quda.h:100
virtual void DslashXpay(ColorSpinorField &out, const ColorSpinorField &in, const QudaParity parity, const ColorSpinorField &x, const double &k) const
double mu
Definition: test_util.cpp:1643
const void * src
#define errorQuda(...)
Definition: util_quda.h:90
cudaGaugeField * gauge
Definition: dirac_quda.h:95
double mu_factor[QUDA_MAX_MG_LEVEL]
Definition: test_util.cpp:1659
virtual void checkFullSpinor(const ColorSpinorField &, const ColorSpinorField &) const
Definition: dirac.cpp:129
void createCoarseOp(GaugeField &Y, GaugeField &X, GaugeField &Xinv, GaugeField &Yhat, const Transfer &T, double kappa, double mu, double mu_factor=0.) const
Create the coarse twisted-clover operator.
cudaColorSpinorField * tmp
Definition: covdev_test.cpp:44
void twistedCloverDslashCuda(cudaColorSpinorField *out, const cudaGaugeField &gauge, const FullClover *clover, const FullClover *cloverInv, const cudaColorSpinorField *in, const int parity, const int dagger, const cudaColorSpinorField *x, const QudaTwistCloverDslashType type, const double &kappa, const double &mu, const double &epsilon, const double &k, const int *commDim, TimeProfile &profile)
const ColorSpinorField & Even() const
void deleteTmp(ColorSpinorField **, const bool &reset) const
Definition: dirac.cpp:64
TimeProfile profile
Definition: dirac_quda.h:112
DiracWilson & operator=(const DiracWilson &dirac)
void createCoarseOp(GaugeField &Y, GaugeField &X, GaugeField &Xinv, GaugeField &Yhat, const Transfer &T, double kappa, double mu, double mu_factor=0.) const
Create the coarse even-odd preconditioned twisted-clover operator. Unlike the Wilson operator...
DiracTwistedCloverPC(const DiracTwistedCloverPC &dirac)
void checkParitySpinor(const ColorSpinorField &, const ColorSpinorField &) const
QudaGaugeParam param
Definition: pack_test.cpp:17
bool newTmp(ColorSpinorField **, const ColorSpinorField &) const
Definition: dirac.cpp:53
#define b
void TwistCloverInv(ColorSpinorField &out, const ColorSpinorField &in, const int parity) const
int commDim[QUDA_MAX_DIM]
Definition: dirac_quda.h:110
const ColorSpinorField & Vectors(QudaFieldLocation location=QUDA_CPU_FIELD_LOCATION) const
Definition: transfer.h:195
VOLATILE spinorFloat kappa
cudaCloverField & clover
Definition: dirac_quda.h:556
DiracTwistedCloverPC & operator=(const DiracTwistedCloverPC &dirac)
cpuColorSpinorField * in
QudaSiteSubset SiteSubset() const
virtual void DslashXpay(ColorSpinorField &out, const ColorSpinorField &in, const QudaParity parity, const ColorSpinorField &x, const double &k) const
DiracTwistedClover & operator=(const DiracTwistedClover &dirac)
int commDim(int)
enum QudaSolutionType_s QudaSolutionType
virtual void M(ColorSpinorField &out, const ColorSpinorField &in) const
DiracTwistedClover(const DiracTwistedClover &dirac)
QudaDagType dagger
Definition: dirac_quda.h:99
enum QudaParity_s QudaParity
void TwistClover(ColorSpinorField &out, const ColorSpinorField &in, const int parity) const
double kappa
Definition: dirac_quda.h:96
QudaMatPCType matpcType
Definition: dirac_quda.h:98
void Mdag(ColorSpinorField &out, const ColorSpinorField &in) const
Definition: dirac.cpp:73
void reconstruct(ColorSpinorField &x, const ColorSpinorField &b, const QudaSolutionType) const
GaugeCovDev * dirac
Definition: covdev_test.cpp:75
cpuColorSpinorField * out
void MdagM(ColorSpinorField &out, const ColorSpinorField &in) const
virtual void MdagM(ColorSpinorField &out, const ColorSpinorField &in) const
int VolumeCB() const
unsigned long long flops
Definition: blas_quda.cu:42
virtual void reconstruct(ColorSpinorField &x, const ColorSpinorField &b, const QudaSolutionType) const
QudaTwistFlavorType TwistFlavor() 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
enum QudaTwistGamma5Type_s QudaTwistGamma5Type
virtual void checkParitySpinor(const ColorSpinorField &, const ColorSpinorField &) const
Definition: dirac.cpp:89
void twistedCloverApply(ColorSpinorField &out, const ColorSpinorField &in, const QudaTwistGamma5Type twistType, const int parity) const
QudaParity parity
Definition: covdev_test.cpp:53
virtual void Dslash(ColorSpinorField &out, const ColorSpinorField &in, const QudaParity parity) const
ColorSpinorField * tmp2
Definition: dirac_quda.h:102
#define a
void ApplyTwistClover(ColorSpinorField &out, const ColorSpinorField &in, const CloverField &clover, double kappa, double mu, double epsilon, int parity, int dagger, QudaTwistGamma5Type twist)
Apply twisted clover-matrix field to a color-spinor field.
Definition: dslash_quda.cu:708
void prepare(ColorSpinorField *&src, ColorSpinorField *&sol, ColorSpinorField &x, ColorSpinorField &b, const QudaSolutionType) const
ColorSpinorField * tmp1
Definition: dirac_quda.h:101