OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
H5PartWrapper.cpp
Go to the documentation of this file.
1 //
2 // Copyright & License: See Copyright.readme in src directory
3 //
4 
6 
7 #include "OPALconfig.h"
9 #include "Utilities/Options.h"
10 #include "Physics/Physics.h"
11 
12 #include <boost/filesystem.hpp>
13 
14 #include <fstream>
15 
16 namespace {
17  const h5_int64_t H5TypesCHAR = H5_STRING_T;
18  const h5_int64_t H5TypesFLOAT = H5_FLOAT32_T;
19  const h5_int64_t H5TypesDOUBLE = H5_FLOAT64_T;
20  const h5_int64_t H5TypesINT32 = H5_INT32_T;
21  const h5_int64_t H5TypesINT64 = H5_INT64_T;
22 }
23 
24 std::string H5PartWrapper::copyFilePrefix_m = ".copy";
25 
26 H5PartWrapper::H5PartWrapper(const std::string &fileName, h5_int32_t flags):
27  file_m(0),
28  fileName_m(fileName),
29  predecessorOPALFlavour_m("NOT SET"),
30  numSteps_m(0),
31  startedFromExistingFile_m(false)
32 {
33  open(flags);
34 }
35 
36 H5PartWrapper::H5PartWrapper(const std::string &fileName, int restartStep, std::string sourceFile, h5_int32_t flags):
37  file_m(0),
38  fileName_m(fileName),
39  predecessorOPALFlavour_m("NOT SET"),
40  numSteps_m(0),
41  startedFromExistingFile_m(true)
42 {
43  namespace fs = boost::filesystem;
44 
45  if (sourceFile == "") sourceFile = fileName_m;
46 
47  copyFile(sourceFile, restartStep, flags);
48 
49  open(H5_O_RDWR);
50 }
51 
53  close();
54 }
55 
57  if (file_m) {
59 
60  REPORTONERROR(H5CloseFile(file_m));
61 
62  file_m = 0;
63  }
64 }
65 
66 void H5PartWrapper::open(h5_int32_t flags) {
67  close();
68 
69  h5_prop_t props = H5CreateFileProp ();
70  MPI_Comm comm = Ippl::getComm();
71  h5_err_t h5err = H5SetPropFileMPIOCollective (props, &comm);
72 #if defined (NDEBUG)
73  (void)h5err;
74 #endif
75  assert (h5err != H5_ERR);
76  file_m = H5OpenFile (fileName_m.c_str(), flags, props);
77  assert (file_m != (h5_file_t)H5_ERR);
78  H5CloseProp (props);
79 }
80 
83  h5_int64_t nAutoPhaseCavities = OpalData::getInstance()->getNumberOfMaxPhases();
84  h5_int64_t nFormerlySavedAutoPhaseCavities = 0;
85  bool fileWasClosed = (file_m == 0);
86 
87  if (nAutoPhaseCavities == 0) return;
88  if (fileWasClosed) open(H5_O_APPENDONLY);
89  if (!H5HasFileAttrib(file_m, "nAutoPhaseCavities") ||
90  H5ReadFileAttribInt64(file_m, "nAutoPhaseCavities", &nFormerlySavedAutoPhaseCavities) != H5_SUCCESS) {
91  nFormerlySavedAutoPhaseCavities = 0;
92  }
93  if (nFormerlySavedAutoPhaseCavities == nAutoPhaseCavities) {
94  if (fileWasClosed) close();
95  return;
96  }
97 
98  WRITEFILEATTRIB(Int64, file_m, "nAutoPhaseCavities", &nAutoPhaseCavities, 1);
99 
100  unsigned int elementNumber = 1;
103  for(; it < end; ++ it, ++ elementNumber) {
104  if (elementNumber <= nFormerlySavedAutoPhaseCavities) continue;
105 
106  std::string nameAttributeName = "Cav-" + std::to_string(elementNumber) + "-name";
107  std::string valueAttributeName = "Cav-" + std::to_string(elementNumber) + "-value";
108 
109  std::string elementName = (*it).first;
110  h5_float64_t elementPhase = (*it).second;
111 
112  WRITESTRINGFILEATTRIB(file_m, nameAttributeName.c_str(), elementName.c_str());
113  WRITEFILEATTRIB(Float64, file_m, valueAttributeName.c_str(), &elementPhase, 1);
114 
115  INFOMSG("Saved phases in the h5 file: "
116  << nameAttributeName << " -> " << elementName << " --- "
117  << valueAttributeName << " -> " << elementPhase << endl);
118  }
119 
120  if (fileWasClosed) close();
121 }
122 
123 void H5PartWrapper::copyFile(const std::string &sourceFile, int lastStep, h5_int32_t flags) {
124 
125  namespace fs = boost::filesystem;
126  if (!fs::exists(sourceFile)) {
127  throw OpalException("H5PartWrapper::copyFile",
128  "source file '" + sourceFile + "' does not exist");
129  }
130 
131  if (sourceFile == fileName_m) {
132  h5_prop_t props = H5CreateFileProp ();
133  MPI_Comm comm = Ippl::getComm();
134  h5_err_t h5err = H5SetPropFileMPIOCollective (props, &comm);
135 #if defined (NDEBUG)
136  (void)h5err;
137 #endif
138  assert (h5err != H5_ERR);
139  h5_file_t source = H5OpenFile (sourceFile.c_str(), H5_O_RDONLY, props);
140  assert (source != (h5_file_t)H5_ERR);
141  H5CloseProp (props);
142  h5_ssize_t numStepsInSource = H5GetNumSteps(source);
143 
144  if (lastStep == -1 || lastStep >= numStepsInSource) {
145  REPORTONERROR(H5SetStep(source, numStepsInSource - 1));
146 
147  char opalFlavour[128];
148  READSTEPATTRIB(String, source, "OPAL_flavour", opalFlavour);
149  predecessorOPALFlavour_m = std::string(opalFlavour);
150 
151  REPORTONERROR(H5CloseFile(source));
152 
153  numSteps_m = numStepsInSource;
154  return;
155  }
156 
157  REPORTONERROR(H5CloseFile(source));
158 
159  Ippl::Comm->barrier();
160 
161  std::string sourceFileName = copyFilePrefix_m + fileName_m;
162  if (Ippl::myNode() == 0) {
163  fs::rename(fileName_m, sourceFileName);
164  }
165 
166  Ippl::Comm->barrier();
167 
168  open(flags);
169  props = H5CreateFileProp ();
170  comm = Ippl::getComm();
171  h5err = H5SetPropFileMPIOCollective (props, &comm);
172  assert (h5err != H5_ERR);
173  source = H5OpenFile (sourceFileName.c_str(), H5_O_RDONLY, props);
174  assert (source != (h5_file_t)H5_ERR);
175  H5CloseProp (props);
176  copyHeader(source);
177 
178  if (lastStep < 0) {
179  if (-lastStep > numStepsInSource) {
180  lastStep = 0;
181  } else {
182  lastStep = numStepsInSource + lastStep;
183  }
184  }
185 
186  // don't copy the whole file, it takes very long
187  copyStep(source, lastStep);
188  ++ numSteps_m;
189 
190  REPORTONERROR(H5CloseFile(source));
191 
192  if (Ippl::myNode() == 0) {
193  fs::remove(sourceFileName);
194  }
195 
196  close();
197  } else {
198 
199  open(flags);
200 
201  h5_prop_t props = H5CreateFileProp ();
202  MPI_Comm comm = Ippl::getComm();
203  h5_err_t h5err = H5SetPropFileMPIOCollective (props, &comm);
204 #if defined (NDEBUG)
205  (void)h5err;
206 #endif
207  assert (h5err != H5_ERR);
208  h5_file_t source = H5OpenFile (sourceFile.c_str(), H5_O_RDONLY, props);
209  assert (source != (h5_file_t)H5_ERR);
210  H5CloseProp (props);
211  h5_ssize_t numStepsInSource = H5GetNumSteps(source);
212 
213  if (lastStep == -1 || lastStep >= numStepsInSource) {
214  REPORTONERROR(H5SetStep(source, numStepsInSource - 1));
215 
216  char opalFlavour[128];
217  READSTEPATTRIB(String, source, "OPAL_flavour", opalFlavour);
218  predecessorOPALFlavour_m = std::string(opalFlavour);
219 
220  REPORTONERROR(H5CloseFile(source));
221  close();
222 
223  copyFileSystem(sourceFile);
224 
225  numSteps_m = numStepsInSource;
226 
227  } else {
228  copyHeader(source);
229 
230  if (lastStep < 0) {
231  if (-lastStep > numStepsInSource) {
232  lastStep = 0;
233  } else {
234  lastStep = numStepsInSource + lastStep;
235  }
236  }
237  // don't copy the whole file, it takes very long
238  copyStep(source, lastStep);
239  ++ numSteps_m;
240 
241  REPORTONERROR(H5CloseFile(source));
242  }
243 
244  close();
245  }
246 }
247 
248 void H5PartWrapper::copyFileSystem(const std::string &sourceFile) {
249  // namespace fs = boost::filesystem;
250 
251  if (sourceFile == fileName_m) return;
252 
253  int sourceNode = 0;
254  if (Ippl::myNode() == sourceNode) {
255 
256  // copy_file not working due to bug in boost, see
257  // https://svn.boost.org/trac/boost/ticket/10038
258  // try {
259  // fs::copy_file(sourceFile, fileName_m, fs::copy_option::none);
260  // } catch (fs::filesystem_error &m) {
261 
262  // ERRORMSG(m.what() << endl);
263 
264  std::ifstream source(sourceFile, std::ios::binary);
265  std::ofstream dest(fileName_m, std::ios::binary);
266 
267  std::istreambuf_iterator<char> begin_source(source);
268  std::istreambuf_iterator<char> end_source;
269  std::ostreambuf_iterator<char> begin_dest(dest);
270  std::copy(begin_source, end_source, begin_dest);
271 
272  source.close();
273 
274  sendFailureMessage(dest.bad(),
275  "H5PartWrapper::copyFile",
276  "could not copy file " + sourceFile);
277  dest.close();
278  } else {
279  receiveFailureMessage(sourceNode,
280  "H5PartWrapper::copyFile",
281  "received message to throw exception from node 0");
282  }
283 }
284 
286  h5_file_t source
287  ) {
288  h5_int64_t numFileAttributes = H5GetNumFileAttribs(source);
289 
290  const h5_size_t lengthAttributeName = 256;
291  char attributeName[lengthAttributeName];
292  h5_int64_t attributeType;
293  h5_size_t numAttributeElements;
294  std::vector<char> buffer(256);
295  h5_float32_t *f32buffer = reinterpret_cast<h5_float32_t*>(&buffer[0]);
296  h5_float64_t *f64buffer = reinterpret_cast<h5_float64_t*>(&buffer[0]);
297  h5_int32_t *i32buffer = reinterpret_cast<h5_int32_t*>(&buffer[0]);
298  h5_int64_t *i64buffer = reinterpret_cast<h5_int64_t*>(&buffer[0]);
299 
300  for (h5_int64_t i = 0; i < numFileAttributes; ++ i) {
301  REPORTONERROR(H5GetFileAttribInfo(source,
302  i,
303  attributeName,
304  lengthAttributeName,
305  &attributeType,
306  &numAttributeElements));
307 
308  if (attributeType == H5_STRING_T) {
309  if (buffer.size() < numAttributeElements) {
310  buffer.resize(numAttributeElements);
311  }
312 
313  READFILEATTRIB(String, source, attributeName, &buffer[0]);
314  WRITESTRINGFILEATTRIB(file_m, attributeName, &buffer[0]);
315 
316  } else if (attributeType == H5_FLOAT32_T) {
317  if (buffer.size() < numAttributeElements * sizeof(h5_float32_t)) {
318  buffer.resize(numAttributeElements * sizeof(h5_float32_t));
319  }
320 
321  READFILEATTRIB(Float32, source, attributeName, f32buffer);
322  WRITEFILEATTRIB(Float32, file_m, attributeName, f32buffer, numAttributeElements);
323 
324  } else if (attributeType == H5_FLOAT64_T) {
325  if (buffer.size() < numAttributeElements * sizeof(h5_float64_t)) {
326  buffer.resize(numAttributeElements * sizeof(h5_float64_t));
327  }
328 
329  READFILEATTRIB(Float64, source, attributeName, f64buffer);
330  WRITEFILEATTRIB(Float64, file_m, attributeName, f64buffer, numAttributeElements);
331 
332  } else if (attributeType == H5_INT32_T) {
333  if (buffer.size() < numAttributeElements * sizeof(h5_int32_t)) {
334  buffer.resize(numAttributeElements * sizeof(h5_int32_t));
335  }
336 
337  READFILEATTRIB(Int32, source, attributeName, i32buffer);
338  WRITEFILEATTRIB(Int32, file_m, attributeName, i32buffer, numAttributeElements);
339 
340  } else if (attributeType == H5_INT64_T) {
341  if (buffer.size() < numAttributeElements * sizeof(h5_int64_t)) {
342  buffer.resize(numAttributeElements * sizeof(h5_int64_t));
343  }
344 
345  READFILEATTRIB(Int64, source, attributeName, i64buffer);
346  WRITEFILEATTRIB(Int64, file_m, attributeName, i64buffer, numAttributeElements);
347 
348  } else {
349  throw OpalException("H5PartWrapper::copyHeader",
350  "unknown data type: " + std::to_string(attributeType));
351  }
352  }
353 }
354 
356  h5_file_t source,
357  int step
358  ) {
359  REPORTONERROR(H5SetStep(file_m, numSteps_m));
360  REPORTONERROR(H5SetStep(source, step));
361 
362  copyStepHeader(source);
363  copyStepData(source);
364 }
365 
367  h5_file_t source
368  ) {
369  h5_int64_t numStepAttributes = H5GetNumStepAttribs(source);
370 
371  h5_size_t lengthAttributeName = 256;
372  char attributeName[lengthAttributeName];
373  h5_int64_t attributeType;
374  h5_size_t numAttributeElements;
375 
376  std::vector<char> buffer(256);
377  h5_float32_t *f32buffer = reinterpret_cast<h5_float32_t*>(&buffer[0]);
378  h5_float64_t *f64buffer = reinterpret_cast<h5_float64_t*>(&buffer[0]);
379  h5_int32_t *i32buffer = reinterpret_cast<h5_int32_t*>(&buffer[0]);
380  h5_int64_t *i64buffer = reinterpret_cast<h5_int64_t*>(&buffer[0]);
381 
382  READSTEPATTRIB(String, source, "OPAL_flavour", &buffer[0]);
383  predecessorOPALFlavour_m = std::string(&buffer[0]);
384 
385  for (h5_int64_t i = 0; i < numStepAttributes; ++ i) {
386  REPORTONERROR(H5GetStepAttribInfo(source,
387  i,
388  attributeName,
389  lengthAttributeName,
390  &attributeType,
391  &numAttributeElements));
392 
393  if (attributeType == H5TypesCHAR) {
394  if (buffer.size() < numAttributeElements) {
395  buffer.resize(numAttributeElements);
396  }
397 
398  READSTEPATTRIB(String, source, attributeName, &buffer[0]);
399  WRITESTRINGSTEPATTRIB(file_m, attributeName, &buffer[0]);
400 
401  } else if (attributeType == H5TypesFLOAT) {
402  if (buffer.size() < numAttributeElements * sizeof(h5_float32_t)) {
403  buffer.resize(numAttributeElements * sizeof(h5_float32_t));
404  }
405 
406  READSTEPATTRIB(Float32, source, attributeName, f32buffer);
407  WRITESTEPATTRIB(Float32, file_m, attributeName, f32buffer, numAttributeElements);
408 
409  } else if (attributeType == H5TypesDOUBLE) {
410  if (buffer.size() < numAttributeElements * sizeof(h5_float64_t)) {
411  buffer.resize(numAttributeElements * sizeof(h5_float64_t));
412  }
413 
414  READSTEPATTRIB(Float64, source, attributeName, f64buffer);
415  WRITESTEPATTRIB(Float64, file_m, attributeName, f64buffer, numAttributeElements);
416 
417  } else if (attributeType == H5TypesINT32) {
418  if (buffer.size() < numAttributeElements * sizeof(h5_int32_t)) {
419  buffer.resize(numAttributeElements * sizeof(h5_int32_t));
420  }
421 
422  READSTEPATTRIB(Int32, source, attributeName, i32buffer);
423  WRITESTEPATTRIB(Int32, file_m, attributeName, i32buffer, numAttributeElements);
424 
425  } else if (attributeType == H5TypesINT64) {
426  if (buffer.size() < numAttributeElements * sizeof(h5_int64_t)) {
427  buffer.resize(numAttributeElements * sizeof(h5_int64_t));
428  }
429 
430  READSTEPATTRIB(Int64, source, attributeName, i64buffer);
431  WRITESTEPATTRIB(Int64, file_m, attributeName, i64buffer, numAttributeElements);
432 
433  } else {
434  throw OpalException("H5PartWrapper::copyStepHeader",
435  "unknown data type: " + std::to_string(attributeType));
436  }
437  }
438 }
439 
441  h5_file_t source
442  ) {
443  h5_size_t lengthSetName = 256;
444  char setName[lengthSetName];
445  h5_int64_t setType;
446  h5_size_t numSetElements;
447 
448  h5_ssize_t numParticles = H5PartGetNumParticles(source);
449  h5_ssize_t numParticlesPerNode = numParticles / Ippl::getNodes();
450 
451  h5_ssize_t firstParticle = numParticlesPerNode * Ippl::myNode();
452  h5_ssize_t lastParticle = firstParticle + numParticlesPerNode - 1;
453  if (Ippl::myNode() == Ippl::getNodes() - 1)
454  lastParticle = numParticles - 1;
455 
456  REPORTONERROR(H5PartSetView(source, firstParticle, lastParticle));
457 
458  numParticles = lastParticle - firstParticle + 1;
459  REPORTONERROR(H5PartSetNumParticles(file_m, numParticles));
460 
461  std::vector<char> buffer(numParticles * sizeof(h5_float64_t));
462  h5_float32_t *f32buffer = reinterpret_cast<h5_float32_t*>(&buffer[0]);
463  h5_float64_t *f64buffer = reinterpret_cast<h5_float64_t*>(&buffer[0]);
464  h5_int32_t *i32buffer = reinterpret_cast<h5_int32_t*>(&buffer[0]);
465  h5_int64_t *i64buffer = reinterpret_cast<h5_int64_t*>(&buffer[0]);
466 
467  h5_ssize_t numDatasets = H5PartGetNumDatasets(source);
468 
469  for (h5_ssize_t i = 0; i < numDatasets; ++ i) {
470  REPORTONERROR(H5PartGetDatasetInfo(source, i, setName, lengthSetName, &setType, &numSetElements));
471 
472  if (setType == H5TypesFLOAT) {
473  READDATA(Float32, source, setName, f32buffer);
474  WRITEDATA(Float32, file_m, setName, f32buffer);
475  } else if (setType == H5TypesDOUBLE) {
476  READDATA(Float64, source, setName, f64buffer);
477  WRITEDATA(Float64, file_m, setName, f64buffer);
478  } else if (setType == H5TypesINT32) {
479  READDATA(Int32, source, setName, i32buffer);
480  WRITEDATA(Int32, file_m, setName, i32buffer);
481  } else if (setType == H5TypesINT64) {
482  READDATA(Int64, source, setName, i64buffer);
483  WRITEDATA(Int64, file_m, setName, i64buffer);
484  } else {
485  throw OpalException("H5PartWrapper::copyStepData",
486  "unknown data type: " + std::to_string(setType));
487  }
488  }
489 
490  numParticles = H5PartGetNumParticles(file_m);
491  REPORTONERROR(H5PartSetView(source, -1, -1));
492 }
493 
495  const std::string &where,
496  const std::string &what) {
497  int tag = 101;
498  Message *mess = new Message();
499  putMessage(*mess, failed);
500  Ippl::Comm->broadcast_all(mess, tag);
501  delete mess;
502 
503  if (failed) throw OpalException(where, what);
504 }
505 
507  const std::string &where,
508  const std::string &what) {
509  int tag = 101;
510  bool failed;
511  Message *mess = Ippl::Comm->receive_block(sourceNode, tag);
512  getMessage(*mess, failed);
513  delete mess;
514 
515  if (failed) throw OpalException(where, what);
516 }
517 
519  if (!file_m) {
520  throw OpalException("H5PartWrapper::getNumParticles",
521  "no file opened");
522  }
523 
524  REPORTONERROR(H5SetStep(file_m, numSteps_m - 1));
525  h5_ssize_t numParticles = H5PartGetNumParticles(file_m);
526 
527  return numParticles;
528 }
529 
530 // vi: set et ts=4 sw=4 sts=4:
531 // Local Variables:
532 // mode:c++
533 // c-basic-offset: 4
534 // indent-tabs-mode:nil
535 // End:
static int getNodes()
Definition: IpplInfo.cpp:773
std::vector< MaxPhasesT >::iterator getLastMaxPhases()
Definition: OpalData.cpp:447
void open(h5_int32_t flags)
void sendFailureMessage(bool failed, const std::string &where, const std::string &what)
The base class for all OPAL exceptions.
Definition: OpalException.h:28
void copyHeader(h5_file_t source)
void copyStep(h5_file_t source, int step)
void barrier(void)
static int myNode()
Definition: IpplInfo.cpp:794
FRONT * fs
Definition: hypervolume.cpp:59
#define WRITEDATA(type, file, name, value)
Definition: H5PartWrapper.h:28
std::string predecessorOPALFlavour_m
Definition: H5PartWrapper.h:71
#define REPORTONERROR(rc)
Definition: H5PartWrapper.h:18
#define WRITESTRINGSTEPATTRIB(file, name, value)
Definition: H5PartWrapper.h:24
h5_int64_t numSteps_m
Definition: H5PartWrapper.h:72
void copyFileSystem(const std::string &sourceFile)
static OpalData * getInstance()
Definition: OpalData.cpp:209
static std::string copyFilePrefix_m
Definition: H5PartWrapper.h:75
#define INFOMSG(msg)
Definition: IpplInfo.h:397
PETE_TTTree< OpWhere, typename Cond_t::PETE_Expr_t, typename True_t::PETE_Expr_t, PETE_Scalar< Vektor< T, Dim > > > where(const PETE_Expr< Cond_t > &c, const PETE_Expr< True_t > &t, const Vektor< T, Dim > &f)
virtual ~H5PartWrapper()
void copyStepHeader(h5_file_t source)
static MPI_Comm getComm()
Definition: IpplInfo.h:178
#define WRITESTEPATTRIB(type, file, name, value, length)
Definition: H5PartWrapper.h:25
void storeCavityInformation()
std::vector< MaxPhasesT >::iterator getFirstMaxPhases()
Definition: OpalData.cpp:443
int getNumberOfMaxPhases()
Definition: OpalData.cpp:451
#define READSTEPATTRIB(type, file, name, value)
Definition: H5PartWrapper.h:23
void getMessage(Message &m, T &t)
Definition: Message.h:580
#define WRITEFILEATTRIB(type, file, name, value, length)
Definition: H5PartWrapper.h:21
h5_file_t file_m
Definition: H5PartWrapper.h:69
#define READDATA(type, file, name, value)
Definition: H5PartWrapper.h:27
std::string::iterator iterator
Definition: MSLang.h:16
void putMessage(Message &m, const T &t)
Definition: Message.h:557
void copyFile(const std::string &sourceFile, int lastStep=-1, h5_int32_t flags=H5_O_WRONLY)
void copyStepData(h5_file_t source)
H5PartWrapper(const std::string &fileName, h5_int32_t flags=H5_O_WRONLY)
Message * receive_block(int &node, int &tag)
void receiveFailureMessage(int sourceNode, const std::string &where, const std::string &what)
std::string fileName_m
Definition: H5PartWrapper.h:70
size_t getNumParticles() const
static Communicate * Comm
Definition: IpplInfo.h:93
virtual int broadcast_all(Message *, int)
#define READFILEATTRIB(type, file, name, value)
Definition: H5PartWrapper.h:19
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
#define WRITESTRINGFILEATTRIB(file, name, value)
Definition: H5PartWrapper.h:20