OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
LossDataSink.cpp
Go to the documentation of this file.
1//
2// Class LossDataSink
3// This class writes file attributes to describe phase space of loss files
4//
5// Copyright (c) 200x - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
6// All rights reserved
7//
8// This file is part of OPAL.
9//
10// OPAL is free software: you can redistribute it and/or modify
11// it under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// You should have received a copy of the GNU General Public License
16// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
17//
19
22#include "Message/GlobalComm.h"
23#include "OPALconfig.h"
25#include "Utilities/Options.h"
26#include "Utilities/Util.h"
27#include "Utility/IpplInfo.h"
28
29#include <boost/filesystem.hpp>
30
31#include <cmath>
32
33extern Inform* gmsg;
34
35#define WRITE_FILEATTRIB_STRING( attribute, value ) { \
36 h5_int64_t h5err = H5WriteFileAttribString (H5file_m, attribute, value); \
37 if (h5err <= H5_ERR) { \
38 std::stringstream ss; \
39 ss << "failed to write string attribute " << attribute << " to file " << fileName_m; \
40 throw GeneralClassicException(std::string(__func__), ss.str()); \
41 }\
42}
43#define WRITE_STEPATTRIB_FLOAT64( attribute, value, size ) { \
44 h5_int64_t h5err = H5WriteStepAttribFloat64 (H5file_m, attribute, value, size); \
45 if (h5err <= H5_ERR) { \
46 std::stringstream ss; \
47 ss << "failed to write float64 attribute " << attribute << " to file " << fileName_m; \
48 throw GeneralClassicException(std::string(__func__), ss.str()); \
49 }\
50}
51#define WRITE_STEPATTRIB_INT64( attribute, value, size ) { \
52 h5_int64_t h5err = H5WriteStepAttribInt64 (H5file_m, attribute, value, size); \
53 if (h5err <= H5_ERR) { \
54 std::stringstream ss; \
55 ss << "failed to write int64 attribute " << attribute << " to file " << fileName_m; \
56 throw GeneralClassicException(std::string(__func__), ss.str()); \
57 }\
58}
59#define WRITE_DATA_FLOAT64( name, value ) { \
60 h5_int64_t h5err = H5PartWriteDataFloat64 (H5file_m, name, value); \
61 if (h5err <= H5_ERR) { \
62 std::stringstream ss; \
63 ss << "failed to write float64 data " << name << " to file " << fileName_m; \
64 throw GeneralClassicException(std::string(__func__), ss.str()); \
65 }\
66}
67#define WRITE_DATA_INT64( name, value ) { \
68 h5_int64_t h5err = H5PartWriteDataInt64 (H5file_m, name, value); \
69 if (h5err <= H5_ERR) { \
70 std::stringstream ss; \
71 ss << "failed to write int64 data " << name << " to file " << fileName_m; \
72 throw GeneralClassicException(std::string(__func__), ss.str()); \
73 }\
74}
75#define SET_STEP() { \
76 h5_int64_t h5err = H5SetStep (H5file_m, H5call_m); \
77 if (h5err <= H5_ERR) { \
78 std::stringstream ss; \
79 ss << "failed to set step " << H5call_m << " in file " << fileName_m; \
80 throw GeneralClassicException(std::string(__func__), ss.str()); \
81 }\
82}
83#define GET_NUM_STEPS() { \
84 H5call_m = H5GetNumSteps( H5file_m ); \
85 if (H5call_m <= H5_ERR) { \
86 std::stringstream ss; \
87 ss << "failed to get number of steps of file " << fileName_m; \
88 throw GeneralClassicException(std::string(__func__), ss.str()); \
89 }\
90}
91#define SET_NUM_PARTICLES( num ) { \
92 h5_int64_t h5err = H5PartSetNumParticles (H5file_m, num); \
93 if (h5err <= H5_ERR) { \
94 std::stringstream ss; \
95 ss << "failed to set number of particles to " << num << " in step " << H5call_m << " in file " << fileName_m; \
96 throw GeneralClassicException(std::string(__func__), ss.str()); \
97 }\
98}
99
100#define OPEN_FILE( fname, mode, props ) { \
101 H5file_m = H5OpenFile (fname, mode, props); \
102 if (H5file_m == (h5_file_t)H5_ERR) { \
103 std::stringstream ss; \
104 ss << "failed to open file " << fileName_m; \
105 throw GeneralClassicException(std::string(__func__), ss.str()); \
106 }\
107}
108#define CLOSE_FILE() { \
109 h5_int64_t h5err = H5CloseFile (H5file_m); \
110 if (h5err <= H5_ERR) { \
111 std::stringstream ss; \
112 ss << "failed to close file " << fileName_m; \
113 throw GeneralClassicException(std::string(__func__), ss.str()); \
114 }\
115}
116
117namespace {
118 void f64transform(const std::vector<OpalParticle> &particles,
119 unsigned int startIdx,
120 unsigned int numParticles,
121 h5_float64_t *buffer,
122 std::function<h5_float64_t(const OpalParticle&)> select) {
123 std::transform(particles.begin() + startIdx,
124 particles.begin() + startIdx + numParticles,
125 buffer, select);
126 }
127 void i64transform(const std::vector<OpalParticle> &particles,
128 unsigned int startIdx,
129 unsigned int numParticles,
130 h5_int64_t *buffer,
131 std::function<h5_int64_t(const OpalParticle&)> select) {
132 std::transform(particles.begin() + startIdx,
133 particles.begin() + startIdx + numParticles,
134 buffer, select);
135 }
136
137 void cminmax(double &min, double &max, double val) {
138 if (-val > min) {
139 min = -val;
140 } else if (val > max) {
141 max = val;
142 }
143 }
144}
145
147 outputName_m(""),
148 spos_m(0.0),
149 refTime_m(0.0),
150 tmean_m(0.0),
151 trms_m(0.0),
152 nTotal_m(0),
153 RefPartR_m(0.0),
154 RefPartP_m(0.0),
155 rmin_m(0.0),
156 rmax_m(0.0),
157 rmean_m(0.0),
158 pmean_m(0.0),
159 rrms_m(0.0),
160 prms_m(0.0),
161 rprms_m(0.0),
162 normEmit_m(0.0),
163 rsqsum_m(0.0),
164 psqsum_m(0.0),
165 rpsum_m(0.0),
166 eps2_m(0.0),
167 eps_norm_m(0.0),
168 fac_m(0.0)
169 { }
170
171LossDataSink::LossDataSink(std::string outfn, bool hdf5Save, CollectionType collectionType):
172 h5hut_mode_m(hdf5Save),
173 H5file_m(0),
174 outputName_m(outfn),
175 H5call_m(0),
176 collectionType_m(collectionType)
177{
178 particles_m.clear();
179 turnNumber_m.clear();
180 bunchNumber_m.clear();
181
184 "LossDataSink::LossDataSink",
185 "You must select an OPTION to save Loss data files\n"
186 "Please, choose 'ENABLEHDF5=TRUE' or 'ASCIIDUMP=TRUE'");
187 }
188
190
191 if (OpalData::getInstance()->hasBunchAllocated()) {
193 }
194}
195
197 h5hut_mode_m(rhs.h5hut_mode_m),
198 H5file_m(rhs.H5file_m),
199 outputName_m(rhs.outputName_m),
200 H5call_m(rhs.H5call_m),
201 RefPartR_m(rhs.RefPartR_m),
202 RefPartP_m(rhs.RefPartP_m),
203 globalTrackStep_m(rhs.globalTrackStep_m),
204 refTime_m(rhs.refTime_m),
205 spos_m(rhs.spos_m),
206 collectionType_m(rhs.collectionType_m)
207{
208 particles_m.clear();
209 turnNumber_m.clear();
210 bunchNumber_m.clear();
211}
212
214 if (H5file_m) {
215 CLOSE_FILE ();
216 H5file_m = 0;
217 }
218}
219
220void LossDataSink::openH5(h5_int32_t mode) {
221 h5_prop_t props = H5CreateFileProp ();
222 MPI_Comm comm = Ippl::getComm();
223 H5SetPropFileMPIOCollective (props, &comm);
224 OPEN_FILE (fileName_m.c_str(), mode, props);
225 H5CloseProp (props);
226}
227
228
230
231 // Write file attributes to describe phase space to H5 file.
232 std::stringstream OPAL_version;
233 OPAL_version << OPAL_PROJECT_NAME << " " << OPAL_PROJECT_VERSION << " # git rev. " << Util::getGitRevision();
234 WRITE_FILEATTRIB_STRING("OPAL_version", OPAL_version.str().c_str());
235
236 WRITE_FILEATTRIB_STRING("SPOSUnit", "m");
237 WRITE_FILEATTRIB_STRING("TIMEUnit", "s");
238 WRITE_FILEATTRIB_STRING("RefPartRUnit", "m");
239 WRITE_FILEATTRIB_STRING("RefPartPUnit", "#beta#gamma");
240 WRITE_FILEATTRIB_STRING("GlobalTrackStepUnit", "1");
241
242 WRITE_FILEATTRIB_STRING("centroidUnit", "m");
243 WRITE_FILEATTRIB_STRING("RMSXUnit", "m");
244 WRITE_FILEATTRIB_STRING("MEANPUnit", "#beta#gamma");
245 WRITE_FILEATTRIB_STRING("RMSPUnit", "#beta#gamma");
246 WRITE_FILEATTRIB_STRING("#varepsilonUnit", "m rad");
247 WRITE_FILEATTRIB_STRING("#varepsilon-geomUnit", "m rad");
248 WRITE_FILEATTRIB_STRING("ENERGYUnit", "MeV");
249 WRITE_FILEATTRIB_STRING("dEUnit", "MeV");
250 WRITE_FILEATTRIB_STRING("TotalChargeUnit", "C");
251 WRITE_FILEATTRIB_STRING("TotalMassUnit", "MeV");
252
253 WRITE_FILEATTRIB_STRING("idUnit", "1");
254 WRITE_FILEATTRIB_STRING("xUnit", "m");
255 WRITE_FILEATTRIB_STRING("yUnit", "m");
256 WRITE_FILEATTRIB_STRING("zUnit", "m");
257 WRITE_FILEATTRIB_STRING("pxUnit", "#beta#gamma");
258 WRITE_FILEATTRIB_STRING("pyUnit", "#beta#gamma");
259 WRITE_FILEATTRIB_STRING("pzUnit", "#beta#gamma");
260 WRITE_FILEATTRIB_STRING("qUnit", "C");
261 WRITE_FILEATTRIB_STRING("mUnit", "MeV");
262
263 WRITE_FILEATTRIB_STRING("turnUnit", "1");
264 WRITE_FILEATTRIB_STRING("bunchNumUnit", "1");
265
266 WRITE_FILEATTRIB_STRING("timeUnit", "s");
267 WRITE_FILEATTRIB_STRING("meanTimeUnit", "s");
268 WRITE_FILEATTRIB_STRING("rmsTimeUnit", "s");
269
271 WRITE_FILEATTRIB_STRING("68-percentileUnit", "m");
272 WRITE_FILEATTRIB_STRING("95-percentileUnit", "m");
273 WRITE_FILEATTRIB_STRING("99-percentileUnit", "m");
274 WRITE_FILEATTRIB_STRING("99_99-percentileUnit", "m");
275 WRITE_FILEATTRIB_STRING("normalizedEps68PercentileUnit", "m rad");
276 WRITE_FILEATTRIB_STRING("normalizedEps95PercentileUnit", "m rad");
277 WRITE_FILEATTRIB_STRING("normalizedEps99PercentileUnit", "m rad");
278 WRITE_FILEATTRIB_STRING("normalizedEps99_99PercentileUnit", "m rad");
279 }
280
282 WRITE_FILEATTRIB_STRING("type", "temporal");
283 } else {
284 WRITE_FILEATTRIB_STRING("type", "spatial");
285 }
286}
287
288
290 bool hasTurn = hasTurnInformations();
291 if (Ippl::myNode() == 0) {
292 os_m << "# x (m), y (m), z (m), px ( ), py ( ), pz ( ), id";
293 if (hasTurn) {
294 os_m << ", turn ( ), bunchNumber ( )";
295 }
296 os_m << ", time (s)" << std::endl;
297 }
298}
299
301 const Vector_t &p,
302 double time,
303 double spos,
304 long long globalTrackStep
305 ) {
306 RefPartR_m.push_back(x);
307 RefPartP_m.push_back(p);
308 globalTrackStep_m.push_back((h5_int64_t)globalTrackStep);
309 spos_m.push_back(spos);
310 refTime_m.push_back(time);
311}
312
313void LossDataSink::addParticle(const OpalParticle &particle, const boost::optional<std::pair<int, short>> &turnBunchNumPair) {
314 if (turnBunchNumPair) {
315 if (!particles_m.empty() && turnNumber_m.empty()) {
316 throw GeneralClassicException("LossDataSink::addParticle",
317 "Either no particle or all have turn number and bunch number");
318 }
319 turnNumber_m.push_back(turnBunchNumPair.get().first);
320 bunchNumber_m.push_back(turnBunchNumPair.get().second);
321 }
322
323 particles_m.push_back(particle);
324}
325
326void LossDataSink::save(unsigned int numSets, OpalData::OpenMode openMode) {
327
328 if (outputName_m.empty()) return;
329 if (hasNoParticlesToDump()) return;
330
331 if (openMode == OpalData::OpenMode::UNDEFINED) {
332 openMode = OpalData::getInstance()->getOpenMode();
333 }
334
335 namespace fs = boost::filesystem;
336 if (h5hut_mode_m) {
337 fileName_m = outputName_m + std::string(".h5");
338 if (openMode == OpalData::OpenMode::WRITE || !fs::exists(fileName_m)) {
339 openH5();
341 } else {
342 openH5(H5_O_APPENDONLY);
343 GET_NUM_STEPS ();
344 }
345
346 for (unsigned int i = 0; i < numSets; ++ i) {
347 saveH5(i);
348 }
349 CLOSE_FILE ();
350 H5file_m = 0;
351
352 } else {
353 fileName_m = outputName_m + std::string(".loss");
354 if (openMode == OpalData::OpenMode::WRITE || !fs::exists(fileName_m)) {
355 openASCII();
357 } else {
358 appendASCII();
359 }
360 saveASCII();
361 closeASCII();
362 }
363 *gmsg << level2 << "Save '" << fileName_m << "'" << endl;
364
366
367 particles_m.clear();
368 turnNumber_m.clear();
369 bunchNumber_m.clear();
370 spos_m.clear();
371 refTime_m.clear();
372 RefPartR_m.clear();
373 RefPartP_m.clear();
374 globalTrackStep_m.clear();
375}
376
377// Note: This was changed to calculate the global number of dumped particles
378// because there are two cases to be considered:
379// 1. ALL nodes have 0 lost particles -> nothing to be done.
380// 2. Some nodes have 0 lost particles, some not -> H5 can handle that but all
381// nodes HAVE to participate, otherwise H5 waits endlessly for a response from
382// the nodes that didn't enter the saveH5 function. -DW
384
385 size_t nLoc = particles_m.size();
386
387 reduce(nLoc, nLoc, OpAddAssign());
388
389 return nLoc == 0;
390}
391
393
394 bool hasTurnInformation = !turnNumber_m.empty();
395
396 allreduce(hasTurnInformation, 1, std::logical_or<bool>());
397
398 return hasTurnInformation > 0;
399}
400
401void LossDataSink::saveH5(unsigned int setIdx) {
402 size_t nLoc = particles_m.size();
403 size_t startIdx = 0, endIdx = nLoc;
404 if (setIdx + 1 < startSet_m.size()) {
405 startIdx = startSet_m[setIdx];
406 endIdx = startSet_m[setIdx + 1];
407 nLoc = endIdx - startIdx;
408 }
409
410 std::unique_ptr<size_t[]> locN(new size_t[Ippl::getNodes()]);
411 std::unique_ptr<size_t[]> globN(new size_t[Ippl::getNodes()]);
412
413 for (int i = 0; i < Ippl::getNodes(); i++) {
414 globN[i] = locN[i] = 0;
415 }
416
417 locN[Ippl::myNode()] = nLoc;
418 reduce(locN.get(), locN.get() + Ippl::getNodes(), globN.get(), OpAddAssign());
419
420 DistributionMoments engine;
421 engine.compute(particles_m.begin() + startIdx, particles_m.begin() + endIdx);
422
424 SET_STEP ();
425 SET_NUM_PARTICLES (nLoc);
426
427 if (setIdx < spos_m.size()) {
428 WRITE_STEPATTRIB_FLOAT64 ("SPOS", &(spos_m[setIdx]), 1);
429 WRITE_STEPATTRIB_FLOAT64 ("TIME", &(refTime_m[setIdx]), 1);
430 WRITE_STEPATTRIB_FLOAT64 ("RefPartR", (h5_float64_t *)&(RefPartR_m[setIdx]), 3);
431 WRITE_STEPATTRIB_FLOAT64 ("RefPartP", (h5_float64_t *)&(RefPartP_m[setIdx]), 3);
432 WRITE_STEPATTRIB_INT64("GlobalTrackStep", &(globalTrackStep_m[setIdx]), 1);
433 }
434
435 Vector_t tmpVector;
436 double tmpDouble;
437 WRITE_STEPATTRIB_FLOAT64("centroid", (tmpVector = engine.getMeanPosition(), &tmpVector[0]), 3);
438 WRITE_STEPATTRIB_FLOAT64("RMSX", (tmpVector = engine.getStandardDeviationPosition(), &tmpVector[0]), 3);
439 WRITE_STEPATTRIB_FLOAT64("MEANP", (tmpVector = engine.getMeanMomentum(), &tmpVector[0]), 3);
440 WRITE_STEPATTRIB_FLOAT64("RMSP", (tmpVector = engine.getStandardDeviationMomentum(), &tmpVector[0]), 3);
441 WRITE_STEPATTRIB_FLOAT64("#varepsilon", (tmpVector = engine.getNormalizedEmittance(), &tmpVector[0]), 3);
442 WRITE_STEPATTRIB_FLOAT64("#varepsilon-geom", (tmpVector = engine.getGeometricEmittance(), &tmpVector[0]), 3);
443 WRITE_STEPATTRIB_FLOAT64("ENERGY", (tmpDouble = engine.getMeanKineticEnergy(), &tmpDouble), 1);
444 WRITE_STEPATTRIB_FLOAT64("dE", (tmpDouble = engine.getStdKineticEnergy(), &tmpDouble), 1);
445 WRITE_STEPATTRIB_FLOAT64("TotalCharge", (tmpDouble = engine.getTotalCharge(), &tmpDouble), 1);
446 WRITE_STEPATTRIB_FLOAT64("TotalMass", (tmpDouble = engine.getTotalMass(), &tmpDouble), 1);
447 WRITE_STEPATTRIB_FLOAT64("meanTime", (tmpDouble = engine.getMeanTime(), &tmpDouble), 1);
448 WRITE_STEPATTRIB_FLOAT64("rmsTime", (tmpDouble = engine.getStdTime(), &tmpDouble), 1);
450 WRITE_STEPATTRIB_FLOAT64("68-percentile", (tmpVector = engine.get68Percentile(), &tmpVector[0]), 3);
451 WRITE_STEPATTRIB_FLOAT64("95-percentile", (tmpVector = engine.get95Percentile(), &tmpVector[0]), 3);
452 WRITE_STEPATTRIB_FLOAT64("99-percentile", (tmpVector = engine.get99Percentile(), &tmpVector[0]), 3);
453 WRITE_STEPATTRIB_FLOAT64("99_99-percentile", (tmpVector = engine.get99_99Percentile(), &tmpVector[0]), 3);
454
455 WRITE_STEPATTRIB_FLOAT64("normalizedEps68Percentile",
456 (tmpVector = engine.getNormalizedEmittance68Percentile(), &tmpVector[0]), 3);
457 WRITE_STEPATTRIB_FLOAT64("normalizedEps95Percentile",
458 (tmpVector = engine.getNormalizedEmittance95Percentile(), &tmpVector[0]), 3);
459 WRITE_STEPATTRIB_FLOAT64("normalizedEps99Percentile",
460 (tmpVector = engine.getNormalizedEmittance99Percentile(), &tmpVector[0]), 3);
461 WRITE_STEPATTRIB_FLOAT64("normalizedEps99_99Percentile",
462 (tmpVector = engine.getNormalizedEmittance99_99Percentile(), &tmpVector[0]), 3);
463 }
464
465 WRITE_STEPATTRIB_FLOAT64("maxR", (tmpVector = engine.getMaxR(), &tmpVector[0]), 3);
466
467 // Write all data
468 std::vector<char> buffer(nLoc * sizeof(h5_float64_t));
469 h5_float64_t *f64buffer = nLoc > 0? reinterpret_cast<h5_float64_t*>(&buffer[0]) : nullptr;
470 h5_int64_t *i64buffer = nLoc > 0? reinterpret_cast<h5_int64_t*>(&buffer[0]) : nullptr;
471
472 ::i64transform(particles_m, startIdx, nLoc, i64buffer,
473 [](const OpalParticle &particle) { return particle.getId(); });
474 WRITE_DATA_INT64 ("id", i64buffer);
475 ::f64transform(particles_m, startIdx, nLoc, f64buffer,
476 [](const OpalParticle &particle) { return particle.getX(); });
477 WRITE_DATA_FLOAT64 ("x", f64buffer);
478 ::f64transform(particles_m, startIdx, nLoc, f64buffer,
479 [](const OpalParticle &particle) { return particle.getY(); });
480 WRITE_DATA_FLOAT64 ("y", f64buffer);
481 ::f64transform(particles_m, startIdx, nLoc, f64buffer,
482 [](const OpalParticle &particle) { return particle.getZ(); });
483 WRITE_DATA_FLOAT64 ("z", f64buffer);
484 ::f64transform(particles_m, startIdx, nLoc, f64buffer,
485 [](const OpalParticle &particle) { return particle.getPx(); });
486 WRITE_DATA_FLOAT64 ("px", f64buffer);
487 ::f64transform(particles_m, startIdx, nLoc, f64buffer,
488 [](const OpalParticle &particle) { return particle.getPy(); });
489 WRITE_DATA_FLOAT64 ("py", f64buffer);
490 ::f64transform(particles_m, startIdx, nLoc, f64buffer,
491 [](const OpalParticle &particle) { return particle.getPz(); });
492 WRITE_DATA_FLOAT64 ("pz", f64buffer);
493 ::f64transform(particles_m, startIdx, nLoc, f64buffer,
494 [](const OpalParticle &particle) { return particle.getCharge(); });
495 WRITE_DATA_FLOAT64 ("q", f64buffer);
496 ::f64transform(particles_m, startIdx, nLoc, f64buffer,
497 [](const OpalParticle &particle) { return particle.getMass(); });
498 WRITE_DATA_FLOAT64 ("m", f64buffer);
499
500 if (hasTurnInformations()) {
501 std::copy(turnNumber_m.begin() + startIdx,
502 turnNumber_m.begin() + startIdx + nLoc,
503 i64buffer);
504 WRITE_DATA_INT64 ("turn", i64buffer);
505
506 std::copy(bunchNumber_m.begin() + startIdx,
507 bunchNumber_m.begin() + startIdx + nLoc,
508 i64buffer);
509 WRITE_DATA_INT64 ("bunchNumber", i64buffer);
510 }
511
512 ::f64transform(particles_m, startIdx, nLoc, f64buffer,
513 [](const OpalParticle &particle) { return particle.getTime(); });
514 WRITE_DATA_FLOAT64 ("time", f64buffer);
515
516 ++ H5call_m;
517}
518
520
521 /*
522 ASCII output
523 */
525 bool hasTurn = hasTurnInformations();
526 if (Ippl::Comm->myNode() == 0) {
527 const unsigned partCount = particles_m.size();
528
529 for (unsigned i = 0; i < partCount; i++) {
530 const OpalParticle& particle = particles_m[i];
531 os_m << particle.getX() << " ";
532 os_m << particle.getY() << " ";
533 os_m << particle.getZ() << " ";
534 os_m << particle.getPx() << " ";
535 os_m << particle.getPy() << " ";
536 os_m << particle.getPz() << " ";
537 os_m << particle.getId() << " ";
538 if (hasTurn) {
539 os_m << turnNumber_m[i] << " ";
540 os_m << bunchNumber_m[i] << " ";
541 }
542 os_m << particle.getTime()
543 << std::endl;
544 }
545
546 int notReceived = Ippl::getNodes() - 1;
547 while (notReceived > 0) {
548 unsigned dataBlocks = 0;
549 int node = COMM_ANY_NODE;
550 Message *rmsg = Ippl::Comm->receive_block(node, tag);
551 if (rmsg == 0) {
552 ERRORMSG("LossDataSink: Could not receive from client nodes output." << endl);
553 }
554 notReceived--;
555 rmsg->get(&dataBlocks);
556 rmsg->get(&hasTurn);
557 for (unsigned i = 0; i < dataBlocks; i++) {
558 long id;
559 size_t bunchNum, turn;
560 double rx, ry, rz, px, py, pz, time;
561
562 os_m << (rmsg->get(&rx), rx) << " ";
563 os_m << (rmsg->get(&ry), ry) << " ";
564 os_m << (rmsg->get(&rz), rz) << " ";
565 os_m << (rmsg->get(&px), px) << " ";
566 os_m << (rmsg->get(&py), py) << " ";
567 os_m << (rmsg->get(&pz), pz) << " ";
568 os_m << (rmsg->get(&id), id) << " ";
569 if (hasTurn) {
570 os_m << (rmsg->get(&turn), turn) << " ";
571 os_m << (rmsg->get(&bunchNum), bunchNum) << " ";
572 }
573 os_m << (rmsg->get(&time), time)
574 << std::endl;
575 }
576 delete rmsg;
577 }
578 } else {
579 Message *smsg = new Message();
580 const unsigned msgsize = particles_m.size();
581 smsg->put(msgsize);
582 smsg->put(hasTurn);
583 for (unsigned i = 0; i < msgsize; i++) {
584 const OpalParticle& particle = particles_m[i];
585 smsg->put(particle.getX());
586 smsg->put(particle.getY());
587 smsg->put(particle.getZ());
588 smsg->put(particle.getPx());
589 smsg->put(particle.getPy());
590 smsg->put(particle.getPz());
591 smsg->put(particle.getId());
592 if (hasTurn) {
593 smsg->put(turnNumber_m[i]);
594 smsg->put(bunchNumber_m[i]);
595 }
596 smsg->put(particle.getTime());
597 }
598 bool res = Ippl::Comm->send(smsg, 0, tag);
599 if (!res) {
600 ERRORMSG("LossDataSink Ippl::Comm->send(smsg, 0, tag) failed " << endl);
601 }
602 }
603}
604
624void LossDataSink::splitSets(unsigned int numSets) {
625 if (numSets <= 1 ||
626 particles_m.size() == 0) return;
627
628 const size_t nLoc = particles_m.size();
629 size_t avgNumPerSet = nLoc / numSets;
630 std::vector<size_t> numPartsInSet(numSets, avgNumPerSet);
631 for (unsigned int j = 0; j < (nLoc - numSets * avgNumPerSet); ++ j) {
632 ++ numPartsInSet[j];
633 }
634 startSet_m.resize(numSets + 1, 0);
635
636 std::vector<double> data(2 * numSets, 0.0);
637 double* meanT = &data[0];
638 double* numParticles = &data[numSets];
639 std::vector<double> timeRange(numSets, 0.0);
640 double maxT = particles_m[0].getTime();
641
642 for (unsigned int iteration = 0; iteration < 2; ++ iteration) {
643 size_t partIdx = 0;
644 for (unsigned int j = 0; j < numSets; ++ j) {
645
646 const size_t &numThisSet = numPartsInSet[j];
647 for (size_t k = 0; k < numThisSet; ++ k, ++ partIdx) {
648 meanT[j] += particles_m[partIdx].getTime();
649 maxT = std::max(maxT, particles_m[partIdx].getTime());
650 }
651 numParticles[j] = numThisSet;
652 }
653
654 allreduce(&(data[0]), 2 * numSets, std::plus<double>());
655
656 for (unsigned int j = 0; j < numSets; ++ j) {
657 meanT[j] /= numParticles[j];
658 }
659
660 for (unsigned int j = 0; j < numSets - 1; ++ j) {
661 timeRange[j] = 0.5 * (meanT[j] + meanT[j + 1]);
662 }
663 timeRange[numSets - 1] = maxT;
664
665 std::fill(numPartsInSet.begin(),
666 numPartsInSet.end(),
667 0);
668
669 size_t setNum = 0;
670 size_t idxPrior = 0;
671 for (size_t idx = 0; idx < nLoc; ++ idx) {
672 if (particles_m[idx].getTime() > timeRange[setNum]) {
673 numPartsInSet[setNum] = idx - idxPrior;
674 idxPrior = idx;
675 ++ setNum;
676 }
677 }
678 numPartsInSet[numSets - 1] = nLoc - idxPrior;
679 }
680
681 for (unsigned int i = 0; i < numSets; ++ i) {
682 startSet_m[i + 1] = startSet_m[i] + numPartsInSet[i];
683 }
684}
685
687 SetStatistics stat;
688 double part[6];
689
690 const unsigned int totalSize = 45;
691 double plainData[totalSize];
692 double rminmax[6] = {};
693
694 Util::KahanAccumulation data[totalSize];
695 Util::KahanAccumulation *localCentroid = data + 1;
696 Util::KahanAccumulation *localMoments = data + 7;
697 Util::KahanAccumulation *localOthers = data + 43;
698
699 size_t startIdx = 0;
700 size_t nLoc = particles_m.size();
701 if (setIdx + 1 < startSet_m.size()) {
702 startIdx = startSet_m[setIdx];
703 nLoc = startSet_m[setIdx + 1] - startSet_m[setIdx];
704 }
705
706 data[0].sum = nLoc;
707
708 unsigned int idx = startIdx;
709 for (unsigned long k = 0; k < nLoc; ++ k, ++ idx) {
710 const OpalParticle& particle = particles_m[idx];
711
712 part[0] = particle.getX();
713 part[1] = particle.getPx();
714 part[2] = particle.getY();
715 part[3] = particle.getPy();
716 part[4] = particle.getZ();
717 part[5] = particle.getPz();
718
719 for (int i = 0; i < 6; i++) {
720 localCentroid[i] += part[i];
721 for (int j = 0; j <= i; j++) {
722 localMoments[i * 6 + j] += part[i] * part[j];
723 }
724 }
725 localOthers[0] += particle.getTime();
726 localOthers[1] += std::pow(particle.getTime(), 2);
727
728 ::cminmax(rminmax[0], rminmax[1], particle.getX());
729 ::cminmax(rminmax[2], rminmax[3], particle.getY());
730 ::cminmax(rminmax[4], rminmax[5], particle.getZ());
731 }
732
733 for (int i = 0; i < 6; i++) {
734 for (int j = 0; j < i; j++) {
735 localMoments[j * 6 + i] = localMoments[i * 6 + j];
736 }
737 }
738
739 for (unsigned int i = 0; i < totalSize; ++ i) {
740 plainData[i] = data[i].sum;
741 }
742
743 allreduce(plainData, totalSize, std::plus<double>());
744 allreduce(rminmax, 6, std::greater<double>());
745
746 if (plainData[0] == 0.0) return stat;
747
748 double *centroid = plainData + 1;
749 double *moments = plainData + 7;
750 double *others = plainData + 43;
751
753 stat.spos_m = spos_m[setIdx];
754 stat.refTime_m = refTime_m[setIdx];
755 stat.RefPartR_m = RefPartR_m[setIdx];
756 stat.RefPartP_m = RefPartP_m[setIdx];
757 stat.nTotal_m = (unsigned long)std::round(plainData[0]);
758
759 for (unsigned int i = 0 ; i < 3u; i++) {
760 stat.rmean_m(i) = centroid[2 * i] / stat.nTotal_m;
761 stat.pmean_m(i) = centroid[(2 * i) + 1] / stat.nTotal_m;
762 stat.rsqsum_m(i) = (moments[2 * i * 6 + 2 * i] -
763 stat.nTotal_m * std::pow(stat.rmean_m(i), 2));
764 stat.psqsum_m(i) = std::max(0.0,
765 moments[(2 * i + 1) * 6 + (2 * i) + 1] -
766 stat.nTotal_m * std::pow(stat.pmean_m(i), 2));
767 stat.rpsum_m(i) = (moments[(2 * i) * 6 + (2 * i) + 1] -
768 stat.nTotal_m * stat.rmean_m(i) * stat.pmean_m(i));
769 }
770 stat.tmean_m = others[0] / stat.nTotal_m;
771 stat.trms_m = std::sqrt(std::max(0.0, (others[1] / stat.nTotal_m - std::pow(stat.tmean_m, 2))));
772
773 stat.eps2_m = ((stat.rsqsum_m * stat.psqsum_m - stat.rpsum_m * stat.rpsum_m) /
774 (1.0 * stat.nTotal_m * stat.nTotal_m));
775
776 stat.rpsum_m /= stat.nTotal_m;
777
778 for (unsigned int i = 0 ; i < 3u; i++) {
779 stat.rrms_m(i) = std::sqrt(std::max(0.0, stat.rsqsum_m(i)) / stat.nTotal_m);
780 stat.prms_m(i) = std::sqrt(std::max(0.0, stat.psqsum_m(i)) / stat.nTotal_m);
781 stat.eps_norm_m(i) = std::sqrt(std::max(0.0, stat.eps2_m(i)));
782 double tmp = stat.rrms_m(i) * stat.prms_m(i);
783 stat.fac_m(i) = (tmp == 0) ? 0.0 : 1.0 / tmp;
784 stat.rmin_m(i) = -rminmax[2 * i];
785 stat.rmax_m(i) = rminmax[2 * i + 1];
786 }
787
788 stat.rprms_m = stat.rpsum_m * stat.fac_m;
789
790 return stat;
791}
#define OPAL_PROJECT_VERSION
Definition: OPALconfig.h:5
#define OPAL_PROJECT_NAME
Definition: OPALconfig.h:2
#define GET_NUM_STEPS()
#define OPEN_FILE(fname, mode, props)
#define SET_STEP()
#define WRITE_DATA_FLOAT64(name, value)
#define WRITE_STEPATTRIB_INT64(attribute, value, size)
#define WRITE_FILEATTRIB_STRING(attribute, value)
#define SET_NUM_PARTICLES(num)
#define WRITE_STEPATTRIB_FLOAT64(attribute, value, size)
#define WRITE_DATA_INT64(name, value)
Inform * gmsg
Definition: Main.cpp:61
#define CLOSE_FILE()
CollectionType
Definition: LossDataSink.h:72
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Definition: TpsMath.h:76
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
void allreduce(const T *input, T *output, int count, Op op)
Definition: GlobalComm.hpp:510
bool reduce(Communicate &, InputIterator, InputIterator, OutputIterator, const ReduceOp &, bool *IncludeVal=0)
Definition: GlobalComm.hpp:55
const int COMM_ANY_NODE
Definition: Communicate.h:40
#define IPPL_APP_CYCLE
Definition: Tags.h:103
#define IPPL_APP_TAG3
Definition: Tags.h:96
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:84
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:76
Inform & level2(Inform &inf)
Definition: Inform.cpp:46
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
#define ERRORMSG(msg)
Definition: IpplInfo.h:350
py::list function(PolynomialPatch *patch, py::list point)
bool computePercentiles
Definition: Options.cpp:111
bool enableHDF5
If true HDF5 files are written.
Definition: Options.cpp:81
std::string getGitRevision()
Definition: Util.cpp:32
FRONT * fs
Definition: hypervolume.cpp:59
void checkAndAddOutputFileName(const std::string &outfn)
checks the output file names of all items to avoid duplicates
Definition: OpalData.cpp:675
OpenMode getOpenMode() const
Definition: OpalData.cpp:353
static OpalData * getInstance()
Definition: OpalData.cpp:196
OpenMode
Enum for writing to files.
Definition: OpalData.h:64
void setOpenMode(OpenMode openMode)
Definition: OpalData.cpp:349
Vector_t getStandardDeviationMomentum() const
Vector_t get99Percentile() const
double getMeanKineticEnergy() const
Vector_t getStandardDeviationPosition() const
Vector_t getNormalizedEmittance95Percentile() const
Vector_t getNormalizedEmittance68Percentile() const
double getTotalCharge() const
Vector_t getNormalizedEmittance99_99Percentile() const
Vector_t getNormalizedEmittance99Percentile() const
Vector_t getMeanPosition() const
Vector_t get99_99Percentile() const
void compute(const std::vector< OpalParticle >::const_iterator &, const std::vector< OpalParticle >::const_iterator &)
double getStdKineticEnergy() const
Vector_t getNormalizedEmittance() const
double getTotalMass() const
Vector_t getMeanMomentum() const
Vector_t getMaxR() const
Vector_t get95Percentile() const
Vector_t get68Percentile() const
double getMeanTime() const
Vector_t getGeometricEmittance() const
double getPy() const
Get vertical momentum (no dimension).
Definition: OpalParticle.h:213
double getPz() const
Get relative momentum error (no dimension).
Definition: OpalParticle.h:219
double getY() const
Get vertical displacement in m.
Definition: OpalParticle.h:195
double getCharge() const
Get charge in Coulomb.
Definition: OpalParticle.h:243
double getZ() const
Get longitudinal displacement c*t in m.
Definition: OpalParticle.h:201
double getMass() const
Get mass in GeV/c^2.
Definition: OpalParticle.h:249
double getTime() const
Get time.
Definition: OpalParticle.h:237
int64_t getId() const
Get the id of the particle.
Definition: OpalParticle.h:176
double getPx() const
Get horizontal momentum (no dimension).
Definition: OpalParticle.h:207
double getX() const
Get horizontal position in m.
Definition: OpalParticle.h:189
Vector_t eps_norm_m
Definition: LossDataSink.h:60
Vector_t rmax_m
Definition: LossDataSink.h:49
Vector_t RefPartP_m
Definition: LossDataSink.h:47
std::string outputName_m
Definition: LossDataSink.h:40
Vector_t prms_m
Definition: LossDataSink.h:53
Vector_t pmean_m
Definition: LossDataSink.h:51
Vector_t psqsum_m
Definition: LossDataSink.h:57
double tmean_m
Definition: LossDataSink.h:43
Vector_t rmean_m
Definition: LossDataSink.h:50
unsigned long nTotal_m
Definition: LossDataSink.h:45
Vector_t rsqsum_m
Definition: LossDataSink.h:56
Vector_t eps2_m
Definition: LossDataSink.h:59
Vector_t rrms_m
Definition: LossDataSink.h:52
Vector_t fac_m
Definition: LossDataSink.h:61
Vector_t RefPartR_m
Definition: LossDataSink.h:46
Vector_t rpsum_m
Definition: LossDataSink.h:58
Vector_t rmin_m
Definition: LossDataSink.h:48
double refTime_m
Definition: LossDataSink.h:42
Vector_t rprms_m
Definition: LossDataSink.h:54
std::vector< size_t > turnNumber_m
Definition: LossDataSink.h:160
std::vector< Vector_t > RefPartR_m
Definition: LossDataSink.h:162
void addReferenceParticle(const Vector_t &x, const Vector_t &p, double time, double spos, long long globalTrackStep)
void openASCII()
Definition: LossDataSink.h:108
h5_file_t H5file_m
used to write out data in H5hut mode
Definition: LossDataSink.h:151
~LossDataSink() noexcept(false)
void writeHeaderH5()
std::vector< double > refTime_m
Definition: LossDataSink.h:165
CollectionType collectionType_m
Definition: LossDataSink.h:170
std::string outputName_m
Definition: LossDataSink.h:153
void writeHeaderASCII()
void save(unsigned int numSets=1, OpalData::OpenMode openMode=OpalData::OpenMode::UNDEFINED)
std::ofstream os_m
Definition: LossDataSink.h:148
std::vector< Vector_t > RefPartP_m
Definition: LossDataSink.h:163
h5_int64_t H5call_m
Current record, or time step, of H5 file.
Definition: LossDataSink.h:156
std::vector< size_t > bunchNumber_m
Definition: LossDataSink.h:159
std::string fileName_m
Definition: LossDataSink.h:142
std::vector< double > spos_m
Definition: LossDataSink.h:166
void addParticle(const OpalParticle &, const boost::optional< std::pair< int, short int > > &turnBunchNumPair=boost::none)
void openH5(h5_int32_t mode=H5_O_WRONLY)
SetStatistics computeSetStatistics(unsigned int setIdx)
void splitSets(unsigned int numSets)
std::vector< OpalParticle > particles_m
Definition: LossDataSink.h:158
bool hasTurnInformations() const
void appendASCII()
Definition: LossDataSink.h:115
void saveH5(unsigned int setIdx)
std::vector< h5_int64_t > globalTrackStep_m
Definition: LossDataSink.h:164
LossDataSink()=default
void closeASCII()
Definition: LossDataSink.h:127
bool hasNoParticlesToDump() const
std::vector< unsigned long > startSet_m
Definition: LossDataSink.h:168
long double sum
Definition: Util.h:214
bool send(Message *, int node, int tag, bool delmsg=true)
Message * receive_block(int &node, int &tag)
void barrier(void)
Message & put(const T &val)
Definition: Message.h:406
Message & get(const T &cval)
Definition: Message.h:476
int next_tag(int t, int s=1000)
Definition: TagMaker.h:39
Definition: Inform.h:42
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