QUDA  v1.1.0
A library for QCD on GPUs
clover_reference.cpp
Go to the documentation of this file.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include <complex>
5 
6 #include <util_quda.h>
7 #include <host_utils.h>
9 
17 template <typename sFloat, typename cFloat>
18 void cloverReference(sFloat *out, cFloat *clover, sFloat *in, int parity) {
19  int nSpin = 4;
20  int nColor = 3;
21  int N = nColor * nSpin / 2;
22  int chiralBlock = N + 2*(N-1)*N/2;
23 
24  for (int i=0; i<Vh; i++) {
25  std::complex<sFloat> *In = reinterpret_cast<std::complex<sFloat>*>(&in[i*nSpin*nColor*2]);
26  std::complex<sFloat> *Out = reinterpret_cast<std::complex<sFloat>*>(&out[i*nSpin*nColor*2]);
27 
28  for (int chi=0; chi<nSpin/2; chi++) {
29  cFloat *D = &clover[((parity*Vh + i)*2 + chi)*chiralBlock];
30  std::complex<cFloat> *L = reinterpret_cast<std::complex<cFloat>*>(&D[N]);
31 
32  for (int s_col=0; s_col<nSpin/2; s_col++) { // 2 spins per chiral block
33  for (int c_col=0; c_col<nColor; c_col++) {
34  const int col = s_col * nColor + c_col;
35  const int Col = chi*N + col;
36  Out[Col] = 0.0;
37 
38  for (int s_row=0; s_row<nSpin/2; s_row++) { // 2 spins per chiral block
39  for (int c_row=0; c_row<nColor; c_row++) {
40  const int row = s_row * nColor + c_row;
41  const int Row = chi*N + row;
42 
43  if (row == col) {
44  Out[Col] += D[row] * In[Row];
45  } else if (col < row) {
46  int k = N*(N-1)/2 - (N-col)*(N-col-1)/2 + row - col - 1;
47  Out[Col] += conj(L[k]) * In[Row];
48  } else if (row < col) {
49  int k = N*(N-1)/2 - (N-row)*(N-row-1)/2 + col - row - 1;
50  Out[Col] += L[k] * In[Row];
51  }
52  }
53  }
54 
55  }
56  }
57 
58  }
59 
60  }
61 
62 }
63 
64 void apply_clover(void *out, void *clover, void *in, int parity, QudaPrecision precision) {
65 
66  switch (precision) {
68  cloverReference(static_cast<double*>(out), static_cast<double*>(clover), static_cast<double*>(in), parity);
69  break;
71  cloverReference(static_cast<float*>(out), static_cast<float*>(clover), static_cast<float*>(in), parity);
72  break;
73  default:
74  errorQuda("Unsupported precision %d", precision);
75  }
76 
77 }
78 
79 void clover_dslash(void *out, void **gauge, void *clover, void *in, int parity,
80  int dagger, QudaPrecision precision, QudaGaugeParam &param) {
81  void *tmp = malloc(Vh * spinor_site_size * precision);
82 
83  wil_dslash(tmp, gauge, in, parity, dagger, precision, param);
84  apply_clover(out, clover, tmp, parity, precision);
85 
86  free(tmp);
87 }
88 
89 // Apply the even-odd preconditioned Wilson-clover operator
90 void clover_matpc(void *out, void **gauge, void *clover, void *clover_inv, void *in, double kappa,
92 
93  double kappa2 = -kappa*kappa;
94  void *tmp = malloc(Vh * spinor_site_size * precision);
95 
96  switch(matpc_type) {
98  if (!dagger) {
99  wil_dslash(tmp, gauge, in, 1, dagger, precision, gauge_param);
100  apply_clover(out, clover_inv, tmp, 1, precision);
101  wil_dslash(tmp, gauge, out, 0, dagger, precision, gauge_param);
102  apply_clover(out, clover_inv, tmp, 0, precision);
103  } else {
104  apply_clover(tmp, clover_inv, in, 0, precision);
105  wil_dslash(out, gauge, tmp, 1, dagger, precision, gauge_param);
106  apply_clover(tmp, clover_inv, out, 1, precision);
107  wil_dslash(out, gauge, tmp, 0, dagger, precision, gauge_param);
108  }
109  xpay(in, kappa2, out, Vh * spinor_site_size, precision);
110  break;
112  wil_dslash(out, gauge, in, 1, dagger, precision, gauge_param);
113  apply_clover(tmp, clover_inv, out, 1, precision);
114  wil_dslash(out, gauge, tmp, 0, dagger, precision, gauge_param);
115  apply_clover(tmp, clover, in, 0, precision);
116  xpay(tmp, kappa2, out, Vh * spinor_site_size, precision);
117  break;
118  case QUDA_MATPC_ODD_ODD:
119  if (!dagger) {
120  wil_dslash(tmp, gauge, in, 0, dagger, precision, gauge_param);
121  apply_clover(out, clover_inv, tmp, 0, precision);
122  wil_dslash(tmp, gauge, out, 1, dagger, precision, gauge_param);
123  apply_clover(out, clover_inv, tmp, 1, precision);
124  } else {
125  apply_clover(tmp, clover_inv, in, 1, precision);
126  wil_dslash(out, gauge, tmp, 0, dagger, precision, gauge_param);
127  apply_clover(tmp, clover_inv, out, 0, precision);
128  wil_dslash(out, gauge, tmp, 1, dagger, precision, gauge_param);
129  }
130  xpay(in, kappa2, out, Vh * spinor_site_size, precision);
131  break;
133  wil_dslash(out, gauge, in, 0, dagger, precision, gauge_param);
134  apply_clover(tmp, clover_inv, out, 0, precision);
135  wil_dslash(out, gauge, tmp, 1, dagger, precision, gauge_param);
136  apply_clover(tmp, clover, in, 1, precision);
137  xpay(tmp, kappa2, out, Vh * spinor_site_size, precision);
138  break;
139  default:
140  errorQuda("Unsupoorted matpc=%d", matpc_type);
141  }
142 
143  free(tmp);
144 }
145 
146 // Apply the full Wilson-clover operator
147 void clover_mat(void *out, void **gauge, void *clover, void *in, double kappa,
148  int dagger, QudaPrecision precision, QudaGaugeParam &gauge_param) {
149 
150  void *tmp = malloc(V * spinor_site_size * precision);
151 
152  void *inEven = in;
153  void *inOdd = (char *)in + Vh * spinor_site_size * precision;
154  void *outEven = out;
155  void *outOdd = (char *)out + Vh * spinor_site_size * precision;
156  void *tmpEven = tmp;
157  void *tmpOdd = (char *)tmp + Vh * spinor_site_size * precision;
158 
159  // Odd part
160  wil_dslash(outOdd, gauge, inEven, 1, dagger, precision, gauge_param);
161  apply_clover(tmpOdd, clover, inOdd, 1, precision);
162 
163  // Even part
164  wil_dslash(outEven, gauge, inOdd, 0, dagger, precision, gauge_param);
165  apply_clover(tmpEven, clover, inEven, 0, precision);
166 
167  // lastly apply the kappa term
168  xpay(tmp, -kappa, out, V * spinor_site_size, precision);
169 
170  free(tmp);
171 }
172 
173 void applyTwist(void *out, void *in, void *tmpH, double a, QudaPrecision precision) {
174  switch (precision) {
176  for(int i = 0; i < Vh; i++)
177  for(int s = 0; s < 4; s++) {
178  double a5 = ((s / 2) ? -1.0 : +1.0) * a;
179  for(int c = 0; c < 3; c++) {
180  ((double *) out)[i * 24 + s * 6 + c * 2 + 0] = ((double *) tmpH)[i * 24 + s * 6 + c * 2 + 0] - a5*((double *) in)[i * 24 + s * 6 + c * 2 + 1];
181  ((double *) out)[i * 24 + s * 6 + c * 2 + 1] = ((double *) tmpH)[i * 24 + s * 6 + c * 2 + 1] + a5*((double *) in)[i * 24 + s * 6 + c * 2 + 0];
182  }
183  }
184  break;
186  for(int i = 0; i < Vh; i++)
187  for(int s = 0; s < 4; s++) {
188  float a5 = ((s / 2) ? -1.0 : +1.0) * a;
189  for(int c = 0; c < 3; c++) {
190  ((float *) out)[i * 24 + s * 6 + c * 2 + 0] = ((float *) tmpH)[i * 24 + s * 6 + c * 2 + 0] - a5*((float *) in)[i * 24 + s * 6 + c * 2 + 1];
191  ((float *) out)[i * 24 + s * 6 + c * 2 + 1] = ((float *) tmpH)[i * 24 + s * 6 + c * 2 + 1] + a5*((float *) in)[i * 24 + s * 6 + c * 2 + 0];
192  }
193  }
194  break;
195  default:
196  errorQuda("Unsupported precision %d", precision);
197  }
198 }
199 
200 // out = x - i*a*gamma_5 Clov *in =
201 void twistClover(void *out, void *in, void *x, void *clover, const double a, int dagger, int parity,
202  QudaPrecision precision)
203 {
204  void *tmp = malloc(Vh * spinor_site_size * precision);
205 
206  // tmp1 = Clov in
207  apply_clover(tmp, clover, in, parity, precision);
208  applyTwist(out, tmp, x, (dagger ? -a : a), precision);
209  free(tmp);
210 }
211 
212 // Apply (C + i*a*gamma_5)/(C^2 + a^2)
213 void twistCloverGamma5(void *out, void *in, void *clover, void *cInv, const int dagger, const double kappa, const double mu,
214  const QudaTwistFlavorType flavor, const int parity, QudaTwistGamma5Type twist, QudaPrecision precision) {
215  void *tmp1 = malloc(Vh * spinor_site_size * precision);
216  void *tmp2 = malloc(Vh * spinor_site_size * precision);
217 
218  double a = 0.0;
219 
220  if (twist == QUDA_TWIST_GAMMA5_DIRECT) {
221  a = 2.0 * kappa * mu * flavor;
222 
223  if (dagger) a *= -1.0;
224 
225  apply_clover(tmp1, clover, in, parity, precision);
226  applyTwist(out, in, tmp1, a, precision);
227  } else if (twist == QUDA_TWIST_GAMMA5_INVERSE) {
228  a = -2.0 * kappa * mu * flavor;
229 
230  if (dagger) a *= -1.0;
231 
232  apply_clover(tmp1, clover, in, parity, precision);
233  applyTwist(tmp2, in, tmp1, a, precision);
234  apply_clover(out, cInv, tmp2, parity, precision);
235  } else {
236  printf("Twist type %d not defined\n", twist);
237  exit(0);
238  }
239 
240  free(tmp2);
241  free(tmp1);
242 }
243 
244 void tmc_dslash(void *out, void **gauge, void *in, void *clover, void *cInv, double kappa, double mu, QudaTwistFlavorType flavor,
246  void *tmp1 = malloc(Vh * spinor_site_size * precision);
247  void *tmp2 = malloc(Vh * spinor_site_size * precision);
248 
249  if (dagger) {
250  twistCloverGamma5(tmp1, in, clover, cInv, dagger, kappa, mu, flavor, 1-parity, QUDA_TWIST_GAMMA5_INVERSE, precision);
252  wil_dslash(tmp2, gauge, tmp1, parity, dagger, precision, param);
253  twistCloverGamma5(out, tmp2, clover, cInv, dagger, kappa, mu, flavor, parity, QUDA_TWIST_GAMMA5_INVERSE, precision);
254  } else {
255  wil_dslash(out, gauge, tmp1, parity, dagger, precision, param);
256  }
257  } else {
258  wil_dslash(tmp1, gauge, in, parity, dagger, precision, param);
259  twistCloverGamma5(out, tmp1, clover, cInv, dagger, kappa, mu, flavor, parity, QUDA_TWIST_GAMMA5_INVERSE, precision);
260  }
261 
262  free(tmp2);
263  free(tmp1);
264 }
265 
266 // Apply the full twisted-clover operator
267 void tmc_mat(void *out, void **gauge, void *clover, void *in, double kappa, double mu,
269 
270  void *tmp = malloc(V * spinor_site_size * precision);
271 
272  void *inEven = in;
273  void *inOdd = (char *)in + Vh * spinor_site_size * precision;
274  void *outEven = out;
275  void *outOdd = (char *)out + Vh * spinor_site_size * precision;
276  void *tmpEven = tmp;
277  void *tmpOdd = (char *)tmp + Vh * spinor_site_size * precision;
278 
279  // Odd part
280  wil_dslash(outOdd, gauge, inEven, 1, dagger, precision, gauge_param);
281  twistCloverGamma5(tmpOdd, inOdd, clover, NULL, dagger, kappa, mu, flavor, 1, QUDA_TWIST_GAMMA5_DIRECT, precision);
282 
283  // Even part
284  wil_dslash(outEven, gauge, inOdd, 0, dagger, precision, gauge_param);
285  twistCloverGamma5(tmpEven, inEven, clover, NULL, dagger, kappa, mu, flavor, 0, QUDA_TWIST_GAMMA5_DIRECT, precision);
286 
287  // lastly apply the kappa term
288  xpay(tmp, -kappa, out, V * spinor_site_size, precision);
289 
290  free(tmp);
291 }
292 
293 // Apply the even-odd preconditioned Dirac operator
294 void tmc_matpc(void *out, void **gauge, void *in, void *clover, void *cInv, double kappa, double mu, QudaTwistFlavorType flavor,
296 
297  double kappa2 = -kappa*kappa;
298 
299  void *tmp1 = malloc(Vh * spinor_site_size * precision);
300  void *tmp2 = malloc(Vh * spinor_site_size * precision);
301 
302  switch(matpc_type) {
304  if (!dagger) {
305  wil_dslash(out, gauge, in, 1, dagger, precision, gauge_param);
306  twistCloverGamma5(tmp1, out, clover, cInv, dagger, kappa, mu, flavor, 1, QUDA_TWIST_GAMMA5_INVERSE, precision);
307  wil_dslash(tmp2, gauge, tmp1, 0, dagger, precision, gauge_param);
308  twistCloverGamma5(out, tmp2, clover, cInv, dagger, kappa, mu, flavor, 0, QUDA_TWIST_GAMMA5_INVERSE, precision);
309  } else {
310  twistCloverGamma5(out, in, clover, cInv, dagger, kappa, mu, flavor, 0, QUDA_TWIST_GAMMA5_INVERSE, precision);
311  wil_dslash(tmp1, gauge, out, 1, dagger, precision, gauge_param);
312  twistCloverGamma5(tmp2, tmp1, clover, cInv, dagger, kappa, mu, flavor, 1, QUDA_TWIST_GAMMA5_INVERSE, precision);
313  wil_dslash(out, gauge, tmp2, 0, dagger, precision, gauge_param);
314  }
315  xpay(in, kappa2, out, Vh * spinor_site_size, precision);
316  break;
318  wil_dslash(tmp1, gauge, in, 1, dagger, precision, gauge_param);
319  twistCloverGamma5(tmp2, tmp1, clover, cInv, dagger, kappa, mu, flavor, 1, QUDA_TWIST_GAMMA5_INVERSE, precision);
320  wil_dslash(out, gauge, tmp2, 0, dagger, precision, gauge_param);
321  twistCloverGamma5(tmp2, in, clover, cInv, dagger, kappa, mu, flavor, 0, QUDA_TWIST_GAMMA5_DIRECT, precision);
322  xpay(tmp2, kappa2, out, Vh * spinor_site_size, precision);
323  break;
324  case QUDA_MATPC_ODD_ODD:
325  if (!dagger) {
326  wil_dslash(out, gauge, in, 0, dagger, precision, gauge_param);
327  twistCloverGamma5(tmp1, out, clover, cInv, dagger, kappa, mu, flavor, 0, QUDA_TWIST_GAMMA5_INVERSE, precision);
328  wil_dslash(tmp2, gauge, tmp1, 1, dagger, precision, gauge_param);
329  twistCloverGamma5(out, tmp2, clover, cInv, dagger, kappa, mu, flavor, 1, QUDA_TWIST_GAMMA5_INVERSE, precision);
330  } else {
331  twistCloverGamma5(out, in, clover, cInv, dagger, kappa, mu, flavor, 1, QUDA_TWIST_GAMMA5_INVERSE, precision);
332  wil_dslash(tmp1, gauge, out, 0, dagger, precision, gauge_param);
333  twistCloverGamma5(tmp2, tmp1, clover, cInv, dagger, kappa, mu, flavor, 0, QUDA_TWIST_GAMMA5_INVERSE, precision);
334  wil_dslash(out, gauge, tmp2, 1, dagger, precision, gauge_param);
335  }
336  xpay(in, kappa2, out, Vh * spinor_site_size, precision);
337  break;
339  wil_dslash(tmp1, gauge, in, 0, dagger, precision, gauge_param);
340  twistCloverGamma5(tmp2, tmp1, clover, cInv, dagger, kappa, mu, flavor, 0, QUDA_TWIST_GAMMA5_INVERSE, precision);
341  wil_dslash(out, gauge, tmp2, 1, dagger, precision, gauge_param);
342  twistCloverGamma5(tmp1, in, clover, cInv, dagger, kappa, mu, flavor, 1, QUDA_TWIST_GAMMA5_DIRECT, precision);
343  xpay(tmp1, kappa2, out, Vh * spinor_site_size, precision);
344  break;
345  default:
346  errorQuda("Unsupported matpc=%d", matpc_type);
347  }
348 
349  free(tmp2);
350  free(tmp1);
351 }
352 
353 // Apply the full twisted-clover operator
354 // for now [ A -k D ]
355 // [ -k D A(1 - i mu gamma_5 A) ]
356 
357 void cloverHasenbuchTwist_mat(void *out, void **gauge, void *clover, void *in, double kappa, double mu, int dagger,
359 {
360 
361  // out = CloverMat in
362  clover_mat(out, gauge, clover, in, kappa, dagger, precision, gauge_param);
363 
365 
366  void *inEven = in;
367  void *inOdd = (char *)in + Vh * spinor_site_size * precision;
368  void *outEven = out;
369  void *outOdd = (char *)out + Vh * spinor_site_size * precision;
370 
371  if (asymmetric) {
372  // Unprec op for asymmetric prec op:
373  // apply a simple twist
374 
375  // out_parity = out_parity -/+ i mu gamma_5
377  // out_e = out_e -/+ i mu gamma5 in_e
378  applyTwist(outEven, inEven, outEven, (dagger ? -mu : mu), precision);
379 
380  } else {
381  // out_o = out_o -/+ i mu gamma5 in_o
382  applyTwist(outOdd, inOdd, outOdd, (dagger ? -mu : mu), precision);
383  }
384  } else {
385 
386  // Symmetric case: - i mu gamma_5 A^2 psi_in
387  void *tmp = malloc(Vh * spinor_site_size * precision);
388 
390 
391  // tmp = A_ee in_e
392  apply_clover(tmp, clover, inEven, 0, precision);
393 
394  // two factors of 2 for two clover applications => (1/4) mu
395  // out_e = out_e -/+ i gamma_5 mu A_ee (A_ee) in_ee
396  twistClover(outEven, tmp, outEven, clover, 0.25 * mu, dagger, 0, precision);
397 
398  } else {
399  apply_clover(tmp, clover, inOdd, 1, precision);
400 
401  // two factors of 2 for two clover applications => (1/4) mu
402  // out_e = out_e -/+ i gamma_5 mu A (A_ee)
403  twistClover(outOdd, tmp, outOdd, clover, 0.25 * mu, dagger, 1, precision);
404  }
405  free(tmp);
406  }
407 }
408 
409 // Apply the even-odd preconditioned Dirac operator
410 void cloverHasenbuschTwist_matpc(void *out, void **gauge, void *in, void *clover, void *cInv, double kappa, double mu,
413 {
414 
415  clover_matpc(out, gauge, clover, cInv, in, kappa, matpc_type, dagger, precision, gauge_param);
416 
418  twistClover(out, in, out, clover, 0.5 * mu, dagger, (matpc_type == QUDA_MATPC_EVEN_EVEN ? 0 : 1), precision);
419  } else {
420  applyTwist(out, in, out, (dagger ? -mu : mu), precision);
421  }
422 }
void applyTwist(void *out, void *in, void *tmpH, double a, QudaPrecision precision)
void twistCloverGamma5(void *out, void *in, void *clover, void *cInv, const int dagger, const double kappa, const double mu, const QudaTwistFlavorType flavor, const int parity, QudaTwistGamma5Type twist, QudaPrecision precision)
void clover_mat(void *out, void **gauge, void *clover, void *in, double kappa, int dagger, QudaPrecision precision, QudaGaugeParam &gauge_param)
void clover_dslash(void *out, void **gauge, void *clover, void *in, int parity, int dagger, QudaPrecision precision, QudaGaugeParam &param)
void cloverReference(sFloat *out, cFloat *clover, sFloat *in, int parity)
Apply the clover matrix field.
void tmc_mat(void *out, void **gauge, void *clover, void *in, double kappa, double mu, QudaTwistFlavorType flavor, int dagger, QudaPrecision precision, QudaGaugeParam &gauge_param)
void clover_matpc(void *out, void **gauge, void *clover, void *clover_inv, void *in, double kappa, QudaMatPCType matpc_type, int dagger, QudaPrecision precision, QudaGaugeParam &gauge_param)
void tmc_dslash(void *out, void **gauge, void *in, void *clover, void *cInv, double kappa, double mu, QudaTwistFlavorType flavor, int parity, QudaMatPCType matpc_type, int dagger, QudaPrecision precision, QudaGaugeParam &param)
void twistClover(void *out, void *in, void *x, void *clover, const double a, int dagger, int parity, QudaPrecision precision)
void cloverHasenbuschTwist_matpc(void *out, void **gauge, void *in, void *clover, void *cInv, double kappa, double mu, QudaMatPCType matpc_type, int dagger, QudaPrecision precision, QudaGaugeParam &gauge_param)
void cloverHasenbuchTwist_mat(void *out, void **gauge, void *clover, void *in, double kappa, double mu, int dagger, QudaPrecision precision, QudaGaugeParam &gauge_param, QudaMatPCType matpc_type)
void tmc_matpc(void *out, void **gauge, void *in, void *clover, void *cInv, double kappa, double mu, QudaTwistFlavorType flavor, QudaMatPCType matpc_type, int dagger, QudaPrecision precision, QudaGaugeParam &gauge_param)
void apply_clover(void *out, void *clover, void *in, int parity, QudaPrecision precision)
double kappa
double mu
QudaMatPCType matpc_type
bool dagger
int Vh
Definition: host_utils.cpp:38
int V
Definition: host_utils.cpp:37
QudaParity parity
Definition: covdev_test.cpp:40
cudaColorSpinorField * tmp
Definition: covdev_test.cpp:34
const int nColor
Definition: covdev_test.cpp:44
QudaGaugeParam gauge_param
Definition: covdev_test.cpp:26
enum QudaPrecision_s QudaPrecision
enum QudaTwistFlavorType_s QudaTwistFlavorType
enum QudaTwistGamma5Type_s QudaTwistGamma5Type
@ QUDA_MATPC_ODD_ODD_ASYMMETRIC
Definition: enum_quda.h:219
@ QUDA_MATPC_EVEN_EVEN_ASYMMETRIC
Definition: enum_quda.h:218
@ QUDA_MATPC_ODD_ODD
Definition: enum_quda.h:217
@ QUDA_MATPC_EVEN_EVEN
Definition: enum_quda.h:216
enum QudaMatPCType_s QudaMatPCType
@ QUDA_TWIST_GAMMA5_INVERSE
Definition: enum_quda.h:424
@ QUDA_TWIST_GAMMA5_DIRECT
Definition: enum_quda.h:423
@ QUDA_DOUBLE_PRECISION
Definition: enum_quda.h:65
@ QUDA_SINGLE_PRECISION
Definition: enum_quda.h:64
Matrix< N, std::complex< T > > conj(const Matrix< N, std::complex< T > > &mat)
#define spinor_site_size
Definition: host_utils.h:9
void xpay(ColorSpinorField &x, double a, ColorSpinorField &y)
Definition: blas_quda.h:45
QudaGaugeParam param
Definition: pack_test.cpp:18
#define errorQuda(...)
Definition: util_quda.h:120
void wil_dslash(void *out, void **gauge, void *in, int oddBit, int daggerBit, QudaPrecision precision, QudaGaugeParam &gauge_param)