QUDA  v0.5.0
A library for QCD on GPUs
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
dirac_clover.cpp
Go to the documentation of this file.
1 #include <iostream>
2 #include <dirac_quda.h>
3 #include <blas_quda.h>
4 
5 namespace quda {
6 
8  : DiracWilson(param), clover(*(param.clover))
9  {
11  }
12 
14  : DiracWilson(dirac), clover(dirac.clover)
15  {
17  }
18 
20 
22  {
23  if (&dirac != this) {
25  clover = dirac.clover;
26  }
27  return *this;
28  }
29 
31  {
32  Dirac::checkParitySpinor(out, in);
33 
34  if (out.Volume() != clover.VolumeCB()) {
35  errorQuda("Parity spinor volume %d doesn't match clover checkboard volume %d",
36  out.Volume(), clover.VolumeCB());
37  }
38  }
39 
43  const double &k) const
44  {
46  checkParitySpinor(in, out);
47  checkSpinorAlias(in, out);
48 
49  setFace(face); // FIXME: temporary hack maintain C linkage for dslashCuda
50 
51  FullClover cs(clover);
52  asymCloverDslashCuda(&out, gauge, cs, &in, parity, dagger, &x, k, commDim);
53 
54  flops += 1872ll*in.Volume();
55  }
56 
57  // Public method to apply the clover term only
59  {
61  checkParitySpinor(in, out);
62 
63  // regular clover term
64  FullClover cs(clover);
65  cloverCuda(&out, gauge, cs, &in, parity);
66 
67  flops += 504ll*in.Volume();
68  }
69 
71  {
72  checkFullSpinor(out, in);
73  DslashXpay(out.Odd(), in.Even(), QUDA_ODD_PARITY, in.Odd(), -kappa);
74  DslashXpay(out.Even(), in.Odd(), QUDA_EVEN_PARITY, in.Even(), -kappa);
75  }
76 
78  {
79  checkFullSpinor(out, in);
80 
81  bool reset = newTmp(&tmp1, in);
82  checkFullSpinor(*tmp1, in);
83 
84  M(*tmp1, in);
85  Mdag(out, *tmp1);
86 
87  deleteTmp(&tmp1, reset);
88  }
89 
92  const QudaSolutionType solType) const
93  {
94  if (solType == QUDA_MATPC_SOLUTION || solType == QUDA_MATPCDAG_MATPC_SOLUTION) {
95  errorQuda("Preconditioned solution requires a preconditioned solve_type");
96  }
97 
98  src = &b;
99  sol = &x;
100  }
101 
103  const QudaSolutionType solType) const
104  {
105  // do nothing
106  }
107 
109  DiracClover(param)
110  {
111  // For the preconditioned operator, we need to check that the inverse of the clover term is present
112  if (!clover.cloverInv) errorQuda("Clover inverse required for DiracCloverPC");
113  }
114 
116 
118 
120  {
121  if (&dirac != this) {
122  DiracClover::operator=(dirac);
123  }
124  return *this;
125  }
126 
127  // Public method
129  const QudaParity parity) const
130  {
132  checkParitySpinor(in, out);
133 
134  // needs to be cloverinv
135  FullClover cs(clover, true);
136  cloverCuda(&out, gauge, cs, &in, parity);
137 
138  flops += 504ll*in.Volume();
139  }
140 
141  // apply hopping term, then clover: (A_ee^-1 D_eo) or (A_oo^-1 D_oe),
142  // and likewise for dagger: (A_ee^-1 D^dagger_eo) or (A_oo^-1 D^dagger_oe)
143  // NOTE - this isn't Dslash dagger since order should be reversed!
145  const QudaParity parity) const
146  {
148  checkParitySpinor(in, out);
149  checkSpinorAlias(in, out);
150 
151  setFace(face); // FIXME: temporary hack maintain C linkage for dslashCuda
152 
153  FullClover cs(clover, true);
154  cloverDslashCuda(&out, gauge, cs, &in, parity, dagger, 0, 0.0, commDim);
155 
156  flops += 1824ll*in.Volume();
157  }
158 
159  // xpay version of the above
161  const QudaParity parity, const cudaColorSpinorField &x,
162  const double &k) const
163  {
165  checkParitySpinor(in, out);
166  checkSpinorAlias(in, out);
167 
168  setFace(face); // FIXME: temporary hack maintain C linkage for dslashCuda
169 
170  FullClover cs(clover, true);
171  cloverDslashCuda(&out, gauge, cs, &in, parity, dagger, &x, k, commDim);
172 
173  flops += 1872ll*in.Volume();
174  }
175 
176  // Apply the even-odd preconditioned clover-improved Dirac operator
178  {
179  double kappa2 = -kappa*kappa;
180  bool reset1 = newTmp(&tmp1, in);
181 
183  // DiracCloverPC::Dslash applies A^{-1}Dslash
184  Dslash(*tmp1, in, QUDA_ODD_PARITY);
185  // DiracClover::DslashXpay applies (A - kappa^2 D)
186  DiracClover::DslashXpay(out, *tmp1, QUDA_EVEN_PARITY, in, kappa2);
188  // DiracCloverPC::Dslash applies A^{-1}Dslash
190  // DiracClover::DslashXpay applies (A - kappa^2 D)
191  DiracClover::DslashXpay(out, *tmp1, QUDA_ODD_PARITY, in, kappa2);
192  } else if (!dagger) { // symmetric preconditioning
194  Dslash(*tmp1, in, QUDA_ODD_PARITY);
195  DslashXpay(out, *tmp1, QUDA_EVEN_PARITY, in, kappa2);
196  } else if (matpcType == QUDA_MATPC_ODD_ODD) {
198  DslashXpay(out, *tmp1, QUDA_ODD_PARITY, in, kappa2);
199  } else {
200  errorQuda("Invalid matpcType");
201  }
202  } else { // symmetric preconditioning, dagger
204  CloverInv(out, in, QUDA_EVEN_PARITY);
205  Dslash(*tmp1, out, QUDA_ODD_PARITY);
206  DiracWilson::DslashXpay(out, *tmp1, QUDA_EVEN_PARITY, in, kappa2);
207  } else if (matpcType == QUDA_MATPC_ODD_ODD) {
208  CloverInv(out, in, QUDA_ODD_PARITY);
209  Dslash(*tmp1, out, QUDA_EVEN_PARITY);
210  DiracWilson::DslashXpay(out, *tmp1, QUDA_ODD_PARITY, in, kappa2);
211  } else {
212  errorQuda("MatPCType %d not valid for DiracCloverPC", matpcType);
213  }
214  }
215 
216  deleteTmp(&tmp1, reset1);
217  }
218 
220  {
221  // need extra temporary because of symmetric preconditioning dagger
222  // and for multi-gpu the input and output fields cannot alias
223  bool reset = newTmp(&tmp2, in);
224  M(*tmp2, in);
225  Mdag(out, *tmp2);
226  deleteTmp(&tmp2, reset);
227  }
228 
231  const QudaSolutionType solType) const
232  {
233  // we desire solution to preconditioned system
234  if (solType == QUDA_MATPC_SOLUTION || solType == QUDA_MATPCDAG_MATPC_SOLUTION) {
235  src = &b;
236  sol = &x;
237  return;
238  }
239 
240  bool reset = newTmp(&tmp1, b.Even());
241 
242  // we desire solution to full system
244  // src = A_ee^-1 (b_e + k D_eo A_oo^-1 b_o)
245  src = &(x.Odd());
246  CloverInv(*src, b.Odd(), QUDA_ODD_PARITY);
249  sol = &(x.Even());
250  } else if (matpcType == QUDA_MATPC_ODD_ODD) {
251  // src = A_oo^-1 (b_o + k D_oe A_ee^-1 b_e)
252  src = &(x.Even());
253  CloverInv(*src, b.Even(), QUDA_EVEN_PARITY);
255  CloverInv(*src, *tmp1, QUDA_ODD_PARITY);
256  sol = &(x.Odd());
258  // src = b_e + k D_eo A_oo^-1 b_o
259  src = &(x.Odd());
260  CloverInv(*tmp1, b.Odd(), QUDA_ODD_PARITY); // safe even when *tmp1 = b.odd
262  sol = &(x.Even());
264  // src = b_o + k D_oe A_ee^-1 b_e
265  src = &(x.Even());
266  CloverInv(*tmp1, b.Even(), QUDA_EVEN_PARITY); // safe even when *tmp1 = b.even
268  sol = &(x.Odd());
269  } else {
270  errorQuda("MatPCType %d not valid for DiracCloverPC", matpcType);
271  }
272 
273  // here we use final solution to store parity solution and parity source
274  // b is now up for grabs if we want
275 
276  deleteTmp(&tmp1, reset);
277 
278  }
279 
281  const QudaSolutionType solType) const
282  {
283  if (solType == QUDA_MATPC_SOLUTION || solType == QUDA_MATPCDAG_MATPC_SOLUTION) {
284  return;
285  }
286 
287  checkFullSpinor(x, b);
288 
289  bool reset = newTmp(&tmp1, b.Even());
290 
291  // create full solution
292 
295  // x_o = A_oo^-1 (b_o + k D_oe x_e)
298  } else if (matpcType == QUDA_MATPC_ODD_ODD ||
300  // x_e = A_ee^-1 (b_e + k D_eo x_o)
303  } else {
304  errorQuda("MatPCType %d not valid for DiracCloverPC", matpcType);
305  }
306 
307  deleteTmp(&tmp1, reset);
308 
309  }
310 
311 } // namespace quda