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