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