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