QUDA  v1.1.0
A library for QCD on GPUs
vector_io.cpp
Go to the documentation of this file.
1 #include <color_spinor_field.h>
2 #include <qio_field.h>
3 #include <vector_io.h>
4 #include <blas_quda.h>
5 
6 namespace quda
7 {
8 
9  VectorIO::VectorIO(const std::string &filename, bool parity_inflate) :
10 #ifdef HAVE_QIO
11  filename(filename),
12  parity_inflate(parity_inflate)
13 #else
14  filename(filename)
15 #endif
16  {
17  if (strcmp(filename.c_str(), "") == 0) { errorQuda("No eigenspace input file defined."); }
18  }
19 
20  void VectorIO::load(std::vector<ColorSpinorField *> &vecs)
21  {
22 #ifdef HAVE_QIO
23  const int Nvec = vecs.size();
24  auto spinor_parity = vecs[0]->SuggestedParity();
25  if (getVerbosity() >= QUDA_SUMMARIZE) printfQuda("Start loading %04d vectors from %s\n", Nvec, filename.c_str());
26 
27  std::vector<ColorSpinorField *> tmp;
28  tmp.reserve(Nvec);
29  if (vecs[0]->Location() == QUDA_CUDA_FIELD_LOCATION) {
30  ColorSpinorParam csParam(*vecs[0]);
32  csParam.setPrecision(vecs[0]->Precision() < QUDA_SINGLE_PRECISION ? QUDA_SINGLE_PRECISION : vecs[0]->Precision());
35  if (csParam.siteSubset == QUDA_PARITY_SITE_SUBSET && parity_inflate) {
36  csParam.x[0] *= 2;
37  csParam.siteSubset = QUDA_FULL_SITE_SUBSET;
38  }
39  for (int i = 0; i < Nvec; i++) { tmp.push_back(ColorSpinorField::Create(csParam)); }
40  } else {
41  ColorSpinorParam csParam(*vecs[0]);
42  if (csParam.siteSubset == QUDA_PARITY_SITE_SUBSET && parity_inflate) {
43  csParam.x[0] *= 2;
44  csParam.siteSubset = QUDA_FULL_SITE_SUBSET;
45  for (int i = 0; i < Nvec; i++) { tmp.push_back(ColorSpinorField::Create(csParam)); }
46  } else {
47  for (int i = 0; i < Nvec; i++) { tmp.push_back(vecs[i]); }
48  }
49  }
50 
51  if (vecs[0]->Ndim() == 4 || vecs[0]->Ndim() == 5) {
52  // since QIO routines presently assume we have 4-d fields, we need to convert to array of 4-d fields
53  auto Ls = vecs[0]->Ndim() == 5 ? tmp[0]->X(4) : 1;
54  auto V4 = tmp[0]->Volume() / Ls;
55  auto stride = V4 * tmp[0]->Ncolor() * tmp[0]->Nspin() * 2 * tmp[0]->Precision();
56  void **V = static_cast<void **>(safe_malloc(Nvec * Ls * sizeof(void *)));
57  for (int i = 0; i < Nvec; i++) {
58  for (int j = 0; j < Ls; j++) { V[i * Ls + j] = static_cast<char *>(tmp[i]->V()) + j * stride; }
59  }
60 
61  read_spinor_field(filename.c_str(), &V[0], tmp[0]->Precision(), tmp[0]->X(), tmp[0]->SiteSubset(), spinor_parity,
62  tmp[0]->Ncolor(), tmp[0]->Nspin(), Nvec * Ls, 0, (char **)0);
63 
64  host_free(V);
65  } else {
66  errorQuda("Unexpected field dimension %d", vecs[0]->Ndim());
67  }
68 
69  if (vecs[0]->Location() == QUDA_CUDA_FIELD_LOCATION) {
70 
71  ColorSpinorParam csParam(*vecs[0]);
72  if (csParam.siteSubset == QUDA_FULL_SITE_SUBSET || !parity_inflate) {
73  for (int i = 0; i < Nvec; i++) {
74  *vecs[i] = *tmp[i];
75  delete tmp[i];
76  }
77  } else {
78  // Create a temporary single-parity CPU field
80  csParam.setPrecision(vecs[0]->Precision() < QUDA_SINGLE_PRECISION ? QUDA_SINGLE_PRECISION : vecs[0]->Precision());
83 
85 
86  for (int i = 0; i < Nvec; i++) {
87  if (spinor_parity == QUDA_EVEN_PARITY)
88  blas::copy(*tmp_intermediate, tmp[i]->Even());
89  else if (spinor_parity == QUDA_ODD_PARITY)
90  blas::copy(*tmp_intermediate, tmp[i]->Odd());
91  else
92  errorQuda("When loading single parity vectors, the suggested parity must be set.");
93 
94  *vecs[i] = *tmp_intermediate;
95  delete tmp[i];
96  }
97 
98  delete tmp_intermediate;
99  }
100  } else if (vecs[0]->Location() == QUDA_CPU_FIELD_LOCATION && vecs[0]->SiteSubset() == QUDA_PARITY_SITE_SUBSET) {
101  for (int i = 0; i < Nvec; i++) {
102  if (spinor_parity == QUDA_EVEN_PARITY)
103  blas::copy(*vecs[i], tmp[i]->Even());
104  else if (spinor_parity == QUDA_ODD_PARITY)
105  blas::copy(*vecs[i], tmp[i]->Odd());
106  else
107  errorQuda("When loading single parity vectors, the suggested parity must be set.");
108 
109  delete tmp[i];
110  }
111  }
112 
113  if (getVerbosity() >= QUDA_SUMMARIZE) printfQuda("Done loading vectors\n");
114 #else
115  errorQuda("\nQIO library was not built.\n");
116 #endif
117  }
118 
119  void VectorIO::save(const std::vector<ColorSpinorField *> &vecs)
120  {
121 #ifdef HAVE_QIO
122  const int Nvec = vecs.size();
123  std::vector<ColorSpinorField *> tmp;
124  tmp.reserve(Nvec);
125  auto spinor_parity = vecs[0]->SuggestedParity();
126  if (vecs[0]->Location() == QUDA_CUDA_FIELD_LOCATION) {
127  ColorSpinorParam csParam(*vecs[0]);
129  csParam.setPrecision(vecs[0]->Precision() < QUDA_SINGLE_PRECISION ? QUDA_SINGLE_PRECISION : vecs[0]->Precision());
130  csParam.location = QUDA_CPU_FIELD_LOCATION;
131 
132  if (csParam.siteSubset == QUDA_FULL_SITE_SUBSET || !parity_inflate) {
133  // We're good, copy as is.
135  for (int i = 0; i < Nvec; i++) {
137  *tmp[i] = *vecs[i];
138  }
139  } else { // QUDA_PARITY_SITE_SUBSET
141 
142  // intermediate host single-parity field
144 
145  csParam.x[0] *= 2; // corrects for the factor of two in the X direction
146  csParam.siteSubset = QUDA_FULL_SITE_SUBSET; // create a full-parity field.
147  csParam.create = QUDA_ZERO_FIELD_CREATE; // to explicitly zero the odd sites.
148  for (int i = 0; i < Nvec; i++) {
150 
151  // copy the single parity eigen/singular vector into an
152  // intermediate device-side vector
153  *tmp_intermediate = *vecs[i];
154 
155  // copy the single parity only eigen/singular vector into the even components of the full parity vector
156  if (spinor_parity == QUDA_EVEN_PARITY)
157  blas::copy(tmp[i]->Even(), *tmp_intermediate);
158  else if (spinor_parity == QUDA_ODD_PARITY)
159  blas::copy(tmp[i]->Odd(), *tmp_intermediate);
160  else
161  errorQuda("When saving single parity vectors, the suggested parity must be set.");
162  }
163  delete tmp_intermediate;
164  }
165  } else {
166  ColorSpinorParam csParam(*vecs[0]);
167  if (csParam.siteSubset == QUDA_PARITY_SITE_SUBSET && parity_inflate) {
168  csParam.x[0] *= 2;
169  csParam.siteSubset = QUDA_FULL_SITE_SUBSET;
171  for (int i = 0; i < Nvec; i++) {
173  if (spinor_parity == QUDA_EVEN_PARITY)
174  blas::copy(tmp[i]->Even(), *vecs[i]);
175  else if (spinor_parity == QUDA_ODD_PARITY)
176  blas::copy(tmp[i]->Odd(), *vecs[i]);
177  else
178  errorQuda("When saving single parity vectors, the suggested parity must be set.");
179  }
180  } else {
181  for (int i = 0; i < Nvec; i++) { tmp.push_back(vecs[i]); }
182  }
183  }
184 
185  if (getVerbosity() >= QUDA_SUMMARIZE) printfQuda("Start saving %d vectors to %s\n", Nvec, filename.c_str());
186 
187  if (vecs[0]->Ndim() == 4 || vecs[0]->Ndim() == 5) {
188  // since QIO routines presently assume we have 4-d fields, we need to convert to array of 4-d fields
189  auto Ls = vecs[0]->Ndim() == 5 ? tmp[0]->X(4) : 1;
190  auto V4 = tmp[0]->Volume() / Ls;
191  auto stride = V4 * tmp[0]->Ncolor() * tmp[0]->Nspin() * 2 * tmp[0]->Precision();
192  void **V = static_cast<void **>(safe_malloc(Nvec * Ls * sizeof(void *)));
193  for (int i = 0; i < Nvec; i++) {
194  for (int j = 0; j < Ls; j++) { V[i * Ls + j] = static_cast<char *>(tmp[i]->V()) + j * stride; }
195  }
196 
197  write_spinor_field(filename.c_str(), &V[0], tmp[0]->Precision(), tmp[0]->X(), tmp[0]->SiteSubset(), spinor_parity,
198  tmp[0]->Ncolor(), tmp[0]->Nspin(), Nvec * Ls, 0, (char **)0);
199 
200  host_free(V);
201  } else {
202  errorQuda("Unexpected field dimension %d", vecs[0]->Ndim());
203  }
204 
205  if (getVerbosity() >= QUDA_SUMMARIZE) printfQuda("Done saving vectors\n");
206  if (vecs[0]->Location() == QUDA_CUDA_FIELD_LOCATION
207  || (vecs[0]->Location() == QUDA_CPU_FIELD_LOCATION && vecs[0]->SiteSubset() == QUDA_PARITY_SITE_SUBSET)) {
208  for (int i = 0; i < Nvec; i++) delete tmp[i];
209  }
210 #else
211  errorQuda("\nQIO library was not built.\n");
212 #endif
213  }
214 
215 } // namespace quda
static ColorSpinorField * Create(const ColorSpinorParam &param)
void load(std::vector< ColorSpinorField * > &vecs)
Load vectors from filename.
Definition: vector_io.cpp:20
void save(const std::vector< ColorSpinorField * > &vecs)
Save vectors to filename.
Definition: vector_io.cpp:119
VectorIO(const std::string &filename, bool parity_inflate=false)
Definition: vector_io.cpp:9
int V
Definition: host_utils.cpp:37
cudaColorSpinorField * tmp
Definition: covdev_test.cpp:34
@ QUDA_CUDA_FIELD_LOCATION
Definition: enum_quda.h:326
@ QUDA_CPU_FIELD_LOCATION
Definition: enum_quda.h:325
@ QUDA_SUMMARIZE
Definition: enum_quda.h:266
@ QUDA_FULL_SITE_SUBSET
Definition: enum_quda.h:333
@ QUDA_PARITY_SITE_SUBSET
Definition: enum_quda.h:332
@ QUDA_EVEN_PARITY
Definition: enum_quda.h:284
@ QUDA_ODD_PARITY
Definition: enum_quda.h:284
@ QUDA_SINGLE_PRECISION
Definition: enum_quda.h:64
@ QUDA_SPACE_SPIN_COLOR_FIELD_ORDER
Definition: enum_quda.h:351
@ QUDA_ZERO_FIELD_CREATE
Definition: enum_quda.h:361
@ QUDA_NULL_FIELD_CREATE
Definition: enum_quda.h:360
int Ls
Definition: host_utils.cpp:48
#define safe_malloc(size)
Definition: malloc_quda.h:106
#define host_free(ptr)
Definition: malloc_quda.h:115
void copy(ColorSpinorField &dst, const ColorSpinorField &src)
Definition: blas_quda.h:24
::std::string string
Definition: gtest-port.h:891
ColorSpinorParam csParam
Definition: pack_test.cpp:25
void read_spinor_field(const char *filename, void *V[], QudaPrecision precision, const int *X, QudaSiteSubset subset, QudaParity parity, int nColor, int nSpin, int Nvec, int argc, char *argv[])
Definition: qio_field.h:24
void write_spinor_field(const char *filename, void *V[], QudaPrecision precision, const int *X, QudaSiteSubset subset, QudaParity parity, int nColor, int nSpin, int Nvec, int argc, char *argv[])
Definition: qio_field.h:31
#define printfQuda(...)
Definition: util_quda.h:114
QudaVerbosity getVerbosity()
Definition: util_quda.cpp:21
#define errorQuda(...)
Definition: util_quda.h:120