QUDA  1.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
coarsecoarse_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 
5 #define COARSECOARSE
6 #ifdef GPU_MULTIGRID
7 #include <coarse_op.cuh>
8 #endif
9 namespace quda {
10 
11 #ifdef GPU_MULTIGRID
12 
13  template <typename Float, typename vFloat, int fineColor, int fineSpin, int coarseColor, int coarseSpin>
14  void calculateYcoarse(GaugeField &Y, GaugeField &X, GaugeField &Yatomic, GaugeField &Xatomic,
15  ColorSpinorField &uv, const Transfer &T, const GaugeField &g, const GaugeField &clover,
16  const GaugeField &cloverInv, double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc,
17  bool need_bidirectional) {
18 
19  if (Y.Location() == QUDA_CPU_FIELD_LOCATION) {
20 
22  constexpr QudaGaugeFieldOrder gOrder = QUDA_QDP_GAUGE_ORDER;
23 
24  if (T.Vectors(Y.Location()).FieldOrder() != csOrder)
25  errorQuda("Unsupported field order %d\n", T.Vectors(Y.Location()).FieldOrder());
26  if (g.FieldOrder() != gOrder) errorQuda("Unsupported field order %d\n", g.FieldOrder());
27 
28  typedef typename colorspinor::FieldOrderCB<Float,fineSpin,fineColor,coarseColor,csOrder,vFloat> V;
29  typedef typename colorspinor::FieldOrderCB<Float,2*fineSpin,fineColor,coarseColor,csOrder,vFloat> F;
30  typedef typename gauge::FieldOrder<Float,fineColor*fineSpin,fineSpin,gOrder,true,vFloat> gFine;
31  typedef typename gauge::FieldOrder<Float,fineColor*fineSpin,fineSpin,gOrder,true,vFloat> cFine;
32  typedef typename gauge::FieldOrder<Float,coarseColor*coarseSpin,coarseSpin,gOrder,true,vFloat> gCoarse;
33  typedef typename gauge::FieldOrder<Float,coarseColor*coarseSpin,coarseSpin,gOrder,true,storeType> gCoarseAtomic;
34 
35  const ColorSpinorField &v = T.Vectors(Y.Location());
36 
37  V vAccessor(const_cast<ColorSpinorField&>(v));
38  F uvAccessor(const_cast<ColorSpinorField&>(uv));
39  gFine gAccessor(const_cast<GaugeField&>(g));
40  cFine cAccessor(const_cast<GaugeField&>(clover));
41  cFine cInvAccessor(const_cast<GaugeField&>(cloverInv));
42  gCoarse yAccessor(const_cast<GaugeField&>(Y));
43  gCoarse xAccessor(const_cast<GaugeField&>(X));
44  gCoarseAtomic yAccessorAtomic(const_cast<GaugeField&>(Yatomic));
45  gCoarseAtomic xAccessorAtomic(const_cast<GaugeField&>(Xatomic));
46 
47  calculateY<true,Float,fineSpin,fineColor,coarseSpin,coarseColor>
48  (yAccessor, xAccessor, yAccessorAtomic, xAccessorAtomic,
49  uvAccessor, vAccessor, vAccessor, gAccessor, cAccessor, cInvAccessor,
50  Y, X, Yatomic, Xatomic, uv, const_cast<ColorSpinorField&>(v), v, kappa, mu, mu_factor, dirac, matpc, need_bidirectional,
51  T.fineToCoarse(Y.Location()), T.coarseToFine(Y.Location()));
52 
53  } else {
54 
55  constexpr QudaFieldOrder csOrder = QUDA_FLOAT2_FIELD_ORDER;
57 
58  if (T.Vectors(Y.Location()).FieldOrder() != csOrder)
59  errorQuda("Unsupported field order %d\n", T.Vectors(Y.Location()).FieldOrder());
60  if (g.FieldOrder() != gOrder) errorQuda("Unsupported field order %d\n", g.FieldOrder());
61 
62  typedef typename colorspinor::FieldOrderCB<Float,fineSpin,fineColor,coarseColor,csOrder,vFloat> V;
63  typedef typename colorspinor::FieldOrderCB<Float,2*fineSpin,fineColor,coarseColor,csOrder,vFloat> F;
64  typedef typename gauge::FieldOrder<Float,fineColor*fineSpin,fineSpin,gOrder,true,vFloat> gFine;
65  typedef typename gauge::FieldOrder<Float,fineColor*fineSpin,fineSpin,gOrder,true,vFloat> cFine;
66  typedef typename gauge::FieldOrder<Float,coarseColor*coarseSpin,coarseSpin,gOrder,true,vFloat> gCoarse;
67  typedef typename gauge::FieldOrder<Float,coarseColor*coarseSpin,coarseSpin,gOrder,true,storeType> gCoarseAtomic;
68 
69  const ColorSpinorField &v = T.Vectors(Y.Location());
70 
71  V vAccessor(const_cast<ColorSpinorField&>(v));
72  F uvAccessor(const_cast<ColorSpinorField&>(uv));
73  gFine gAccessor(const_cast<GaugeField&>(g));
74  cFine cAccessor(const_cast<GaugeField&>(clover));
75  cFine cInvAccessor(const_cast<GaugeField&>(cloverInv));
76  gCoarse yAccessor(const_cast<GaugeField&>(Y));
77  gCoarse xAccessor(const_cast<GaugeField&>(X));
78  gCoarseAtomic yAccessorAtomic(const_cast<GaugeField&>(Yatomic));
79  gCoarseAtomic xAccessorAtomic(const_cast<GaugeField&>(Xatomic));
80 
81  calculateY<true,Float,fineSpin,fineColor,coarseSpin,coarseColor>
82  (yAccessor, xAccessor, yAccessorAtomic, xAccessorAtomic,
83  uvAccessor, vAccessor, vAccessor, gAccessor, cAccessor, cInvAccessor,
84  Y, X, Yatomic, Xatomic, uv, const_cast<ColorSpinorField&>(v), v, kappa, mu, mu_factor, dirac, matpc, need_bidirectional,
85  T.fineToCoarse(Y.Location()), T.coarseToFine(Y.Location()));
86 
87  }
88 
89  }
90 
91  // template on the number of coarse degrees of freedom
92  template <typename Float, typename vFloat, int fineColor, int fineSpin>
93  void calculateYcoarse(GaugeField &Y, GaugeField &X, GaugeField &Yatomic, GaugeField &Xatomic,
94  ColorSpinorField &uv, const Transfer &T, const GaugeField &g, const GaugeField &clover,
95  const GaugeField &cloverInv, double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc, bool need_bidirectional) {
96  if (T.Vectors().Nspin()/T.Spin_bs() != 2)
97  errorQuda("Unsupported number of coarse spins %d\n",T.Vectors().Nspin()/T.Spin_bs());
98  const int coarseSpin = 2;
99  const int coarseColor = Y.Ncolor() / coarseSpin;
100 
101  if (coarseColor == 6) {
102  calculateYcoarse<Float,vFloat,fineColor,fineSpin,6,coarseSpin>(Y, X, Yatomic, Xatomic, uv, T, g, clover, cloverInv, kappa, mu, mu_factor, dirac, matpc, need_bidirectional);
103 #if 0
104  } else if (coarseColor == 8) {
105  calculateYcoarse<Float,vFloat,fineColor,fineSpin,8,coarseSpin>(Y, X, Yatomic, Xatomic, uv, T, g, clover, cloverInv, kappa, mu, mu_factor, dirac, matpc, need_bidirectional);
106  } else if (coarseColor == 16) {
107  calculateYcoarse<Float,vFloat,fineColor,fineSpin,16,coarseSpin>(Y, X, Yatomic, Xatomic, uv, T, g, clover, cloverInv, kappa, mu, mu_factor, dirac, matpc, need_bidirectional);
108 #endif
109  } else if (coarseColor == 24) {
110  calculateYcoarse<Float,vFloat,fineColor,fineSpin,24,coarseSpin>(Y, X, Yatomic, Xatomic, uv, T, g, clover, cloverInv, kappa, mu, mu_factor, dirac, matpc, need_bidirectional);
111  } else if (coarseColor == 32) {
112  calculateYcoarse<Float,vFloat,fineColor,fineSpin,32,coarseSpin>(Y, X, Yatomic, Xatomic, uv, T, g, clover, cloverInv, kappa, mu, mu_factor, dirac, matpc, need_bidirectional);
113  } else {
114  errorQuda("Unsupported number of coarse dof %d\n", Y.Ncolor());
115  }
116  }
117 
118  // template on fine spin
119  template <typename Float, typename vFloat, int fineColor>
120  void calculateYcoarse(GaugeField &Y, GaugeField &X, GaugeField &Yatomic, GaugeField &Xatomic,
121  ColorSpinorField &uv, const Transfer &T, const GaugeField &g, const GaugeField &clover,
122  const GaugeField &cloverInv, double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc, bool need_bidirectional) {
123  if (T.Vectors().Nspin() == 2) {
124  calculateYcoarse<Float,vFloat,fineColor,2>(Y, X, Yatomic, Xatomic, uv, T, g, clover, cloverInv, kappa, mu, mu_factor, dirac, matpc, need_bidirectional);
125  } else {
126  errorQuda("Unsupported number of spins %d\n", T.Vectors().Nspin());
127  }
128  }
129 
130  // template on fine colors
131  template <typename Float, typename vFloat>
132  void calculateYcoarse(GaugeField &Y, GaugeField &X, GaugeField &Yatomic, GaugeField &Xatomic,
133  ColorSpinorField &uv, const Transfer &T, const GaugeField &g, const GaugeField &clover,
134  const GaugeField &cloverInv, double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc, bool need_bidirectional) {
135  if (g.Ncolor()/T.Vectors().Nspin() == 6) { // free field Wilson
136  calculateYcoarse<Float,vFloat,6>(Y, X, Yatomic, Xatomic, uv, T, g, clover, cloverInv, kappa, mu, mu_factor, dirac, matpc, need_bidirectional);
137 #if 0
138  } else if (g.Ncolor()/T.Vectors().Nspin() == 8) {
139  calculateYcoarse<Float,vFloat,8>(Y, X, Yatomic, Xatomic, uv, T, g, clover, cloverInv, kappa, mu, mu_factor, dirac, matpc, need_bidirectional);
140  } else if (g.Ncolor()/T.Vectors().Nspin() == 16) {
141  calculateYcoarse<Float,vFloat,16>(Y, X, Yatomic, Xatomic, uv, T, g, clover, cloverInv, kappa, mu, mu_factor, dirac, matpc, need_bidirectional);
142 #endif
143  } else if (g.Ncolor()/T.Vectors().Nspin() == 24) {
144  calculateYcoarse<Float,vFloat,24>(Y, X, Yatomic, Xatomic, uv, T, g, clover, cloverInv, kappa, mu, mu_factor, dirac, matpc, need_bidirectional);
145  } else if (g.Ncolor()/T.Vectors().Nspin() == 32) {
146  calculateYcoarse<Float,vFloat,32>(Y, X, Yatomic, Xatomic, uv, T, g, clover, cloverInv, kappa, mu, mu_factor, dirac, matpc, need_bidirectional);
147  } else {
148  errorQuda("Unsupported number of colors %d\n", g.Ncolor());
149  }
150  }
151 
152  //Does the heavy lifting of creating the coarse color matrices Y
153  void calculateYcoarse(GaugeField &Y, GaugeField &X, GaugeField &Yatomic, GaugeField &Xatomic, ColorSpinorField &uv,
154  const Transfer &T, const GaugeField &g, const GaugeField &clover, const GaugeField &cloverInv,
155  double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc, bool need_bidirectional) {
156  checkPrecision(X, Y, g, clover, cloverInv, uv, T.Vectors(X.Location()));
157  checkPrecision(Xatomic, Yatomic);
158 
159  if (getVerbosity() >= QUDA_SUMMARIZE) printfQuda("Computing Y field......\n");
160  if (Y.Precision() == QUDA_DOUBLE_PRECISION) {
161 #ifdef GPU_MULTIGRID_DOUBLE
162  if (T.Vectors(X.Location()).Precision() == QUDA_DOUBLE_PRECISION) {
163  calculateYcoarse<double,double>(Y, X, Yatomic, Xatomic, uv, T, g, clover, cloverInv, kappa, mu, mu_factor, dirac, matpc, need_bidirectional);
164  } else {
165  errorQuda("Unsupported precision %d\n", Y.Precision());
166  }
167 #else
168  errorQuda("Double precision multigrid has not been enabled");
169 #endif
170  } else if (Y.Precision() == QUDA_SINGLE_PRECISION) {
171  if (T.Vectors(X.Location()).Precision() == QUDA_SINGLE_PRECISION) {
172  calculateYcoarse<float,float>(Y, X, Yatomic, Xatomic, uv, T, g, clover, cloverInv, kappa, mu, mu_factor, dirac, matpc, need_bidirectional);
173  } else {
174  errorQuda("Unsupported precision %d\n", T.Vectors(X.Location()).Precision());
175  }
176  } else if (Y.Precision() == QUDA_HALF_PRECISION) {
177  if (T.Vectors(X.Location()).Precision() == QUDA_HALF_PRECISION) {
178  calculateYcoarse<float,short>(Y, X, Yatomic, Xatomic, uv, T, g, clover, cloverInv, kappa, mu, mu_factor, dirac, matpc, need_bidirectional);
179  } else {
180  errorQuda("Unsupported precision %d\n", T.Vectors(X.Location()).Precision());
181  }
182  } else {
183  errorQuda("Unsupported precision %d\n", Y.Precision());
184  }
185  if (getVerbosity() >= QUDA_SUMMARIZE) printfQuda("....done computing Y field\n");
186  }
187 
188 #endif // GPU_MULTIGRID
189 
190  //Calculates the coarse color matrix and puts the result in Y.
191  //N.B. Assumes Y, X have been allocated.
193  const GaugeField &gauge, const GaugeField &clover, const GaugeField &cloverInv,
194  double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc,
195  bool need_bidirectional) {
196 
197 #ifdef GPU_MULTIGRID
198  QudaPrecision precision = Y.Precision();
199  QudaFieldLocation location = checkLocation(X, Y, gauge, clover, cloverInv);
200 
201  //Create a field UV which holds U*V. Has the same similar
202  //structure to V but double the number of spins so we can store
203  //the four distinct block chiral multiplications in a single UV
204  //computation.
205  ColorSpinorParam UVparam(T.Vectors(location));
206  UVparam.create = QUDA_ZERO_FIELD_CREATE;
207  UVparam.location = location;
208  UVparam.nSpin *= 2; // so nSpin == 4
209  UVparam.setPrecision(T.Vectors(location).Precision());
210  UVparam.mem_type = Y.MemType(); // allocate temporaries to match coarse-grid link field
211 
213 
214  GaugeField *Yatomic = &Y;
215  GaugeField *Xatomic = &X;
216  if (Y.Precision() < QUDA_SINGLE_PRECISION) {
217  // we need to coarsen into single precision fields (float or int), so we allocate temporaries for this purpose
218  // else we can just coarsen directly into the original fields
219  GaugeFieldParam param(X); // use X since we want scalar geometry
220  param.location = location;
221  param.setPrecision(QUDA_SINGLE_PRECISION, location == QUDA_CUDA_FIELD_LOCATION ? true : false);
222 
223  Yatomic = GaugeField::Create(param);
224  Xatomic = GaugeField::Create(param);
225  }
226 
227  calculateYcoarse(Y, X, *Yatomic, *Xatomic, *uv, T, gauge, clover, cloverInv, kappa, mu, mu_factor, dirac, matpc, need_bidirectional);
228 
229  if (Yatomic != &Y) delete Yatomic;
230  if (Xatomic != &X) delete Xatomic;
231 
232  delete uv;
233 #else
234  errorQuda("Multigrid has not been built");
235 #endif // GPU_MULTIGRID
236  }
237 
238 } //namespace quda
double mu
Definition: test_util.cpp:1648
enum QudaPrecision_s QudaPrecision
void CoarseCoarseOp(GaugeField &Y, GaugeField &X, const Transfer &T, const GaugeField &gauge, const GaugeField &clover, const GaugeField &cloverInv, double kappa, double mu, double mu_factor, QudaDiracType dirac, QudaMatPCType matpc, bool need_bidirectional)
Coarse operator construction from an intermediate-grid operator (Coarse)
QudaVerbosity getVerbosity()
Definition: util_quda.cpp:21
double kappa
Definition: test_util.cpp:1647
#define checkPrecision(...)
#define errorQuda(...)
Definition: util_quda.h:121
enum QudaFieldOrder_s QudaFieldOrder
static ColorSpinorField * Create(const ColorSpinorParam &param)
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
static GaugeField * Create(const GaugeFieldParam &param)
Create the gauge field, with meta data specified in the parameter struct.
QudaFieldLocation location
Definition: gauge_field.h:12
enum QudaMatPCType_s QudaMatPCType
#define checkLocation(...)
enum QudaGaugeFieldOrder_s QudaGaugeFieldOrder
int X[4]
Definition: covdev_test.cpp:70
int V
Definition: test_util.cpp:27
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
#define printfQuda(...)
Definition: util_quda.h:115
double mu_factor[QUDA_MAX_MG_LEVEL]
Definition: test_util.cpp:1674
QudaPrecision Precision() const
const ColorSpinorField & Vectors(QudaFieldLocation location=QUDA_INVALID_FIELD_LOCATION) const
Definition: transfer.h:205
enum QudaDiracType_s QudaDiracType