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