QUDA  1.0.0
coarse_op.cu
Go to the documentation of this file.
1 #include <transfer.h>
2 #include <color_spinor_field.h>
3 #include <gauge_field.h>
4 #include <clover_field.h>
5 
6 #ifdef GPU_MULTIGRID
7 #include <coarse_op.cuh>
8 #endif
9 
10 namespace quda {
11 
12 #ifdef GPU_MULTIGRID
13 
14  template <typename Float, typename vFloat, int fineColor, int fineSpin, int coarseColor, int coarseSpin>
15  void calculateY(GaugeField &Y, GaugeField &X, GaugeField &Yatomic, GaugeField &Xatomic,
16  ColorSpinorField &uv, ColorSpinorField &av, const Transfer &T,
17  const GaugeField &g, const CloverField &c, double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc) {
18 
19  QudaFieldLocation location = Y.Location();
20 
21  bool need_bidirectional = false;
22  if (dirac == QUDA_CLOVERPC_DIRAC || dirac == QUDA_TWISTED_MASSPC_DIRAC || dirac == QUDA_TWISTED_CLOVERPC_DIRAC) { need_bidirectional = QUDA_BOOLEAN_TRUE; }
23 
24  if (location == QUDA_CPU_FIELD_LOCATION) {
25 
27  constexpr QudaGaugeFieldOrder gOrder = QUDA_QDP_GAUGE_ORDER;
29 
30  if (T.Vectors(Y.Location()).FieldOrder() != csOrder)
31  errorQuda("Unsupported field order %d\n", T.Vectors(Y.Location()).FieldOrder());
32  if (g.FieldOrder() != gOrder) errorQuda("Unsupported field order %d\n", g.FieldOrder());
33  if (c.Order() != clOrder && c.Bytes()) errorQuda("Unsupported field order %d\n", c.Order());
34 
35  typedef typename colorspinor::FieldOrderCB<Float,fineSpin,fineColor,coarseColor,csOrder,vFloat> V;
36  typedef typename colorspinor::FieldOrderCB<Float,fineSpin,fineColor,coarseColor,csOrder,vFloat> F;
37  typedef typename gauge::FieldOrder<Float,fineColor,1,gOrder> gFine;
38  typedef typename gauge::FieldOrder<Float,coarseColor*coarseSpin,coarseSpin,gOrder,true,vFloat> gCoarse;
39  typedef typename gauge::FieldOrder<Float,coarseColor*coarseSpin,coarseSpin,gOrder,true,storeType> gCoarseAtomic;
40  typedef typename clover::FieldOrder<Float,fineColor,fineSpin,clOrder> cFine;
41 
42  const ColorSpinorField &v = T.Vectors(g.Location());
43 
44  V vAccessor(const_cast<ColorSpinorField&>(v));
45  F uvAccessor(const_cast<ColorSpinorField&>(uv));
46  F avAccessor(const_cast<ColorSpinorField&>(av));
47  gFine gAccessor(const_cast<GaugeField&>(g));
48  gCoarse yAccessor(const_cast<GaugeField&>(Y));
49  gCoarse xAccessor(const_cast<GaugeField&>(X));
50  gCoarseAtomic yAccessorAtomic(const_cast<GaugeField&>(Yatomic));
51  gCoarseAtomic xAccessorAtomic(const_cast<GaugeField&>(Xatomic));
52  cFine cAccessor(const_cast<CloverField&>(c), false);
53  cFine cInvAccessor(const_cast<CloverField&>(c), true);
54 
55 
56  calculateY<false,Float,fineSpin,fineColor,coarseSpin,coarseColor>
57  (yAccessor, xAccessor, yAccessorAtomic, xAccessorAtomic, uvAccessor,
58  avAccessor, vAccessor, gAccessor, cAccessor, cInvAccessor, Y, X, Yatomic, Xatomic, uv, av, v, kappa, mu, mu_factor, dirac, matpc, need_bidirectional,
59  T.fineToCoarse(location), T.coarseToFine(location));
60 
61  } else {
62 
63  constexpr QudaFieldOrder csOrder = QUDA_FLOAT2_FIELD_ORDER;
66 
67  if (T.Vectors(Y.Location()).FieldOrder() != csOrder)
68  errorQuda("Unsupported field order %d\n", T.Vectors(Y.Location()).FieldOrder());
69  if (g.FieldOrder() != gOrder) errorQuda("Unsupported field order %d\n", g.FieldOrder());
70  if (c.Order() != clOrder && c.Bytes()) errorQuda("Unsupported field order %d\n", c.Order());
71 
72  constexpr bool use_tex = __COMPUTE_CAPABILITY__ < 520 ? true : false; // on pre-Maxwell-2 use textures/ldg to get caching
73  typedef typename colorspinor::FieldOrderCB<Float,fineSpin,fineColor,coarseColor,csOrder,vFloat,vFloat,false,false,use_tex> F;
74  typedef typename gauge::FieldOrder<Float,fineColor,1,gOrder,true,Float,use_tex> gFine;
75  typedef typename gauge::FieldOrder<Float,coarseColor*coarseSpin,coarseSpin,gOrder,true,vFloat> gCoarse;
76  typedef typename gauge::FieldOrder<Float,coarseColor*coarseSpin,coarseSpin,gOrder,true,storeType> gCoarseAtomic;
77  typedef typename clover::FieldOrder<Float,fineColor,fineSpin,clOrder> cFine;
78 
79  const ColorSpinorField &v = T.Vectors(g.Location());
80 
81  F vAccessor(const_cast<ColorSpinorField&>(v));
82  F uvAccessor(const_cast<ColorSpinorField&>(uv));
83  F avAccessor(const_cast<ColorSpinorField&>(av));
84  gFine gAccessor(const_cast<GaugeField&>(g));
85  gCoarse yAccessor(const_cast<GaugeField&>(Y));
86  gCoarse xAccessor(const_cast<GaugeField&>(X));
87  gCoarseAtomic yAccessorAtomic(const_cast<GaugeField&>(Yatomic));
88  gCoarseAtomic xAccessorAtomic(const_cast<GaugeField&>(Xatomic));
89  cFine cAccessor(const_cast<CloverField&>(c), false);
90  cFine cInvAccessor(const_cast<CloverField&>(c), true);
91 
92  calculateY<false,Float,fineSpin,fineColor,coarseSpin,coarseColor>
93  (yAccessor, xAccessor, yAccessorAtomic, xAccessorAtomic, uvAccessor,
94  avAccessor, vAccessor, gAccessor, cAccessor, cInvAccessor, Y, X, Yatomic, Xatomic, uv, av, v, kappa, mu, mu_factor, dirac, matpc, need_bidirectional,
95  T.fineToCoarse(location), T.coarseToFine(location));
96 
97  }
98 
99  }
100 
101  // template on the number of coarse degrees of freedom
102  template <typename Float, typename vFloat, int fineColor, int fineSpin>
103  void calculateY(GaugeField &Y, GaugeField &X, GaugeField &Yatomic, GaugeField &Xatomic,
104  ColorSpinorField &uv, ColorSpinorField &av, const Transfer &T,
105  const GaugeField &g, const CloverField &c, double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc) {
106  if (T.Vectors().Nspin()/T.Spin_bs() != 2)
107  errorQuda("Unsupported number of coarse spins %d\n",T.Vectors().Nspin()/T.Spin_bs());
108  const int coarseSpin = 2;
109  const int coarseColor = Y.Ncolor() / coarseSpin;
110 
111 #if 0
112  } else if (coarseCoor == 4) {
113  calculateY<Float,vFloat,fineColor,fineSpin,4,coarseSpin>(Y, X, Yatomic, Xatomic, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
114 #endif
115  if (coarseColor == 6) { // free field Wilson
116  calculateY<Float,vFloat,fineColor,fineSpin,6,coarseSpin>(Y, X, Yatomic, Xatomic, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
117 #if 0
118  } else if (coarseColor == 8) {
119  calculateY<Float,vFloat,fineColor,fineSpin,8,coarseSpin>(Y, X, Yatomic, Xatomic, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
120  } else if (coarseColor == 12) {
121  calculateY<Float,vFloat,fineColor,fineSpin,12,coarseSpin>(Y, X, Yatomic, Xatomic, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
122  } else if (coarseColor == 16) {
123  calculateY<Float,vFloat,fineColor,fineSpin,16,coarseSpin>(Y, X, Yatomic, Xatomic, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
124  } else if (coarseColor == 20) {
125  calculateY<Float,vFloat,fineColor,fineSpin,20,coarseSpin>(Y, X, Yatomic, Xatomic, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
126 #endif
127  } else if (coarseColor == 24) {
128  calculateY<Float,vFloat,fineColor,fineSpin,24,coarseSpin>(Y, X, Yatomic, Xatomic, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
129  } else if (coarseColor == 32) {
130  calculateY<Float,vFloat,fineColor,fineSpin,32,coarseSpin>(Y, X, Yatomic, Xatomic, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
131  } else {
132  errorQuda("Unsupported number of coarse dof %d\n", Y.Ncolor());
133  }
134  }
135 
136  // template on fine spin
137  template <typename Float, typename vFloat, int fineColor>
138  void calculateY(GaugeField &Y, GaugeField &X, GaugeField &Yatomic, GaugeField &Xatomic,
139  ColorSpinorField &uv, ColorSpinorField &av, const Transfer &T,
140  const GaugeField &g, const CloverField &c, double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc) {
141  if (uv.Nspin() == 4) {
142  calculateY<Float,vFloat,fineColor,4>(Y, X, Yatomic, Xatomic, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
143  } else {
144  errorQuda("Unsupported number of spins %d\n", uv.Nspin());
145  }
146  }
147 
148  // template on fine colors
149  template <typename Float, typename vFloat>
150  void calculateY(GaugeField &Y, GaugeField &X, GaugeField &Yatomic, GaugeField &Xatomic,
151  ColorSpinorField &uv, ColorSpinorField &av, const Transfer &T,
152  const GaugeField &g, const CloverField &c, double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc) {
153  if (g.Ncolor() == 3) {
154  calculateY<Float,vFloat,3>(Y, X, Yatomic, Xatomic, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
155  } else {
156  errorQuda("Unsupported number of colors %d\n", g.Ncolor());
157  }
158  }
159 
160  //Does the heavy lifting of creating the coarse color matrices Y
161  void calculateY(GaugeField &Y, GaugeField &X, GaugeField &Yatomic, GaugeField &Xatomic,
162  ColorSpinorField &uv, ColorSpinorField &av, const Transfer &T,
163  const GaugeField &g, const CloverField &c, double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc) {
164  checkPrecision(Xatomic, Yatomic, g);
165  checkPrecision(uv, av, T.Vectors(X.Location()), X, Y);
166 
167  if (getVerbosity() >= QUDA_SUMMARIZE) printfQuda("Computing Y field......\n");
168 
169  if (Y.Precision() == QUDA_DOUBLE_PRECISION) {
170 #ifdef GPU_MULTIGRID_DOUBLE
171  if (T.Vectors(X.Location()).Precision() == QUDA_DOUBLE_PRECISION) {
172  calculateY<double,double>(Y, X, Yatomic, Xatomic, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
173  } else {
174  errorQuda("Unsupported precision %d\n", Y.Precision());
175  }
176 #else
177  errorQuda("Double precision multigrid has not been enabled");
178 #endif
179  } else if (Y.Precision() == QUDA_SINGLE_PRECISION) {
180  if (T.Vectors(X.Location()).Precision() == QUDA_SINGLE_PRECISION) {
181  calculateY<float,float>(Y, X, Yatomic, Xatomic, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
182  } else {
183  errorQuda("Unsupported precision %d\n", T.Vectors(X.Location()).Precision());
184  }
185  } else if (Y.Precision() == QUDA_HALF_PRECISION) {
186  if (T.Vectors(X.Location()).Precision() == QUDA_HALF_PRECISION) {
187  calculateY<float,short>(Y, X, Yatomic, Xatomic, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
188  } else {
189  errorQuda("Unsupported precision %d\n", T.Vectors(X.Location()).Precision());
190  }
191  } else {
192  errorQuda("Unsupported precision %d\n", Y.Precision());
193  }
194  if (getVerbosity() >= QUDA_SUMMARIZE) printfQuda("....done computing Y field\n");
195  }
196 
197 #endif // GPU_MULTIGRID
198 
199  //Calculates the coarse color matrix and puts the result in Y.
200  //N.B. Assumes Y, X have been allocated.
201  void CoarseOp(GaugeField &Y, GaugeField &X, const Transfer &T,
202  const cudaGaugeField &gauge, const cudaCloverField *clover,
203  double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc) {
204 
205 #ifdef GPU_MULTIGRID
206  QudaPrecision precision = Y.Precision();
207  QudaFieldLocation location = checkLocation(Y, X);
208 
209  GaugeField *U = location == QUDA_CUDA_FIELD_LOCATION ? const_cast<cudaGaugeField*>(&gauge) : nullptr;
210  CloverField *C = location == QUDA_CUDA_FIELD_LOCATION ? const_cast<cudaCloverField*>(clover) : nullptr;
211 
212  if (location == QUDA_CPU_FIELD_LOCATION) {
213  //First make a cpu gauge field from the cuda gauge field
214  int pad = 0;
215  GaugeFieldParam gf_param(gauge.X(), precision, QUDA_RECONSTRUCT_NO, pad, gauge.Geometry());
216  gf_param.order = QUDA_QDP_GAUGE_ORDER;
217  gf_param.fixed = gauge.GaugeFixed();
218  gf_param.link_type = gauge.LinkType();
219  gf_param.t_boundary = gauge.TBoundary();
220  gf_param.anisotropy = gauge.Anisotropy();
221  gf_param.gauge = NULL;
222  gf_param.create = QUDA_NULL_FIELD_CREATE;
223  gf_param.siteSubset = QUDA_FULL_SITE_SUBSET;
224  gf_param.nFace = 1;
225  gf_param.ghostExchange = QUDA_GHOST_EXCHANGE_PAD;
226 
227  U = new cpuGaugeField(gf_param);
228 
229  //Copy the cuda gauge field to the cpu
230  gauge.saveCPUField(*static_cast<cpuGaugeField*>(U));
231  } else if (location == QUDA_CUDA_FIELD_LOCATION && gauge.Reconstruct() != QUDA_RECONSTRUCT_NO) {
232  //Create a copy of the gauge field with no reconstruction, required for fine-grained access
233  GaugeFieldParam gf_param(gauge);
234  gf_param.reconstruct = QUDA_RECONSTRUCT_NO;
235  gf_param.order = QUDA_FLOAT2_GAUGE_ORDER;
236  gf_param.setPrecision(gf_param.Precision());
237  U = new cudaGaugeField(gf_param);
238 
239  U->copy(gauge);
240  }
241 
242  CloverFieldParam cf_param;
243  cf_param.nDim = 4;
244  cf_param.pad = 0;
245  cf_param.setPrecision(clover ? clover->Precision() : QUDA_SINGLE_PRECISION);
246 
247  // if we have no clover term then create an empty clover field
248  for(int i = 0; i < cf_param.nDim; i++) cf_param.x[i] = clover ? clover->X()[i] : 0;
249 
250  cf_param.direct = true;
251  cf_param.inverse = true;
252  cf_param.clover = NULL;
253  cf_param.norm = 0;
254  cf_param.cloverInv = NULL;
255  cf_param.invNorm = 0;
256  cf_param.create = QUDA_NULL_FIELD_CREATE;
258 
259  if (location == QUDA_CUDA_FIELD_LOCATION && !clover) {
260  // create a dummy cudaCloverField if one is not defined
261  cf_param.order = QUDA_INVALID_CLOVER_ORDER;
262  C = new cudaCloverField(cf_param);
263  } else if (location == QUDA_CPU_FIELD_LOCATION) {
264  //Create a cpuCloverField from the cudaCloverField
265  cf_param.order = QUDA_PACKED_CLOVER_ORDER;
266  C = new cpuCloverField(cf_param);
267  if (clover) clover->saveCPUField(*static_cast<cpuCloverField*>(C));
268  }
269 
270  //Create a field UV which holds U*V. Has the same structure as V.
271  ColorSpinorParam UVparam(T.Vectors(location));
272  UVparam.create = QUDA_ZERO_FIELD_CREATE;
273  UVparam.location = location;
274  UVparam.setPrecision(T.Vectors(location).Precision());
275  UVparam.mem_type = Y.MemType(); // allocate temporaries to match coarse-grid link field
276 
278 
279  // if we are coarsening a preconditioned clover or twisted-mass operator we need
280  // an additional vector to store the cloverInv * V field, else just alias v
281  ColorSpinorField *av = ((matpc != QUDA_MATPC_INVALID && clover) || (dirac == QUDA_TWISTED_MASSPC_DIRAC)) ?
282  ColorSpinorField::Create(UVparam) : &const_cast<ColorSpinorField&>(T.Vectors(location));
283 
284  GaugeField *Yatomic = &Y;
285  GaugeField *Xatomic = &X;
286  if (Y.Precision() < QUDA_SINGLE_PRECISION) {
287  // we need to coarsen into single precision fields (float or int), so we allocate temporaries for this purpose
288  // else we can just coarsen directly into the original fields
289  GaugeFieldParam param(X); // use X since we want scalar geometry
290  param.location = location;
291  param.setPrecision(QUDA_SINGLE_PRECISION, location == QUDA_CUDA_FIELD_LOCATION ? true : false);
292 
293  Yatomic = GaugeField::Create(param);
294  Xatomic = GaugeField::Create(param);
295  }
296 
297  calculateY(Y, X, *Yatomic, *Xatomic, *uv, *av, T, *U, *C, kappa, mu, mu_factor, dirac, matpc);
298 
299  if (Yatomic != &Y) delete Yatomic;
300  if (Xatomic != &X) delete Xatomic;
301 
302  if (&T.Vectors(location) != av) delete av;
303  delete uv;
304 
305  if (C != clover) delete C;
306  if (U != &gauge) delete U;
307 #else
308  errorQuda("Multigrid has not been built");
309 #endif // GPU_MULTIGRID
310  }
311 
312 } //namespace quda
QudaCloverFieldOrder order
Definition: clover_field.h:21
double mu
Definition: test_util.cpp:1648
enum QudaPrecision_s QudaPrecision
void saveCPUField(cpuGaugeField &cpu) const
Upload from this field into a CPU field.
QudaVerbosity getVerbosity()
Definition: util_quda.cpp:21
double kappa
Definition: test_util.cpp:1647
#define checkPrecision(...)
#define errorQuda(...)
Definition: util_quda.h:121
QudaFieldCreate create
Definition: clover_field.h:22
void saveCPUField(cpuCloverField &cpu) const
enum QudaFieldOrder_s QudaFieldOrder
QudaLinkType LinkType() const
Definition: gauge_field.h:255
void CoarseOp(GaugeField &Y, GaugeField &X, 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:201
static ColorSpinorField * Create(const ColorSpinorParam &param)
QudaFieldGeometry Geometry() const
Definition: gauge_field.h:258
QudaSiteSubset siteSubset
Definition: lattice_field.h:71
QudaGaugeParam param
Definition: pack_test.cpp:17
void matpc(void *outEven, void **gauge, void *inEven, double kappa, QudaMatPCType matpc_type, int dagger_bit, QudaPrecision sPrecision, QudaPrecision gPrecision, double mferm)
virtual QudaMemoryType MemType() const
int x[QUDA_MAX_DIM]
Definition: lattice_field.h:67
enum QudaCloverFieldOrder_s QudaCloverFieldOrder
static GaugeField * Create(const GaugeFieldParam &param)
Create the gauge field, with meta data specified in the parameter struct.
void setPrecision(QudaPrecision precision)
Definition: clover_field.h:23
QudaFieldLocation location
Definition: gauge_field.h:12
enum QudaMatPCType_s QudaMatPCType
double Anisotropy() const
Definition: gauge_field.h:252
QudaGaugeFieldOrder order
Definition: gauge_field.h:17
#define checkLocation(...)
enum QudaGaugeFieldOrder_s QudaGaugeFieldOrder
int X[4]
Definition: covdev_test.cpp:70
int V
Definition: test_util.cpp:27
void calculateY(coarseGauge &Y, coarseGauge &X, coarseGaugeAtomic &Y_atomic, coarseGaugeAtomic &X_atomic, Ftmp &UV, F &AV, Vt &V, fineGauge &G, fineClover &C, fineClover &Cinv, GaugeField &Y_, GaugeField &X_, GaugeField &Y_atomic_, GaugeField &X_atomic_, ColorSpinorField &uv, ColorSpinorField &av, const ColorSpinorField &v, double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc, bool need_bidirectional, const int *fine_to_coarse, const int *coarse_to_fine)
Calculate the coarse-link field, including the coarse clover field.
Definition: coarse_op.cuh:869
enum QudaFieldLocation_s QudaFieldLocation
void setPrecision(QudaPrecision precision, bool force_native=false)
Helper function for setting the precision and corresponding field order for QUDA internal fields...
Definition: gauge_field.h:131
GaugeCovDev * dirac
Definition: covdev_test.cpp:73
QudaPrecision Precision() const
Definition: lattice_field.h:58
#define printfQuda(...)
Definition: util_quda.h:115
double mu_factor[QUDA_MAX_MG_LEVEL]
Definition: test_util.cpp:1674
QudaReconstructType reconstruct
Definition: gauge_field.h:16
QudaReconstructType Reconstruct() const
Definition: gauge_field.h:250
QudaTboundary TBoundary() const
Definition: gauge_field.h:254
QudaGaugeFixed GaugeFixed() const
Definition: gauge_field.h:256
QudaPrecision Precision() const
const ColorSpinorField & Vectors(QudaFieldLocation location=QUDA_INVALID_FIELD_LOCATION) const
Definition: transfer.h:205
virtual void copy(const GaugeField &src)=0
enum QudaDiracType_s QudaDiracType
const int * X() const