QUDA  v0.5.0
A library for QCD on GPUs
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
color_spinor_field.cpp
Go to the documentation of this file.
1 #include <color_spinor_field.h>
2 #include <string.h>
3 #include <iostream>
4 #include <typeinfo>
5 #include <face_quda.h>
6 
7 namespace quda {
8 
9  // forward declarations
10  double normCpu(const cpuColorSpinorField &b);
11  double normCuda(const cudaColorSpinorField &b);
12 
13 
14  /*ColorSpinorField::ColorSpinorField() : init(false) {
15 
16  }*/
17 
19  field.fill(*this);
20  }
21 
23  v(0), norm(0), even(0), odd(0)
24  {
25  create(param.nDim, param.x, param.nColor, param.nSpin, param.twistFlavor, param.precision, param.pad,
26  param.siteSubset, param.siteOrder, param.fieldOrder, param.gammaBasis);
27 
28  }
29 
31  v(0), norm(0), even(0), odd(0)
32  {
33  create(field.nDim, field.x, field.nColor, field.nSpin, field.twistFlavor, field.precision, field.pad,
34  field.siteSubset, field.siteOrder, field.fieldOrder, field.gammaBasis);
35 
36  }
37 
39  destroy();
40  }
41 
43 
44  if (verbose == QUDA_DEBUG_VERBOSE)
45  printfQuda("Precision = %d, Subset = %d\n", precision, siteSubset);
46 
47  int num_faces = 1;
48  int num_norm_faces=2;
49  if (nSpin == 1) { //staggered
50  num_faces=6;
51  num_norm_faces=6;
52  }
53 
54  // calculate size of ghost zone required
55  int ghostVolume = 0;
56  //temporal hack
57  int dims = nDim == 5 ? (nDim - 1) : nDim;
58  int x5 = nDim == 5 ? x[4] : 1;
59  for (int i=0; i<dims; i++) {
60  ghostFace[i] = 0;
61  if (commDimPartitioned(i)) {
62  ghostFace[i] = 1;
63  for (int j=0; j<dims; j++) {
64  if (i==j) continue;
65  ghostFace[i] *= x[j];
66  }
67  ghostFace[i] *= x5;
68  if (i==0 && siteSubset != QUDA_FULL_SITE_SUBSET) ghostFace[i] /= 2;
70  ghostVolume += ghostFace[i];
71  }
72  if(i==0){
73  ghostOffset[i] = 0;
74  ghostNormOffset[i] = 0;
75  }else{
76  ghostOffset[i] = ghostOffset[i-1] + num_faces*ghostFace[i-1];
77  ghostNormOffset[i] = ghostNormOffset[i-1] + num_norm_faces*ghostFace[i-1];
78  }
79 
80 #ifdef MULTI_GPU
81  if (verbose == QUDA_DEBUG_VERBOSE)
82  printfQuda("face %d = %6d commDimPartitioned = %6d ghostOffset = %6d ghostNormOffset = %6d\n",
84 #endif
85  }//end of outmost for loop
86  int ghostNormVolume = num_norm_faces * ghostVolume;
87  ghostVolume *= num_faces;
88 
89  if (verbose == QUDA_DEBUG_VERBOSE)
90  printfQuda("Allocated ghost volume = %d, ghost norm volume %d\n", ghostVolume, ghostNormVolume);
91 
92  // ghost zones are calculated on c/b volumes
93 #ifdef MULTI_GPU
94  ghost_length = ghostVolume*nColor*nSpin*2;
95  ghost_norm_length = (precision == QUDA_HALF_PRECISION) ? ghostNormVolume : 0;
96 #else
97  ghost_length = 0;
99 #endif
100 
102  total_length = length + 2*ghost_length; // 2 ghost zones in a full field
103  total_norm_length = 2*(stride + ghost_norm_length); // norm length = 2*stride
104  } else {
106  total_norm_length = (precision == QUDA_HALF_PRECISION) ? stride + ghost_norm_length : 0; // norm length = stride
107  }
108 
110 
111  if (verbose == QUDA_DEBUG_VERBOSE) {
112  printfQuda("ghost length = %d, ghost norm length = %d\n", ghost_length, ghost_norm_length);
113  printfQuda("total length = %d, total norm length = %d\n", total_length, total_norm_length);
114  }
115 
116  // initialize the ghost pointers
118  for(int i=0; i<dims; ++i){
119  if(commDimPartitioned(i)){
120  ghost[i] = (char*)v + (stride + ghostOffset[i])*nColor*nSpin*2*precision;
121  if(precision == QUDA_HALF_PRECISION)
123  }
124  }
125  }
126 
127  } // createGhostZone
128 
129  void ColorSpinorField::create(int Ndim, const int *X, int Nc, int Ns, QudaTwistFlavorType Twistflavor,
130  QudaPrecision Prec, int Pad, QudaSiteSubset siteSubset,
131  QudaSiteOrder siteOrder, QudaFieldOrder fieldOrder,
132  QudaGammaBasis gammaBasis) {
133  this->siteSubset = siteSubset;
134  this->siteOrder = siteOrder;
135  this->fieldOrder = fieldOrder;
136  this->gammaBasis = gammaBasis;
137 
138  if (Ndim > QUDA_MAX_DIM){
139  errorQuda("Number of dimensions nDim = %d too great", Ndim);
140  }
141  nDim = Ndim;
142  nColor = Nc;
143  nSpin = Ns;
144  twistFlavor = Twistflavor;
145 
146  precision = Prec;
147  volume = 1;
148  for (int d=0; d<nDim; d++) {
149  x[d] = X[d];
150  volume *= x[d];
151  }
152 
153  if((twistFlavor == QUDA_TWIST_NONDEG_DOUBLET || twistFlavor == QUDA_TWIST_DEG_DOUBLET) && x[4] != 2) errorQuda("Must be two flavors for non-degenerate twisted mass spinor (while provided with %d number of components)\n", x[4]);//two flavors
154 
155  pad = Pad;
156  if (siteSubset == QUDA_FULL_SITE_SUBSET) {
157  stride = volume/2 + pad; // padding is based on half volume
158  length = 2*stride*nColor*nSpin*2;
159  } else {
160  stride = volume + pad;
162  }
163 
164  real_length = volume*nColor*nSpin*2; // physical length
165 
166  createGhostZone();
167 
168  bytes = total_length * precision; // includes pads and ghost zones
170 
171  norm_bytes = total_norm_length * sizeof(float);
172  norm_bytes = (siteSubset == QUDA_FULL_SITE_SUBSET) ? 2*ALIGNMENT_ADJUST(norm_bytes/2) : ALIGNMENT_ADJUST(norm_bytes);
173 
174  init = true;
175 
177  }
178 
179  void ColorSpinorField::destroy() {
180  init = false;
181  }
182 
184  if (&src != this) {
185  create(src.nDim, src.x, src.nColor, src.nSpin, src.twistFlavor,
186  src.precision, src.pad, src.siteSubset,
187  src.siteOrder, src.fieldOrder, src.gammaBasis);
188  }
189  return *this;
190  }
191 
192  // Resets the attributes of this field if param disagrees (and is defined)
194 
195  if (param.nColor != 0) nColor = param.nColor;
196  if (param.nSpin != 0) nSpin = param.nSpin;
198 
199  if (param.precision != QUDA_INVALID_PRECISION) precision = param.precision;
200  if (param.nDim != 0) nDim = param.nDim;
201 
202  volume = 1;
203  for (int d=0; d<nDim; d++) {
204  if (param.x[0] != 0) x[d] = param.x[d];
205  volume *= x[d];
206  }
207  if((twistFlavor == QUDA_TWIST_NONDEG_DOUBLET || twistFlavor == QUDA_TWIST_DEG_DOUBLET) && x[4] != 2) errorQuda("Must be two flavors for non-degenerate twisted mass spinor (provided with %d)\n", x[4]);
208 
209 
210  if (param.pad != 0) pad = param.pad;
211 
212  if (param.siteSubset == QUDA_FULL_SITE_SUBSET){
213  stride = volume/2 + pad;
214  length = 2*stride*nColor*nSpin*2;
215  } else if (param.siteSubset == QUDA_PARITY_SITE_SUBSET){
216  stride = volume + pad;
217  length = stride*nColor*nSpin*2;
218  } else {
219  //errorQuda("SiteSubset not defined %d", param.siteSubset);
220  //do nothing, not an error (can't remember why - need to document this sometime! )
221  }
222 
223  if (param.siteSubset != QUDA_INVALID_SITE_SUBSET) siteSubset = param.siteSubset;
224  if (param.siteOrder != QUDA_INVALID_SITE_ORDER) siteOrder = param.siteOrder;
225  if (param.fieldOrder != QUDA_INVALID_FIELD_ORDER) fieldOrder = param.fieldOrder;
226  if (param.gammaBasis != QUDA_INVALID_GAMMA_BASIS) gammaBasis = param.gammaBasis;
227 
228  createGhostZone();
229 
230  real_length = volume*nColor*nSpin*2;
231 
232  bytes = total_length * precision; // includes pads and ghost zones
234 
235  norm_bytes = total_norm_length * sizeof(float);
236  norm_bytes = (siteSubset == QUDA_FULL_SITE_SUBSET) ? 2*ALIGNMENT_ADJUST(norm_bytes/2) : ALIGNMENT_ADJUST(norm_bytes);
237 
238  if (!init) errorQuda("Shouldn't be resetting a non-inited field\n");
239 
240  if (verbose >= QUDA_DEBUG_VERBOSE) {
241  printfQuda("\nPrinting out reset field\n");
242  std::cout << *this << std::endl;
243  printfQuda("\n");
244  }
245  }
246 
247  // Fills the param with the contents of this field
249  param.nColor = nColor;
250  param.nSpin = nSpin;
251  param.twistFlavor = twistFlavor;
252  param.precision = precision;
253  param.nDim = nDim;
254  memcpy(param.x, x, QUDA_MAX_DIM*sizeof(int));
255  param.pad = pad;
256  param.siteSubset = siteSubset;
257  param.siteOrder = siteOrder;
258  param.fieldOrder = fieldOrder;
259  param.gammaBasis = gammaBasis;
261  param.verbose = verbose;
262  }
263 
264  // For kernels with precision conversion built in
266  if (a.Length() != b.Length()) {
267  errorQuda("checkSpinor: lengths do not match: %d %d", a.Length(), b.Length());
268  }
269 
270  if (a.Ncolor() != b.Ncolor()) {
271  errorQuda("checkSpinor: colors do not match: %d %d", a.Ncolor(), b.Ncolor());
272  }
273 
274  if (a.Nspin() != b.Nspin()) {
275  errorQuda("checkSpinor: spins do not match: %d %d", a.Nspin(), b.Nspin());
276  }
277 
278  if (a.TwistFlavor() != b.TwistFlavor()) {
279  errorQuda("checkSpinor: twist flavors do not match: %d %d", a.TwistFlavor(), b.TwistFlavor());
280  }
281  }
282 
283  // Set the ghost pointers to NULL.
284  // This is a private initialisation routine.
286  {
287  for(int dim=0; dim<QUDA_MAX_DIM; ++dim){
288  ghost[dim] = NULL;
289  ghostNorm[dim] = NULL;
290  }
291  }
292 
293 
294  void* ColorSpinorField::Ghost(const int i) {
295  if(siteSubset != QUDA_PARITY_SITE_SUBSET) errorQuda("Site Subset %d is not supported",siteSubset);
296  return ghost[i];
297  }
298 
299  const void* ColorSpinorField::Ghost(const int i) const {
300  if(siteSubset != QUDA_PARITY_SITE_SUBSET) errorQuda("Site Subset %d is not supported",siteSubset);
301  return ghost[i];
302  }
303 
304 
305  void* ColorSpinorField::GhostNorm(const int i){
306  if(siteSubset != QUDA_PARITY_SITE_SUBSET) errorQuda("Site Subset %d is not supported",siteSubset);
307  return ghostNorm[i];
308  }
309 
310  const void* ColorSpinorField::GhostNorm(const int i) const{
311  if(siteSubset != QUDA_PARITY_SITE_SUBSET) errorQuda("Site Subset %d is not supported",siteSubset);
312  return ghostNorm[i];
313  }
314 
315  double norm2(const ColorSpinorField &a) {
316 
317  double rtn = 0.0;
318  if (typeid(a) == typeid(cudaColorSpinorField)) {
319  rtn = normCuda(dynamic_cast<const cudaColorSpinorField&>(a));
320  } else if (typeid(a) == typeid(cpuColorSpinorField)) {
321  rtn = normCpu(dynamic_cast<const cpuColorSpinorField&>(a));
322  } else {
323  errorQuda("Unknown input ColorSpinorField %s", typeid(a).name());
324  }
325 
326  return rtn;
327  }
328 
329  std::ostream& operator<<(std::ostream &out, const ColorSpinorField &a) {
330  out << "typdid = " << typeid(a).name() << std::endl;
331  out << "nColor = " << a.nColor << std::endl;
332  out << "nSpin = " << a.nSpin << std::endl;
333  out << "twistFlavor = " << a.twistFlavor << std::endl;
334  out << "nDim = " << a.nDim << std::endl;
335  for (int d=0; d<a.nDim; d++) out << "x[" << d << "] = " << a.x[d] << std::endl;
336  out << "volume = " << a.volume << std::endl;
337  out << "precision = " << a.precision << std::endl;
338  out << "pad = " << a.pad << std::endl;
339  out << "stride = " << a.stride << std::endl;
340  out << "real_length = " << a.real_length << std::endl;
341  out << "length = " << a.length << std::endl;
342  out << "ghost_length = " << a.ghost_length << std::endl;
343  out << "total_length = " << a.total_length << std::endl;
344  out << "ghost_norm_length = " << a.ghost_norm_length << std::endl;
345  out << "total_norm_length = " << a.total_norm_length << std::endl;
346  out << "bytes = " << a.bytes << std::endl;
347  out << "norm_bytes = " << a.norm_bytes << std::endl;
348  out << "siteSubset = " << a.siteSubset << std::endl;
349  out << "siteOrder = " << a.siteOrder << std::endl;
350  out << "fieldOrder = " << a.fieldOrder << std::endl;
351  out << "gammaBasis = " << a.gammaBasis << std::endl;
352  return out;
353  }
354 
355 } // namespace quda