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