OPALX (Object Oriented Parallel Accelerator Library for Exascal) MINIorX
OPALX
H5PartWrapper.cpp
Go to the documentation of this file.
1//
2// Copyright & License: See Copyright.readme in src directory
3//
4
6
8#include "OPALconfig.h"
9#include "Physics/Physics.h"
11#include "Utilities/Options.h"
12#include "Utilities/Util.h"
13
14#include "Utility/PAssert.h"
15
16#include <boost/filesystem.hpp>
17
18#include <fstream>
19
20namespace {
21 const h5_int64_t H5TypesCHAR = H5_STRING_T;
22 const h5_int64_t H5TypesFLOAT = H5_FLOAT32_T;
23 const h5_int64_t H5TypesDOUBLE = H5_FLOAT64_T;
24 const h5_int64_t H5TypesINT32 = H5_INT32_T;
25 const h5_int64_t H5TypesINT64 = H5_INT64_T;
26} // namespace
27
28std::string H5PartWrapper::copyFilePrefix_m = ".copy";
29
30H5PartWrapper::H5PartWrapper(const std::string& fileName, h5_int32_t flags)
31 : file_m(0),
32 fileName_m(fileName),
33 predecessorOPALFlavour_m("NOT SET"),
34 numSteps_m(0),
36 open(flags);
37}
38
40 const std::string& fileName, int restartStep, std::string sourceFile, h5_int32_t flags)
41 : file_m(0),
42 fileName_m(fileName),
43 predecessorOPALFlavour_m("NOT SET"),
44 numSteps_m(0),
46 if (sourceFile.empty()) {
47 sourceFile = fileName_m;
48 }
49
50 copyFile(sourceFile, restartStep, flags);
51
52 open(H5_O_RDWR);
53}
54
58
60 if (file_m) {
61 ippl::Comm->barrier();
62
63 REPORTONERROR(H5CloseFile(file_m));
64
65 file_m = 0;
66 }
67}
68
69void H5PartWrapper::open(h5_int32_t flags) {
70 h5_prop_t props = H5CreateFileProp();
71 MPI_Comm comm = ippl::Comm->getCommunicator();
72 h5_err_t h5err = H5SetPropFileMPIOCollective(props, &comm);
73#if defined(NDEBUG)
74 (void)h5err;
75#endif
76 PAssert(h5err != H5_ERR);
77 file_m = H5OpenFile(fileName_m.c_str(), flags, props);
78 PAssert(file_m != (h5_file_t)H5_ERR);
79 H5CloseProp(props);
80}
81
84 h5_int64_t nAutoPhaseCavities = OpalData::getInstance()->getNumberOfMaxPhases();
85 h5_int64_t nFormerlySavedAutoPhaseCavities = 0;
86 bool fileWasClosed = (file_m == 0);
87
88 if (nAutoPhaseCavities == 0)
89 return;
90 if (fileWasClosed)
91 open(H5_O_APPENDONLY);
92 if (!H5HasFileAttrib(file_m, "nAutoPhaseCavities")
93 || H5ReadFileAttribInt64(file_m, "nAutoPhaseCavities", &nFormerlySavedAutoPhaseCavities)
94 != H5_SUCCESS) {
95 nFormerlySavedAutoPhaseCavities = 0;
96 }
97 if (nFormerlySavedAutoPhaseCavities == nAutoPhaseCavities) {
98 if (fileWasClosed)
99 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)
110 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 *ippl::Info << "Saved phases in the h5 file: " << nameAttributeName << " -> " << elementName
122 << " --- " << valueAttributeName << " -> " << elementPhase << endl;
123 }
124
125 if (fileWasClosed)
126 close();
127}
128
129void H5PartWrapper::copyFile(const std::string& sourceFile, int lastStep, h5_int32_t flags) {
130 namespace fs = boost::filesystem;
131 if (!fs::exists(sourceFile)) {
132 throw OpalException(
133 "H5PartWrapper::copyFile", "source file '" + sourceFile + "' does not exist");
134 }
135
136 if (sourceFile == fileName_m) {
137 h5_prop_t props = H5CreateFileProp();
138 MPI_Comm comm = ippl::Comm->getCommunicator();
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::Comm->rank() == 0) {
168 fs::rename(fileName_m, sourceFileName);
169 }
170
171 ippl::Comm->barrier();
172
173 open(flags);
174 props = H5CreateFileProp();
175 comm = ippl::Comm->getCommunicator();
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::Comm->rank() == 0) {
198 fs::remove(sourceFileName);
199 }
200
201 close();
202 } else {
203 open(flags);
204
205 h5_prop_t props = H5CreateFileProp();
206 MPI_Comm comm = ippl::Comm->getCommunicator();
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
252void H5PartWrapper::copyFileSystem(const std::string& sourceFile) {
253 // namespace fs = boost::filesystem;
254
255 if (sourceFile == fileName_m)
256 return;
257
258 int sourceNode = 0;
259 if (ippl::Comm->rank() == sourceNode) {
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 // *ippl::Error << 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
279 dest.bad(), "H5PartWrapper::copyFile", "could not copy file " + sourceFile);
280 dest.close();
281 } else {
283 sourceNode, "H5PartWrapper::copyFile",
284 "received message to throw exception from node 0");
285 }
286}
287
288void H5PartWrapper::copyHeader(h5_file_t source) {
289 h5_int64_t numFileAttributes = H5GetNumFileAttribs(source);
290
291 const h5_size_t lengthAttributeName = 256;
292 char attributeName[lengthAttributeName];
293 h5_int64_t attributeType;
294 h5_size_t numAttributeElements;
295 std::vector<char> buffer(256);
296 h5_float32_t* f32buffer = reinterpret_cast<h5_float32_t*>(&buffer[0]);
297 h5_float64_t* f64buffer = reinterpret_cast<h5_float64_t*>(&buffer[0]);
298 h5_int32_t* i32buffer = reinterpret_cast<h5_int32_t*>(&buffer[0]);
299 h5_int64_t* i64buffer = reinterpret_cast<h5_int64_t*>(&buffer[0]);
300
301 for (h5_int64_t i = 0; i < numFileAttributes; ++i) {
302 REPORTONERROR(H5GetFileAttribInfo(
303 source, i, attributeName, lengthAttributeName, &attributeType, &numAttributeElements));
304
305 if (attributeType == H5_STRING_T) {
306 if (buffer.size() < numAttributeElements) {
307 buffer.resize(numAttributeElements);
308 }
309
310 READFILEATTRIB(String, source, attributeName, &buffer[0]);
311 WRITESTRINGFILEATTRIB(file_m, attributeName, &buffer[0]);
312
313 } else if (attributeType == H5_FLOAT32_T) {
314 if (buffer.size() < numAttributeElements * sizeof(h5_float32_t)) {
315 buffer.resize(numAttributeElements * sizeof(h5_float32_t));
316 }
317
318 READFILEATTRIB(Float32, source, attributeName, f32buffer);
319 WRITEFILEATTRIB(Float32, file_m, attributeName, f32buffer, numAttributeElements);
320
321 } else if (attributeType == H5_FLOAT64_T) {
322 if (buffer.size() < numAttributeElements * sizeof(h5_float64_t)) {
323 buffer.resize(numAttributeElements * sizeof(h5_float64_t));
324 }
325
326 READFILEATTRIB(Float64, source, attributeName, f64buffer);
327 WRITEFILEATTRIB(Float64, file_m, attributeName, f64buffer, numAttributeElements);
328
329 } else if (attributeType == H5_INT32_T) {
330 if (buffer.size() < numAttributeElements * sizeof(h5_int32_t)) {
331 buffer.resize(numAttributeElements * sizeof(h5_int32_t));
332 }
333
334 READFILEATTRIB(Int32, source, attributeName, i32buffer);
335 WRITEFILEATTRIB(Int32, file_m, attributeName, i32buffer, numAttributeElements);
336
337 } else if (attributeType == H5_INT64_T) {
338 if (buffer.size() < numAttributeElements * sizeof(h5_int64_t)) {
339 buffer.resize(numAttributeElements * sizeof(h5_int64_t));
340 }
341
342 READFILEATTRIB(Int64, source, attributeName, i64buffer);
343 WRITEFILEATTRIB(Int64, file_m, attributeName, i64buffer, numAttributeElements);
344
345 } else {
346 throw OpalException(
347 "H5PartWrapper::copyHeader", "unknown data type: " + std::to_string(attributeType));
348 }
349 }
350}
351
352void H5PartWrapper::copyStep(h5_file_t source, int step) {
353 REPORTONERROR(H5SetStep(file_m, numSteps_m));
354 REPORTONERROR(H5SetStep(source, step));
355
356 copyStepHeader(source);
357 copyStepData(source);
358}
359
360void H5PartWrapper::copyStepHeader(h5_file_t source) {
361 h5_int64_t numStepAttributes = H5GetNumStepAttribs(source);
362
363 h5_size_t lengthAttributeName = 256;
364 char attributeName[lengthAttributeName];
365 h5_int64_t attributeType;
366 h5_size_t numAttributeElements;
367
368 std::vector<char> buffer(256);
369 h5_float32_t* f32buffer = reinterpret_cast<h5_float32_t*>(&buffer[0]);
370 h5_float64_t* f64buffer = reinterpret_cast<h5_float64_t*>(&buffer[0]);
371 h5_int32_t* i32buffer = reinterpret_cast<h5_int32_t*>(&buffer[0]);
372 h5_int64_t* i64buffer = reinterpret_cast<h5_int64_t*>(&buffer[0]);
373
374 READSTEPATTRIB(String, source, "OPAL_flavour", &buffer[0]);
375 predecessorOPALFlavour_m = std::string(&buffer[0]);
376
377 for (h5_int64_t i = 0; i < numStepAttributes; ++i) {
378 REPORTONERROR(H5GetStepAttribInfo(
379 source, i, attributeName, lengthAttributeName, &attributeType, &numAttributeElements));
380
381 if (attributeType == H5TypesCHAR) {
382 if (buffer.size() < numAttributeElements) {
383 buffer.resize(numAttributeElements);
384 }
385
386 READSTEPATTRIB(String, source, attributeName, &buffer[0]);
387 WRITESTRINGSTEPATTRIB(file_m, attributeName, &buffer[0]);
388
389 } else if (attributeType == H5TypesFLOAT) {
390 if (buffer.size() < numAttributeElements * sizeof(h5_float32_t)) {
391 buffer.resize(numAttributeElements * sizeof(h5_float32_t));
392 }
393
394 READSTEPATTRIB(Float32, source, attributeName, f32buffer);
395 WRITESTEPATTRIB(Float32, file_m, attributeName, f32buffer, numAttributeElements);
396
397 } else if (attributeType == H5TypesDOUBLE) {
398 if (buffer.size() < numAttributeElements * sizeof(h5_float64_t)) {
399 buffer.resize(numAttributeElements * sizeof(h5_float64_t));
400 }
401
402 READSTEPATTRIB(Float64, source, attributeName, f64buffer);
403 WRITESTEPATTRIB(Float64, file_m, attributeName, f64buffer, numAttributeElements);
404
405 } else if (attributeType == H5TypesINT32) {
406 if (buffer.size() < numAttributeElements * sizeof(h5_int32_t)) {
407 buffer.resize(numAttributeElements * sizeof(h5_int32_t));
408 }
409
410 READSTEPATTRIB(Int32, source, attributeName, i32buffer);
411 WRITESTEPATTRIB(Int32, file_m, attributeName, i32buffer, numAttributeElements);
412
413 } else if (attributeType == H5TypesINT64) {
414 if (buffer.size() < numAttributeElements * sizeof(h5_int64_t)) {
415 buffer.resize(numAttributeElements * sizeof(h5_int64_t));
416 }
417
418 READSTEPATTRIB(Int64, source, attributeName, i64buffer);
419 WRITESTEPATTRIB(Int64, file_m, attributeName, i64buffer, numAttributeElements);
420
421 } else {
422 throw OpalException(
423 "H5PartWrapper::copyStepHeader",
424 "unknown data type: " + std::to_string(attributeType));
425 }
426 }
427}
428
429void H5PartWrapper::copyStepData(h5_file_t source) {
430 h5_size_t lengthSetName = 256;
431 char setName[lengthSetName];
432 h5_int64_t setType;
433 h5_size_t numSetElements;
434
435 h5_ssize_t numParticles = H5PartGetNumParticles(source);
436 h5_ssize_t numParticlesPerNode = numParticles / ippl::Comm->size();
437
438 h5_ssize_t firstParticle = numParticlesPerNode * ippl::Comm->rank();
439 h5_ssize_t lastParticle = firstParticle + numParticlesPerNode - 1;
440 if (ippl::Comm->rank() == ippl::Comm->size() - 1)
441 lastParticle = numParticles - 1;
442
443 REPORTONERROR(H5PartSetView(source, firstParticle, lastParticle));
444
445 numParticles = lastParticle - firstParticle + 1;
446 REPORTONERROR(H5PartSetNumParticles(file_m, numParticles));
447
448 std::vector<char> buffer(numParticles * sizeof(h5_float64_t));
449 char* buffer_ptr = Util::c_data(buffer);
450 h5_float32_t* f32buffer = reinterpret_cast<h5_float32_t*>(buffer_ptr);
451 h5_float64_t* f64buffer = reinterpret_cast<h5_float64_t*>(buffer_ptr);
452 h5_int32_t* i32buffer = reinterpret_cast<h5_int32_t*>(buffer_ptr);
453 h5_int64_t* i64buffer = reinterpret_cast<h5_int64_t*>(buffer_ptr);
454
455 h5_ssize_t numDatasets = H5PartGetNumDatasets(source);
456
457 for (h5_ssize_t i = 0; i < numDatasets; ++i) {
459 H5PartGetDatasetInfo(source, i, setName, lengthSetName, &setType, &numSetElements));
460
461 if (setType == H5TypesFLOAT) {
462 READDATA(Float32, source, setName, f32buffer);
463 WRITEDATA(Float32, file_m, setName, f32buffer);
464 } else if (setType == H5TypesDOUBLE) {
465 READDATA(Float64, source, setName, f64buffer);
466 WRITEDATA(Float64, file_m, setName, f64buffer);
467 } else if (setType == H5TypesINT32) {
468 READDATA(Int32, source, setName, i32buffer);
469 WRITEDATA(Int32, file_m, setName, i32buffer);
470 } else if (setType == H5TypesINT64) {
471 READDATA(Int64, source, setName, i64buffer);
472 WRITEDATA(Int64, file_m, setName, i64buffer);
473 } else {
474 throw OpalException(
475 "H5PartWrapper::copyStepData", "unknown data type: " + std::to_string(setType));
476 }
477 }
478
479 numParticles = H5PartGetNumParticles(file_m);
480 REPORTONERROR(H5PartSetView(source, -1, -1));
481}
482
484 bool failed, const std::string& where, const std::string& what) {
485 // int tag = 101;
486 /* \todo Message* mess = new Message();
487 putMessage(*mess, failed);
488 Ippl::Comm->broadcast_all(mess, tag);
489 delete mess;
490 */
491 if (failed)
492 throw OpalException(where, what);
493}
494
496 int sourceNode, const std::string& where, const std::string& what) {
497 // int tag = 101;
498 bool failed=false;
499 /* \todo
500 Message* mess = Ippl::Comm->receive_block(sourceNode, tag);
501 getMessage(*mess, failed);
502 delete mess;
503 */
504 if (failed)
505 throw OpalException(where, what);
506}
507
509 if (!file_m) {
510 throw OpalException("H5PartWrapper::getNumParticles", "no file opened");
511 }
512
513 REPORTONERROR(H5SetStep(file_m, numSteps_m - 1));
514 h5_ssize_t numParticles = H5PartGetNumParticles(file_m);
515
516 return numParticles;
517}
PartBunch< T, Dim >::ConstIterator end(PartBunch< 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)
T * c_data(std::vector< T, A > &v)
Definition Util.h:225
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
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.