23#include "OPALconfig.h"
35#define WRITE_FILEATTRIB_STRING(attribute, value) \
37 h5_int64_t h5err = H5WriteFileAttribString(H5file_m, attribute, value); \
38 if (h5err <= H5_ERR) { \
39 std::stringstream ss; \
40 ss << "failed to write string attribute " << attribute << " to file " << fileName_m; \
41 throw GeneralClassicException(std::string(__func__), ss.str()); \
44#define WRITE_STEPATTRIB_FLOAT64(attribute, value, size) \
46 h5_int64_t h5err = H5WriteStepAttribFloat64(H5file_m, attribute, value, size); \
47 if (h5err <= H5_ERR) { \
48 std::stringstream ss; \
49 ss << "failed to write float64 attribute " << attribute << " to file " << fileName_m; \
50 throw GeneralClassicException(std::string(__func__), ss.str()); \
53#define WRITE_STEPATTRIB_INT64(attribute, value, size) \
55 h5_int64_t h5err = H5WriteStepAttribInt64(H5file_m, attribute, value, size); \
56 if (h5err <= H5_ERR) { \
57 std::stringstream ss; \
58 ss << "failed to write int64 attribute " << attribute << " to file " << fileName_m; \
59 throw GeneralClassicException(std::string(__func__), ss.str()); \
62#define WRITE_DATA_FLOAT64(name, value) \
64 h5_int64_t h5err = H5PartWriteDataFloat64(H5file_m, name, value); \
65 if (h5err <= H5_ERR) { \
66 std::stringstream ss; \
67 ss << "failed to write float64 data " << name << " to file " << fileName_m; \
68 throw GeneralClassicException(std::string(__func__), ss.str()); \
71#define WRITE_DATA_INT64(name, value) \
73 h5_int64_t h5err = H5PartWriteDataInt64(H5file_m, name, value); \
74 if (h5err <= H5_ERR) { \
75 std::stringstream ss; \
76 ss << "failed to write int64 data " << name << " to file " << fileName_m; \
77 throw GeneralClassicException(std::string(__func__), ss.str()); \
82 h5_int64_t h5err = H5SetStep(H5file_m, H5call_m); \
83 if (h5err <= H5_ERR) { \
84 std::stringstream ss; \
85 ss << "failed to set step " << H5call_m << " in file " << fileName_m; \
86 throw GeneralClassicException(std::string(__func__), ss.str()); \
89#define GET_NUM_STEPS() \
91 H5call_m = H5GetNumSteps(H5file_m); \
92 if (H5call_m <= H5_ERR) { \
93 std::stringstream ss; \
94 ss << "failed to get number of steps of file " << fileName_m; \
95 throw GeneralClassicException(std::string(__func__), ss.str()); \
98#define SET_NUM_PARTICLES(num) \
100 h5_int64_t h5err = H5PartSetNumParticles(H5file_m, num); \
101 if (h5err <= H5_ERR) { \
102 std::stringstream ss; \
103 ss << "failed to set number of particles to " << num << " in step " << H5call_m \
104 << " in file " << fileName_m; \
105 throw GeneralClassicException(std::string(__func__), ss.str()); \
109#define OPEN_FILE(fname, mode, props) \
111 H5file_m = H5OpenFile(fname, mode, props); \
112 if (H5file_m == (h5_file_t)H5_ERR) { \
113 std::stringstream ss; \
114 ss << "failed to open file " << fileName_m; \
115 throw GeneralClassicException(std::string(__func__), ss.str()); \
118#define CLOSE_FILE() \
120 h5_int64_t h5err = H5CloseFile(H5file_m); \
121 if (h5err <= H5_ERR) { \
122 std::stringstream ss; \
123 ss << "failed to close file " << fileName_m; \
124 throw GeneralClassicException(std::string(__func__), ss.str()); \
130 const std::vector<OpalParticle>& particles,
unsigned int startIdx,
131 unsigned int numParticles, h5_float64_t* buffer,
132 std::function<h5_float64_t(
const OpalParticle&)> select) {
134 particles.begin() + startIdx, particles.begin() + startIdx + numParticles, buffer,
138 const std::vector<OpalParticle>& particles,
unsigned int startIdx,
139 unsigned int numParticles, h5_int64_t* buffer,
140 std::function<h5_int64_t(
const OpalParticle&)> select) {
142 particles.begin() + startIdx, particles.begin() + startIdx + numParticles, buffer,
146 void cminmax(
double&
min,
double&
max,
double val) {
149 }
else if (val >
max) {
192 "LossDataSink::LossDataSink",
193 "You must select an OPTION to save Loss data files\n"
194 "Please, choose 'ENABLEHDF5=TRUE' or 'ASCIIDUMP=TRUE'");
228 h5_prop_t props = H5CreateFileProp();
230 H5SetPropFileMPIOCollective(props, &comm);
237 std::stringstream OPAL_version;
238 OPAL_version << OPAL_PROJECT_NAME <<
" " << OPAL_PROJECT_VERSION <<
" # git rev. "
297 os_m <<
"# x (m), y (m), z (m), px ( ), py ( ), pz ( ), id";
299 os_m <<
", turn ( ), bunchNumber ( )";
301 os_m <<
", time (s)" << std::endl;
306 const Vector_t& x,
const Vector_t& p,
double time,
double spos,
long long globalTrackStep) {
315 const OpalParticle& particle,
const boost::optional<std::pair<int, short>>& turnBunchNumPair) {
316 if (turnBunchNumPair) {
319 "LossDataSink::addParticle",
320 "Either no particle or all have turn number and bunch number");
339 namespace fs = std::filesystem;
350 for (
unsigned int i = 0; i < numSets; ++i) {
376 spos_m = std::vector<double>();
400 allreduce(hasTurnInformation, 1, std::logical_or<bool>());
402 return hasTurnInformation > 0;
407 size_t startIdx = 0, endIdx = nLoc;
411 nLoc = endIdx - startIdx;
418 globN[i] = locN[i] = 0;
431 if (setIdx <
spos_m.size()) {
459 "68-percentile", (tmpVector = engine.
get68Percentile(), &tmpVector[0]), 3);
461 "95-percentile", (tmpVector = engine.
get95Percentile(), &tmpVector[0]), 3);
463 "99-percentile", (tmpVector = engine.
get99Percentile(), &tmpVector[0]), 3);
468 "normalizedEps68Percentile",
471 "normalizedEps95Percentile",
474 "normalizedEps99Percentile",
477 "normalizedEps99_99Percentile",
484 std::vector<char> buffer(nLoc *
sizeof(h5_float64_t));
485 h5_float64_t* f64buffer = nLoc > 0 ?
reinterpret_cast<h5_float64_t*
>(&buffer[0]) :
nullptr;
486 h5_int64_t* i64buffer = nLoc > 0 ?
reinterpret_cast<h5_int64_t*
>(&buffer[0]) :
nullptr;
489 return particle.
getId();
493 return particle.
getX();
497 return particle.
getY();
501 return particle.
getZ();
505 return particle.
getPx();
509 return particle.
getPy();
513 return particle.
getPz();
552 for (
unsigned i = 0; i < partCount; i++) {
569 while (notReceived > 0) {
570 unsigned dataBlocks = 0;
574 ERRORMSG(
"LossDataSink: Could not receive from client nodes output." <<
endl);
577 rmsg->
get(&dataBlocks);
579 for (
unsigned i = 0; i < dataBlocks; i++) {
581 size_t bunchNum, turn;
582 double rx, ry, rz, px, py, pz, time;
584 os_m << (rmsg->
get(&rx), rx) <<
" ";
585 os_m << (rmsg->
get(&ry), ry) <<
" ";
586 os_m << (rmsg->
get(&rz), rz) <<
" ";
587 os_m << (rmsg->
get(&px), px) <<
" ";
588 os_m << (rmsg->
get(&py), py) <<
" ";
589 os_m << (rmsg->
get(&pz), pz) <<
" ";
590 os_m << (rmsg->
get(&
id),
id) <<
" ";
592 os_m << (rmsg->
get(&turn), turn) <<
" ";
593 os_m << (rmsg->
get(&bunchNum), bunchNum) <<
" ";
595 os_m << (rmsg->
get(&time), time) << std::endl;
604 for (
unsigned i = 0; i < msgsize; i++) {
621 ERRORMSG(
"LossDataSink Ippl::Comm->send(smsg, 0, tag) failed " <<
endl);
650 size_t avgNumPerSet = nLoc / numSets;
651 std::vector<size_t> numPartsInSet(numSets, avgNumPerSet);
652 for (
unsigned int j = 0; j < (nLoc - numSets * avgNumPerSet); ++j) {
657 std::vector<double> data(2 * numSets, 0.0);
658 double* meanT = &data[0];
659 double* numParticles = &data[numSets];
660 std::vector<double> timeRange(numSets, 0.0);
663 for (
unsigned int iteration = 0; iteration < 2; ++iteration) {
665 for (
unsigned int j = 0; j < numSets; ++j) {
666 const size_t& numThisSet = numPartsInSet[j];
667 for (
size_t k = 0; k < numThisSet; ++k, ++partIdx) {
669 maxT = std::max(maxT,
particles_m[partIdx].getTime());
671 numParticles[j] = numThisSet;
674 allreduce(&(data[0]), 2 * numSets, std::plus<double>());
676 for (
unsigned int j = 0; j < numSets; ++j) {
677 meanT[j] /= numParticles[j];
680 for (
unsigned int j = 0; j < numSets - 1; ++j) {
681 timeRange[j] = 0.5 * (meanT[j] + meanT[j + 1]);
683 timeRange[numSets - 1] = maxT;
685 std::fill(numPartsInSet.begin(), numPartsInSet.end(), 0);
689 for (
size_t idx = 0; idx < nLoc; ++idx) {
690 if (
particles_m[idx].getTime() > timeRange[setNum]) {
691 numPartsInSet[setNum] = idx - idxPrior;
696 numPartsInSet[numSets - 1] = nLoc - idxPrior;
699 for (
unsigned int i = 0; i < numSets; ++i) {
708 const unsigned int totalSize = 45;
709 double plainData[totalSize];
710 double rminmax[6] = {};
726 unsigned int idx = startIdx;
727 for (
unsigned long k = 0; k < nLoc; ++k, ++idx) {
730 part[0] = particle.
getX();
731 part[1] = particle.
getPx();
732 part[2] = particle.
getY();
733 part[3] = particle.
getPy();
734 part[4] = particle.
getZ();
735 part[5] = particle.
getPz();
737 for (
int i = 0; i < 6; i++) {
738 localCentroid[i] += part[i];
739 for (
int j = 0; j <= i; j++) {
740 localMoments[i * 6 + j] += part[i] * part[j];
743 localOthers[0] += particle.
getTime();
744 localOthers[1] += std::pow(particle.
getTime(), 2);
746 ::cminmax(rminmax[0], rminmax[1], particle.
getX());
747 ::cminmax(rminmax[2], rminmax[3], particle.
getY());
748 ::cminmax(rminmax[4], rminmax[5], particle.
getZ());
751 for (
int i = 0; i < 6; i++) {
752 for (
int j = 0; j < i; j++) {
753 localMoments[j * 6 + i] = localMoments[i * 6 + j];
757 for (
unsigned int i = 0; i < totalSize; ++i) {
758 plainData[i] = data[i].
sum;
761 allreduce(plainData, totalSize, std::plus<double>());
762 allreduce(rminmax, 6, std::greater<double>());
764 if (plainData[0] == 0.0)
767 double* centroid = plainData + 1;
768 double* moments = plainData + 7;
769 double* others = plainData + 43;
776 stat.
nTotal_m = (
unsigned long)std::round(plainData[0]);
778 for (
unsigned int i = 0; i < 3u; i++) {
782 (moments[2 * i * 6 + 2 * i] - stat.
nTotal_m * std::pow(stat.
rmean_m(i), 2));
785 moments[(2 * i + 1) * 6 + (2 * i) + 1] - stat.
nTotal_m * std::pow(stat.
pmean_m(i), 2));
787 (moments[(2 * i) * 6 + (2 * i) + 1]
799 for (
unsigned int i = 0; i < 3u; i++) {
804 stat.
fac_m(i) = (tmp == 0) ? 0.0 : 1.0 / tmp;
805 stat.
rmin_m(i) = -rminmax[2 * i];
806 stat.
rmax_m(i) = rminmax[2 * i + 1];
#define OPEN_FILE(fname, mode, props)
#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)
void allreduce(const T *input, T *output, int count, Op op)
bool reduce(Communicate &, InputIterator, InputIterator, OutputIterator, const ReduceOp &, bool *IncludeVal=0)
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Inform & level2(Inform &inf)
Inform & endl(Inform &inf)
bool enableHDF5
If true HDF5 files are written.
std::string getGitRevision()
void checkAndAddOutputFileName(const std::string &outfn)
checks the output file names of all items to avoid duplicates
OpenMode getOpenMode() const
static OpalData * getInstance()
OpenMode
Enum for writing to files.
void setOpenMode(OpenMode openMode)
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 getStdTime() const
double getTotalMass() const
Vector_t getMeanMomentum() const
Vector_t get95Percentile() const
Vector_t get68Percentile() const
double getMeanTime() const
Vector_t getGeometricEmittance() const
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.
std::vector< size_t > turnNumber_m
std::vector< Vector_t > RefPartR_m
void addReferenceParticle(const Vector_t &x, const Vector_t &p, double time, double spos, long long globalTrackStep)
h5_file_t H5file_m
used to write out data in H5hut mode
~LossDataSink() noexcept(false)
std::vector< double > refTime_m
CollectionType collectionType_m
void save(unsigned int numSets=1, OpalData::OpenMode openMode=OpalData::OpenMode::UNDEFINED)
std::vector< Vector_t > RefPartP_m
h5_int64_t H5call_m
Current record, or time step, of H5 file.
std::vector< size_t > bunchNumber_m
std::vector< double > spos_m
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
bool hasTurnInformations() const
void saveH5(unsigned int setIdx)
std::vector< h5_int64_t > globalTrackStep_m
bool hasNoParticlesToDump() const
std::vector< unsigned long > startSet_m
Message & put(const T &val)
Message & get(const T &cval)
static MPI_Comm getComm()
static Communicate * Comm
Vektor< double, 3 > Vector_t