QUDA  0.9.0
coarse_op.cu
Go to the documentation of this file.
1 #include <transfer.h>
2 #include <color_spinor_field.h>
4 #include <gauge_field.h>
5 #include <gauge_field_order.h>
6 #include <clover_field_order.h>
7 #include <complex_quda.h>
8 #include <index_helper.cuh>
9 #include <gamma.cuh>
10 #include <blas_cublas.h>
11 #include <coarse_op.cuh>
12 
13 namespace quda {
14 
15 #ifdef GPU_MULTIGRID
16 
17  template <typename Float, int fineColor, int fineSpin, int coarseColor, int coarseSpin>
18  void calculateY(GaugeField &Y, GaugeField &X, GaugeField &Xinv, GaugeField &Yhat, ColorSpinorField &uv, ColorSpinorField &av, const Transfer &T,
19  const GaugeField &g, const CloverField &c, double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc) {
20 
21  QudaFieldLocation location = Y.Location();
22 
23  if (location == QUDA_CPU_FIELD_LOCATION) {
24 
26  constexpr QudaGaugeFieldOrder gOrder = QUDA_QDP_GAUGE_ORDER;
28 
29  if (T.Vectors(Y.Location()).FieldOrder() != csOrder)
30  errorQuda("Unsupported field order %d\n", T.Vectors(Y.Location()).FieldOrder());
31  if (g.FieldOrder() != gOrder) errorQuda("Unsupported field order %d\n", g.FieldOrder());
32  if (c.Order() != clOrder && c.Bytes()) errorQuda("Unsupported field order %d\n", c.Order());
33 
34  typedef typename colorspinor::FieldOrderCB<Float,fineSpin,fineColor,coarseColor,csOrder> F;
35  typedef typename gauge::FieldOrder<Float,fineColor,1,gOrder> gFine;
36  typedef typename gauge::FieldOrder<Float,coarseColor*coarseSpin,coarseSpin,gOrder> gCoarse;
37  typedef typename clover::FieldOrder<Float,fineColor,fineSpin,clOrder> cFine;
38 
39  const ColorSpinorField &v = T.Vectors(g.Location());
40 
41  F vAccessor(const_cast<ColorSpinorField&>(v));
42  F uvAccessor(const_cast<ColorSpinorField&>(uv));
43  F avAccessor(const_cast<ColorSpinorField&>(av));
44  gFine gAccessor(const_cast<GaugeField&>(g));
45  gCoarse yAccessor(const_cast<GaugeField&>(Y));
46  gCoarse xAccessor(const_cast<GaugeField&>(X));
47  gCoarse xInvAccessor(const_cast<GaugeField&>(Xinv));
48  cFine cAccessor(const_cast<CloverField&>(c), false);
49  cFine cInvAccessor(const_cast<CloverField&>(c), true);
50 
51  calculateY<false,Float,fineSpin,fineColor,coarseSpin,coarseColor,gOrder>
52  (yAccessor, xAccessor, xInvAccessor, uvAccessor, avAccessor, vAccessor, gAccessor, cAccessor, cInvAccessor, Y, X, Xinv, Yhat, av, v, kappa, mu, mu_factor, dirac, matpc);
53 
54  } else {
55 
56  constexpr QudaFieldOrder csOrder = QUDA_FLOAT2_FIELD_ORDER;
59 
60  if (T.Vectors(Y.Location()).FieldOrder() != csOrder)
61  errorQuda("Unsupported field order %d\n", T.Vectors(Y.Location()).FieldOrder());
62  if (g.FieldOrder() != gOrder) errorQuda("Unsupported field order %d\n", g.FieldOrder());
63  if (c.Order() != clOrder && c.Bytes()) errorQuda("Unsupported field order %d\n", c.Order());
64 
65  typedef typename colorspinor::FieldOrderCB<Float,fineSpin,fineColor,coarseColor,csOrder> F;
66  typedef typename gauge::FieldOrder<Float,fineColor,1,gOrder> gFine;
67  typedef typename gauge::FieldOrder<Float,coarseColor*coarseSpin,coarseSpin,gOrder> gCoarse;
68  typedef typename clover::FieldOrder<Float,fineColor,fineSpin,clOrder> cFine;
69 
70  const ColorSpinorField &v = T.Vectors(g.Location());
71 
72  F vAccessor(const_cast<ColorSpinorField&>(v));
73  F uvAccessor(const_cast<ColorSpinorField&>(uv));
74  F avAccessor(const_cast<ColorSpinorField&>(av));
75  gFine gAccessor(const_cast<GaugeField&>(g));
76  gCoarse yAccessor(const_cast<GaugeField&>(Y));
77  gCoarse xAccessor(const_cast<GaugeField&>(X));
78  gCoarse xInvAccessor(const_cast<GaugeField&>(Xinv));
79  cFine cAccessor(const_cast<CloverField&>(c), false);
80  cFine cInvAccessor(const_cast<CloverField&>(c), true);
81 
82  calculateY<false,Float,fineSpin,fineColor,coarseSpin,coarseColor,gOrder>
83  (yAccessor, xAccessor, xInvAccessor, uvAccessor, avAccessor, vAccessor, gAccessor, cAccessor, cInvAccessor, Y, X, Xinv, Yhat, av, v, kappa, mu, mu_factor, dirac, matpc);
84 
85  }
86 
87  }
88 
89  // template on the number of coarse degrees of freedom
90  template <typename Float, int fineColor, int fineSpin>
91  void calculateY(GaugeField &Y, GaugeField &X, GaugeField &Xinv, GaugeField &Yhat, ColorSpinorField &uv, ColorSpinorField &av, const Transfer &T,
92  const GaugeField &g, const CloverField &c, double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc) {
93  if (T.Vectors().Nspin()/T.Spin_bs() != 2)
94  errorQuda("Unsupported number of coarse spins %d\n",T.Vectors().Nspin()/T.Spin_bs());
95  const int coarseSpin = 2;
96  const int coarseColor = Y.Ncolor() / coarseSpin;
97 
98  if (coarseColor == 2) {
99  calculateY<Float,fineColor,fineSpin,2,coarseSpin>(Y, X, Xinv, Yhat, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
100 #if 0
101  } else if (coarseCoor == 4) {
102  calculateY<Float,fineColor,fineSpin,4,coarseSpin>(Y, X, Xinv, Yhat, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
103  } else if (coarseColor == 8) {
104  calculateY<Float,fineColor,fineSpin,8,coarseSpin>(Y, X, Xinv, Yhat, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
105  } else if (coarseColor == 12) {
106  calculateY<Float,fineColor,fineSpin,12,coarseSpin>(Y, X, Xinv, Yhat, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
107  } else if (coarseColor == 16) {
108  calculateY<Float,fineColor,fineSpin,16,coarseSpin>(Y, X, Xinv, Yhat, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
109  } else if (coarseColor == 20) {
110  calculateY<Float,fineColor,fineSpin,20,coarseSpin>(Y, X, Xinv, Yhat, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
111 #endif
112  } else if (coarseColor == 24) {
113  calculateY<Float,fineColor,fineSpin,24,coarseSpin>(Y, X, Xinv, Yhat, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
114 #if 0
115  } else if (coarseColor == 32) {
116  calculateY<Float,fineColor,fineSpin,32,coarseSpin>(Y, X, Xinv, Yhat, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
117 #endif
118  } else {
119  errorQuda("Unsupported number of coarse dof %d\n", Y.Ncolor());
120  }
121  }
122 
123  // template on fine spin
124  template <typename Float, int fineColor>
125  void calculateY(GaugeField &Y, GaugeField &X, GaugeField &Xinv, GaugeField &Yhat, ColorSpinorField &uv, ColorSpinorField &av, const Transfer &T,
126  const GaugeField &g, const CloverField &c, double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc) {
127  if (uv.Nspin() == 4) {
128  calculateY<Float,fineColor,4>(Y, X, Xinv, Yhat, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
129  } else {
130  errorQuda("Unsupported number of spins %d\n", uv.Nspin());
131  }
132  }
133 
134  // template on fine colors
135  template <typename Float>
136  void calculateY(GaugeField &Y, GaugeField &X, GaugeField &Xinv, GaugeField &Yhat, ColorSpinorField &uv, ColorSpinorField &av, const Transfer &T,
137  const GaugeField &g, const CloverField &c, double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc) {
138  if (g.Ncolor() == 3) {
139  calculateY<Float,3>(Y, X, Xinv, Yhat, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
140  } else {
141  errorQuda("Unsupported number of colors %d\n", g.Ncolor());
142  }
143  }
144 
145  //Does the heavy lifting of creating the coarse color matrices Y
146  void calculateY(GaugeField &Y, GaugeField &X, GaugeField &Xinv, GaugeField &Yhat, ColorSpinorField &uv, ColorSpinorField &av, const Transfer &T,
147  const GaugeField &g, const CloverField &c, double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc) {
148  checkPrecision(X, Y, uv, T.Vectors(), g);
149 
150  printfQuda("Computing Y field......\n");
151 
152  if (Y.Precision() == QUDA_DOUBLE_PRECISION) {
153 #ifdef GPU_MULTIGRID_DOUBLE
154  calculateY<double>(Y, X, Xinv, Yhat, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
155 #else
156  errorQuda("Double precision multigrid has not been enabled");
157 #endif
158  } else if (Y.Precision() == QUDA_SINGLE_PRECISION) {
159  calculateY<float>(Y, X, Xinv, Yhat, uv, av, T, g, c, kappa, mu, mu_factor, dirac, matpc);
160  } else {
161  errorQuda("Unsupported precision %d\n", Y.Precision());
162  }
163  printfQuda("....done computing Y field\n");
164  }
165 
166 #endif // GPU_MULTIGRID
167 
168  //Calculates the coarse color matrix and puts the result in Y.
169  //N.B. Assumes Y, X have been allocated.
170  void CoarseOp(GaugeField &Y, GaugeField &X, GaugeField &Xinv, GaugeField &Yhat, const Transfer &T,
171  const cudaGaugeField &gauge, const cudaCloverField *clover,
172  double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc) {
173 
174 #ifdef GPU_MULTIGRID
175  QudaPrecision precision = Y.Precision();
176  QudaFieldLocation location = checkLocation(Y, X, Xinv, Yhat);
177 
178  GaugeField *U = location == QUDA_CUDA_FIELD_LOCATION ? const_cast<cudaGaugeField*>(&gauge) : nullptr;
179  CloverField *C = location == QUDA_CUDA_FIELD_LOCATION ? const_cast<cudaCloverField*>(clover) : nullptr;
180 
181  if (location == QUDA_CPU_FIELD_LOCATION) {
182  //First make a cpu gauge field from the cuda gauge field
183  int pad = 0;
184  GaugeFieldParam gf_param(gauge.X(), precision, QUDA_RECONSTRUCT_NO, pad, gauge.Geometry());
185  gf_param.order = QUDA_QDP_GAUGE_ORDER;
186  gf_param.fixed = gauge.GaugeFixed();
187  gf_param.link_type = gauge.LinkType();
188  gf_param.t_boundary = gauge.TBoundary();
189  gf_param.anisotropy = gauge.Anisotropy();
190  gf_param.gauge = NULL;
191  gf_param.create = QUDA_NULL_FIELD_CREATE;
192  gf_param.siteSubset = QUDA_FULL_SITE_SUBSET;
193  gf_param.nFace = 1;
194  gf_param.ghostExchange = QUDA_GHOST_EXCHANGE_PAD;
195 
196  U = new cpuGaugeField(gf_param);
197 
198  //Copy the cuda gauge field to the cpu
199  gauge.saveCPUField(*static_cast<cpuGaugeField*>(U));
200  } else if (location == QUDA_CUDA_FIELD_LOCATION && gauge.Reconstruct() != QUDA_RECONSTRUCT_NO) {
201  //Create a copy of the gauge field with no reconstruction, required for fine-grained access
202  GaugeFieldParam gf_param(gauge);
203  gf_param.reconstruct = QUDA_RECONSTRUCT_NO;
204  gf_param.setPrecision(gf_param.precision);
205  U = new cudaGaugeField(gf_param);
206 
207  U->copy(gauge);
208  }
209 
210  CloverFieldParam cf_param;
211  cf_param.nDim = 4;
212  cf_param.pad = 0;
213  cf_param.precision = clover ? clover->Precision() : QUDA_INVALID_PRECISION;
214 
215  // if we have no clover term then create an empty clover field
216  for(int i = 0; i < cf_param.nDim; i++) cf_param.x[i] = clover ? clover->X()[i] : 0;
217 
218  cf_param.direct = true;
219  cf_param.inverse = true;
220  cf_param.clover = NULL;
221  cf_param.norm = 0;
222  cf_param.cloverInv = NULL;
223  cf_param.invNorm = 0;
224  cf_param.create = QUDA_NULL_FIELD_CREATE;
226 
227  if (location == QUDA_CUDA_FIELD_LOCATION && !clover) {
228  // create a dummy cudaCloverField if one is not defined
229  cf_param.order = QUDA_INVALID_CLOVER_ORDER;
230  C = new cudaCloverField(cf_param);
231  } else if (location == QUDA_CPU_FIELD_LOCATION) {
232  //Create a cpuCloverField from the cudaCloverField
233  cf_param.order = QUDA_PACKED_CLOVER_ORDER;
234  C = new cpuCloverField(cf_param);
235  if (clover) clover->saveCPUField(*static_cast<cpuCloverField*>(C));
236  }
237 
238  //Create a field UV which holds U*V. Has the same structure as V.
239  ColorSpinorParam UVparam(T.Vectors(location));
240  UVparam.create = QUDA_ZERO_FIELD_CREATE;
241  UVparam.location = location;
242 
244 
245  // if we are coarsening a preconditioned clover or twisted-mass operator we need
246  // an additional vector to store the cloverInv * V field, else just alias v
248  &const_cast<ColorSpinorField&>(T.Vectors(location));
249 
250  calculateY(Y, X, Xinv, Yhat, *uv, *av, T, *U, *C, kappa, mu, mu_factor, dirac, matpc);
251 
252  if (&T.Vectors(location) != av) delete av;
253  delete uv;
254 
255  if (C != clover) delete C;
256  if (U != &gauge) delete U;
257 #else
258  errorQuda("Multigrid has not been built");
259 #endif // GPU_MULTIGRID
260  }
261 
262 } //namespace quda
QudaCloverFieldOrder order
Definition: clover_field.h:21
double mu
Definition: test_util.cpp:1643
enum QudaPrecision_s QudaPrecision
void saveCPUField(cpuGaugeField &cpu) const
Upload from this field into a CPU field.
#define checkPrecision(...)
#define errorQuda(...)
Definition: util_quda.h:90
void setPrecision(QudaPrecision precision)
Helper function for setting the precision and corresponding field order for QUDA internal fields...
Definition: gauge_field.h:113
QudaFieldCreate create
Definition: clover_field.h:22
double mu_factor[QUDA_MAX_MG_LEVEL]
Definition: test_util.cpp:1659
enum QudaFieldOrder_s QudaFieldOrder
QudaLinkType LinkType() const
Definition: gauge_field.h:209
static ColorSpinorField * Create(const ColorSpinorParam &param)
QudaPrecision precision
Definition: lattice_field.h:54
QudaFieldGeometry Geometry() const
Definition: gauge_field.h:212
Main header file for host and device accessors to CloverFields.
QudaSiteSubset siteSubset
Definition: lattice_field.h:55
void matpc(void *outEven, void **gauge, void *inEven, double kappa, QudaMatPCType matpc_type, int dagger_bit, QudaPrecision sPrecision, QudaPrecision gPrecision, double mferm)
int x[QUDA_MAX_DIM]
Definition: lattice_field.h:50
enum QudaCloverFieldOrder_s QudaCloverFieldOrder
const ColorSpinorField & Vectors(QudaFieldLocation location=QUDA_CPU_FIELD_LOCATION) const
Definition: transfer.h:195
VOLATILE spinorFloat kappa
enum QudaMatPCType_s QudaMatPCType
double Anisotropy() const
Definition: gauge_field.h:205
QudaGaugeFieldOrder order
Definition: gauge_field.h:15
#define checkLocation(...)
enum QudaGaugeFieldOrder_s QudaGaugeFieldOrder
Main header file for host and device accessors to GaugeFields.
enum QudaFieldLocation_s QudaFieldLocation
GaugeCovDev * dirac
Definition: covdev_test.cpp:75
#define printfQuda(...)
Definition: util_quda.h:84
QudaReconstructType reconstruct
Definition: gauge_field.h:14
const void * c
QudaReconstructType Reconstruct() const
Definition: gauge_field.h:203
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
QudaTboundary TBoundary() const
Definition: gauge_field.h:208
QudaGaugeFixed GaugeFixed() const
Definition: gauge_field.h:210
QudaPrecision Precision() const
virtual void copy(const GaugeField &src)=0
void calculateY(coarseGauge &Y, coarseGauge &X, coarseGauge &Xinv, Ftmp &UV, F &AV, F &V, fineGauge &G, fineClover &C, fineClover &Cinv, GaugeField &Y_, GaugeField &X_, GaugeField &Xinv_, GaugeField &Yhat_, ColorSpinorField &av, const ColorSpinorField &v, double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc)
Calculate the coarse-link field, include the clover field, and its inverse, and finally also compute ...
Definition: coarse_op.cuh:1487
enum QudaDiracType_s QudaDiracType
const int * X() const