29 #include <boost/filesystem.hpp>
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 " << fn_m; \
40 throw GeneralClassicException(std::string(__func__), ss.str()); \
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 " << fn_m; \
48 throw GeneralClassicException(std::string(__func__), ss.str()); \
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 " << fn_m; \
56 throw GeneralClassicException(std::string(__func__), ss.str()); \
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 " << fn_m; \
64 throw GeneralClassicException(std::string(__func__), ss.str()); \
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 " << fn_m; \
72 throw GeneralClassicException(std::string(__func__), ss.str()); \
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 " << fn_m; \
80 throw GeneralClassicException(std::string(__func__), ss.str()); \
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 " << fn_m; \
88 throw GeneralClassicException(std::string(__func__), ss.str()); \
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 " << fn_m; \
96 throw GeneralClassicException(std::string(__func__), ss.str()); \
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 " << fn_m; \
105 throw GeneralClassicException(std::string(__func__), ss.str()); \
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 " << fn_m; \
113 throw GeneralClassicException(std::string(__func__), ss.str()); \
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,
127 void i64transform(
const std::vector<OpalParticle> &particles,
128 unsigned int startIdx,
129 unsigned int numParticles,
131 std::function<h5_int64_t(
const OpalParticle&)> select) {
132 std::transform(particles.begin() + startIdx,
133 particles.begin() + startIdx + numParticles,
137 void cminmax(
double &
min,
double &
max,
double val) {
140 }
else if (val >
max) {
172 h5hut_mode_m(hdf5Save),
176 collectionType_m(collectionType)
184 "LossDataSink::LossDataSink",
185 "You must select an OPTION to save Loss data files\n"
186 "Please, choose 'ENABLEHDF5=TRUE' or 'ASCIIDUMP=TRUE'");
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),
206 collectionType_m(rhs.collectionType_m)
222 h5_prop_t props = H5CreateFileProp ();
224 H5SetPropFileMPIOCollective (props, &comm);
233 std::stringstream OPAL_version;
282 os_m <<
"# x (m), y (m), z (m), px ( ), py ( ), pz ( ), id";
284 os_m <<
", turn ( ), bunchNumber ( )";
294 long long globalTrackStep
304 if (turnBunchNumPair) {
307 "Either no particle or all have turn number and bunch number");
325 namespace fs = boost::filesystem;
338 for (
unsigned int i = 0; i < numSets; ++ i) {
389 allreduce(hasTurnInformation, 1, std::logical_or<bool>());
391 return hasTurnInformation > 0;
395 size_t startIdx = 0, endIdx = 0;
400 nLoc = endIdx - startIdx;
407 globN[i] = locN[i] = 0;
420 if (setIdx <
spos_m.size()) {
444 std::vector<char> buffer(nLoc *
sizeof(h5_float64_t));
445 h5_float64_t *f64buffer = nLoc > 0?
reinterpret_cast<h5_float64_t*
>(&buffer[0]) :
nullptr;
446 h5_int64_t *i64buffer = nLoc > 0?
reinterpret_cast<h5_int64_t*
>(&buffer[0]) :
nullptr;
448 ::i64transform(
particles_m, startIdx, nLoc, i64buffer,
451 ::f64transform(
particles_m, startIdx, nLoc, f64buffer,
454 ::f64transform(
particles_m, startIdx, nLoc, f64buffer,
457 ::f64transform(
particles_m, startIdx, nLoc, f64buffer,
460 ::f64transform(
particles_m, startIdx, nLoc, f64buffer,
463 ::f64transform(
particles_m, startIdx, nLoc, f64buffer,
466 ::f64transform(
particles_m, startIdx, nLoc, f64buffer,
469 ::f64transform(
particles_m, startIdx, nLoc, f64buffer,
472 ::f64transform(
particles_m, startIdx, nLoc, f64buffer,
488 ::f64transform(
particles_m, startIdx, nLoc, f64buffer,
505 for (
unsigned i = 0; i < partCount; i++) {
523 while (notReceived > 0) {
524 unsigned dataBlocks = 0;
528 ERRORMSG(
"LossDataSink: Could not receive from client nodes output." <<
endl);
531 rmsg->
get(&dataBlocks);
533 for (
unsigned i = 0; i < dataBlocks; i++) {
535 size_t bunchNum, turn;
536 double rx, ry, rz, px, py, pz, time;
538 os_m << (rmsg->
get(&rx), rx) <<
" ";
539 os_m << (rmsg->
get(&ry), ry) <<
" ";
540 os_m << (rmsg->
get(&rz), rz) <<
" ";
541 os_m << (rmsg->
get(&px), px) <<
" ";
542 os_m << (rmsg->
get(&py), py) <<
" ";
543 os_m << (rmsg->
get(&pz), pz) <<
" ";
544 os_m << (rmsg->
get(&
id), id) <<
" ";
546 os_m << (rmsg->
get(&turn), turn) <<
" ";
547 os_m << (rmsg->
get(&bunchNum), bunchNum) <<
" ";
549 os_m << (rmsg->
get(&time), time)
559 for (
unsigned i = 0; i < msgsize; i++) {
576 ERRORMSG(
"LossDataSink Ippl::Comm->send(smsg, 0, tag) failed " <<
endl);
605 size_t avgNumPerSet = nLoc / numSets;
606 std::vector<size_t> numPartsInSet(numSets, avgNumPerSet);
607 for (
unsigned int j = 0; j < (nLoc - numSets * avgNumPerSet); ++ j) {
612 std::vector<double> data(2 * numSets, 0.0);
613 double* meanT = &data[0];
614 double* numParticles = &data[numSets];
615 std::vector<double> timeRange(numSets, 0.0);
618 for (
unsigned int iteration = 0; iteration < 2; ++ iteration) {
620 for (
unsigned int j = 0; j < numSets; ++ j) {
622 const size_t &numThisSet = numPartsInSet[j];
623 for (
size_t k = 0; k < numThisSet; ++ k, ++ partIdx) {
627 numParticles[j] = numThisSet;
630 allreduce(&(data[0]), 2 * numSets, std::plus<double>());
632 for (
unsigned int j = 0; j < numSets; ++ j) {
633 meanT[j] /= numParticles[j];
636 for (
unsigned int j = 0; j < numSets - 1; ++ j) {
637 timeRange[j] = 0.5 * (meanT[j] + meanT[j + 1]);
639 timeRange[numSets - 1] = maxT;
641 std::fill(numPartsInSet.begin(),
647 for (
size_t idx = 0; idx < nLoc; ++ idx) {
648 if (
particles_m[idx].getTime() > timeRange[setNum]) {
649 numPartsInSet[setNum] = idx - idxPrior;
654 numPartsInSet[numSets - 1] = nLoc - idxPrior;
657 for (
unsigned int i = 0; i < numSets; ++ i) {
666 const unsigned int totalSize = 45;
667 double plainData[totalSize];
668 double rminmax[6] = {};
684 unsigned int idx = startIdx;
685 for (
unsigned long k = 0; k < nLoc; ++ k, ++ idx) {
688 part[0] = particle.
getX();
689 part[1] = particle.
getPx();
690 part[2] = particle.
getY();
691 part[3] = particle.
getPy();
692 part[4] = particle.
getZ();
693 part[5] = particle.
getPz();
695 for (
int i = 0; i < 6; i++) {
696 localCentroid[i] += part[i];
697 for (
int j = 0; j <= i; j++) {
698 localMoments[i * 6 + j] += part[i] * part[j];
701 localOthers[0] += particle.
getTime();
704 ::cminmax(rminmax[0], rminmax[1], particle.
getX());
705 ::cminmax(rminmax[2], rminmax[3], particle.
getY());
706 ::cminmax(rminmax[4], rminmax[5], particle.
getZ());
709 for (
int i = 0; i < 6; i++) {
710 for (
int j = 0; j < i; j++) {
711 localMoments[j * 6 + i] = localMoments[i * 6 + j];
715 for (
unsigned int i = 0; i < totalSize; ++ i) {
716 plainData[i] = data[i].
sum;
719 new_reduce(plainData, totalSize, std::plus<double>());
720 new_reduce(rminmax, 6, std::greater<double>());
723 if (plainData[0] == 0.0)
return stat;
725 double *centroid = plainData + 1;
726 double *moments = plainData + 7;
727 double *others = plainData + 43;
734 stat.
nTotal_m = (
unsigned long)std::round(plainData[0]);
736 for (
unsigned int i = 0 ; i < 3u; i++) {
739 stat.
rsqsum_m(i) = (moments[2 * i * 6 + 2 * i] -
742 moments[(2 * i + 1) * 6 + (2 * i) + 1] -
744 stat.
rpsum_m(i) = (moments[(2 * i) * 6 + (2 * i) + 1] -
755 for (
unsigned int i = 0 ; i < 3u; i++) {
760 stat.
fac_m(i) = (tmp == 0) ? 0.0 : 1.0 / tmp;
761 stat.
rmin_m(i) = -rminmax[2 * i];
762 stat.
rmax_m(i) = rminmax[2 * i + 1];
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Tps< T > sqrt(const Tps< T > &x)
Square root.
#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)
#define OPAL_PROJECT_VERSION
#define OPAL_PROJECT_NAME
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)
void allreduce(const T *input, T *output, int count, Op op)
bool reduce(Communicate &, InputIterator, InputIterator, OutputIterator, const ReduceOp &, bool *IncludeVal=0)
void new_reduce(const T *input, T *output, int count, Op op, int root=0)
Inform & endl(Inform &inf)
Inform & level2(Inform &inf)
bool enableHDF5
If true HDF5 files are written.
std::string getGitRevision()
void setOpenMode(OPENMODE openMode)
OPENMODE getOpenMode() const
void checkAndAddOutputFileName(const std::string &outfn)
checks the output file names of all items to avoid duplicates
OPENMODE
Enum for writing to files.
static OpalData * getInstance()
Vector_t getStandardDeviationMomentum() const
double getMeanKineticEnergy() const
Vector_t getStandardDeviationPosition() const
double getTotalCharge() const
Vector_t getMeanPosition() 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
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
void addParticle(const OpalParticle &, const boost::optional< std::pair< int, short int >> &turnBunchNumPair=boost::none)
~LossDataSink() noexcept(false)
std::vector< double > refTime_m
CollectionType collectionType_m
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 openH5(h5_int32_t mode=H5_O_WRONLY)
SetStatistics computeSetStatistics(unsigned int setIdx)
void splitSets(unsigned int numSets)
std::vector< OpalParticle > particles_m
void save(unsigned int numSets=1, OpalData::OPENMODE openMode=OpalData::OPENMODE::UNDEFINED)
bool hasTurnInformations() const
void saveH5(unsigned int setIdx)
std::vector< h5_int64_t > globalTrackStep_m
bool hasNoParticlesToDump() const
std::vector< unsigned long > startSet_m
bool send(Message *, int node, int tag, bool delmsg=true)
Message * receive_block(int &node, int &tag)
Message & put(const T &val)
Message & get(const T &cval)
int next_tag(int t, int s=1000)
static MPI_Comm getComm()
static Communicate * Comm