OPALX (Object Oriented Parallel Accelerator Library for Exascal) master (dc2a29eed580)
OPALX
Loading...
Searching...
No Matches
DataSink.cpp
Go to the documentation of this file.
1//
2// Class DataSink
3// This class acts as an observer during the calculation. It generates diagnostic
4// output of the accelerated beam such as statistical beam descriptors of particle
5// positions, momenta, beam phase space (emittance) etc. These are written to file
6// at periodic time steps during the calculation.
7//
8// This class also writes the full beam phase space to an H5 file at periodic time
9// steps in the calculation (this period is different from that of the statistical
10// numbers).
11
12// Class also writes processor load balancing data to file to track parallel
13// calculation efficiency.
14//
15// Copyright (c) 2008 - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
16// All rights reserved
17//
18// This file is part of OPAL.
19//
20// OPAL is free software: you can redistribute it and/or modify
21// it under the terms of the GNU General Public License as published by
22// the Free Software Foundation, either version 3 of the License, or
23// (at your option) any later version.
24//
25// You should have received a copy of the GNU General Public License
26// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
27//
28#include "Structure/DataSink.h"
29
31#include "Fields/Fieldmap.h"
32#include "Physics/Units.h"
36#include "Utilities/Options.h"
37#include "Utilities/Timer.h"
38#include "Utilities/Util.h"
39
40#include <algorithm>
41#include <sstream>
42
44 const std::string& inputBasename, size_t numContainers, size_t index) {
45 if (numContainers <= 1) {
46 return inputBasename;
47 }
48 return inputBasename + "_c" + std::to_string(index);
49}
50
51DataSink::DataSink() { this->init(false, {}, 1); }
52
54 const std::vector<H5PartWrapper*>& h5wrappers, bool restart, size_t numParticleContainers) {
55 if (restart && !Options::enableHDF5) {
56 throw OpalException("DataSink::DataSink()", "Can not restart when HDF5 is disabled");
57 }
58
59 this->init(restart, h5wrappers, numParticleContainers);
60
61 if (restart) {
63 }
64}
65
66DataSink::DataSink(H5PartWrapper* h5wrapper, bool restart)
67 : DataSink(std::vector<H5PartWrapper*>{h5wrapper}, restart, 1) {}
68
69DataSink::DataSink(H5PartWrapper* h5wrapper) : DataSink(h5wrapper, false) {}
70
72 const size_t n = beam.getNumParticleContainers();
73 std::vector<std::array<Vector_t<double, 3>, 2>> v(n);
74 for (size_t i = 0; i < n; ++i) {
75 v[i][0] = FDext[0];
76 v[i][1] = FDext[1];
77 }
78 dumpH5(beam, v);
79}
80
82 PartBunch_t& beam,
83 const std::vector<std::array<Vector_t<double, 3>, 2>>& fdextPerContainer) const {
85 return;
86 }
87
88 const size_t n = beam.getNumParticleContainers();
89 if (fdextPerContainer.size() < n) {
90 throw OpalException(
91 "DataSink::dumpH5", "fdextPerContainer size ("
92 + std::to_string(fdextPerContainer.size())
93 + ") < num containers (" + std::to_string(n) + ").");
94 }
95
96 for (size_t i = 0; i < n; ++i) {
97 if (i >= h5Writers_m.size()) {
98 break;
99 }
100 auto pc = beam.getParticleContainer(i);
101 if (!pc || pc->getTotalNum() == 0) {
102 continue;
103 }
104 Vector_t<double, 3> fd[2] = {fdextPerContainer[i][0], fdextPerContainer[i][1]};
105 h5Writers_m[i]->writePhaseSpace(beam, fd, i);
106 }
107}
108
110 PartBunch_t& beam, Vector_t<double, 3> FDext[], double meanEnergy, double refPr,
111 double refPt, double refPz, double refR, double refTheta, double refZ, double azimuth,
112 double elevation, bool local) const {
113 if (!Options::enableHDF5 || h5Writers_m.empty()) {
114 return -1;
115 }
116
117 return h5Writers_m[0]->writePhaseSpace(
118 beam, FDext, meanEnergy, refPr, refPt, refPz, refR, refTheta, refZ, azimuth, elevation,
119 local, 0);
120}
121
123 PartBunch_t& beam, const std::vector<std::array<Vector_t<double, 3>, 2>>& fdextPerContainer,
124 const double& azimuth) const {
125 dumpSDDS(beam, fdextPerContainer, losses_t(), azimuth);
126}
127
129 PartBunch_t& beam, const std::vector<std::array<Vector_t<double, 3>, 2>>& fdextPerContainer,
130 const losses_t& losses, const double& azimuth) const {
131 const size_t n = beam.getNumParticleContainers();
132 if (fdextPerContainer.size() < n) {
133 throw OpalException(
134 "DataSink::dumpSDDS", "fdextPerContainer size ("
135 + std::to_string(fdextPerContainer.size())
136 + ") < num containers (" + std::to_string(n) + ").");
137 }
138
139 IpplTimings::startTimer(StatMarkerTimer_m);
140
141 for (size_t i = 0; i < n; ++i) {
142 if (i >= statWriters_m.size()) {
143 break;
144 }
145 auto pc = beam.getParticleContainer(i);
146 if (!pc) {
147 continue;
148 }
149
150 size_t npOutside = 0;
151 if (pc->getTotalNum() > 0) {
152 pc->updateMoments();
153
155 npOutside = beam.calcNumPartsOutside(Options::beamHaloBoundary * pc->getRmsR());
156 }
157 }
158
159 Vector_t<double, 3> fd[2] = {fdextPerContainer[i][0], fdextPerContainer[i][1]};
160 statWriters_m[i]->write(beam, fd, losses, azimuth, npOutside, i);
161 }
162
164 auto primary = beam.getParticleContainer(0);
165 if (primary && primary->getTotalNum() > 0) {
166 beam.calcBeamParameters();
167 }
168
169 IpplTimings::stopTimer(StatMarkerTimer_m);
170}
171
173 if (!Options::enableHDF5 || h5Writers_m.empty()) {
174 return;
175 }
176
177 h5Writers_m[0]->storeCavityInformation();
178}
179
180void DataSink::changeH5Wrappers(const std::vector<H5PartWrapper*>& h5wrappers) {
181 if (!Options::enableHDF5) {
182 return;
183 }
184
185 if (h5wrappers.size() != h5Writers_m.size()) {
186 throw OpalException(
187 "DataSink::changeH5Wrappers", "Expected " + std::to_string(h5Writers_m.size())
188 + " wrappers, got "
189 + std::to_string(h5wrappers.size()) + ".");
190 }
191
192 for (size_t i = 0; i < h5wrappers.size(); ++i) {
193 h5Writers_m[i]->changeH5Wrapper(h5wrappers[i]);
194 }
195}
196
198 if (ippl::Comm->rank() == 0 && Options::enableVTK) {
199 bg.writeGeomToVtk(fn);
200 }
201}
202
204 const PartBunch_t& beam, long long& step, size_t& impact, double& sey_num,
205 size_t numberOfFieldEmittedParticles, bool nEmissionMode, std::string fn) {
206 double charge = 0.0;
207 size_t Npart = 0;
208 double Npart_d = 0.0;
209 if (!nEmissionMode) {
210 const auto pc = beam.getParticleContainers()[0];
211 charge = -1.0 * pc->getTotalCharge();
212 // reduce(charge, charge, OpAddAssign());
213 Npart_d = -1.0 * charge / pc->getChargePerParticle();
214 } else {
215 Npart = beam.getParticleContainers()[0]->getTotalNum();
216 }
217 if (ippl::Comm->rank() == 0) {
218 std::string ffn = fn + std::string(".dat");
219
220 std::unique_ptr<Inform> ofp(new Inform(nullptr, ffn.c_str(), Inform::APPEND, 0));
221 Inform& fid = *ofp;
222 fid.precision(6);
223 fid << std::setiosflags(std::ios::scientific);
224 double t = beam.getT() * Units::s2ns;
225 if (!nEmissionMode) {
226 if (step == 0) {
227 fid << "#Time/ns" << std::setw(18) << "#Geometry impacts" << std::setw(18)
228 << "tot_sey" << std::setw(18) << "TotalCharge" << std::setw(18) << "PartNum"
229 << " numberOfFieldEmittedParticles " << endl;
230 }
231 fid << t << std::setw(18) << impact << std::setw(18) << sey_num << std::setw(18)
232 << charge << std::setw(18) << Npart_d << std::setw(18)
233 << numberOfFieldEmittedParticles << endl;
234 } else {
235 if (step == 0) {
236 fid << "#Time/ns" << std::setw(18) << "#Geometry impacts" << std::setw(18)
237 << "tot_sey" << std::setw(18) << "ParticleNumber"
238 << " numberOfFieldEmittedParticles " << endl;
239 }
240 fid << t << std::setw(18) << impact << std::setw(18) << sey_num << std::setw(18)
241 << double(Npart) << std::setw(18) << numberOfFieldEmittedParticles << endl;
242 }
243 }
244}
245
247 long long step, double time, bool preMerge, const std::vector<std::size_t>& binCounts,
248 const std::vector<double>& binWidths, double xMin, const std::string& fileName) {
249 if (ippl::Comm->rank() != 0) {
250 return;
251 }
252
253 Inform m("DataSink::dumpBinConfig");
254
255 if (binCounts.size() != binWidths.size()) {
256 m << level4 << "Invalid bin configuration: binCounts.size() = " << binCounts.size()
257 << ", binWidths.size() = " << binWidths.size() << endl;
258 throw OpalException(
259 "DataSink::dumpBinConfig", "binCounts and binWidths must have the same length.");
260 }
261
262 if (!binConfigWriter_m) {
263 m << level4 << "Creating BinConfigWriter for JSON binning output file \"" << fileName
264 << "\"." << endl;
265 binConfigWriter_m = std::make_unique<BinConfigWriter>(fileName);
266 }
267
268 m << level5 << "Dumping bin configuration snapshot: step=" << step << ", time=" << time
269 << ", preMerge=" << (preMerge ? 1 : 0) << ", nBins=" << binCounts.size() << ", xMin=" << xMin
270 << endl;
271
272 binConfigWriter_m->writeEntry(step, time, preMerge, binCounts, binWidths, xMin);
273}
274
276 unsigned int linesToRewind = 0;
277
278 for (size_t i = 0; i < h5Writers_m.size(); ++i) {
279 double spos = h5Writers_m[i]->getLastPosition();
280 if (i < statWriters_m.size() && statWriters_m[i]->exists()) {
281 unsigned int li = statWriters_m[i]->rewindToSpos(spos);
282 statWriters_m[i]->replaceVersionString();
283 linesToRewind = std::max(linesToRewind, li);
284 }
285 h5Writers_m[i]->close();
286 }
287
288 if (linesToRewind > 0) {
289 for (size_t i = 0; i < sddsWriter_m.size(); ++i) {
290 sddsWriter_m[i]->rewindLines(linesToRewind);
291 sddsWriter_m[i]->replaceVersionString();
292 }
293 }
294}
295
297 bool restart, const std::vector<H5PartWrapper*>& h5wrappers, size_t numParticleContainers) {
298 std::string fn = OpalData::getInstance()->getInputBasename();
299
300 lossWrCounter_m = 0;
301 StatMarkerTimer_m = IpplTimings::getTimer("Write Stat");
302
303 statWriters_m.clear();
304 for (size_t i = 0; i < numParticleContainers; ++i) {
305 std::string stem = diagnosticStemForContainer(fn, numParticleContainers, i);
306 statWriters_m.push_back(statWriter_t(new StatWriter(stem + std::string(".stat"), restart)));
307 }
308
309 sddsWriter_m.clear();
310 sddsWriter_m.push_back(sddsWriter_t(new LBalWriter(fn + std::string(".lbal"), restart)));
311
312 h5Writers_m.clear();
314 if (h5wrappers.size() != numParticleContainers) {
315 throw OpalException(
316 "DataSink::init",
317 "HDF5 enabled: expected " + std::to_string(numParticleContainers)
318 + " H5PartWrapper(s), got " + std::to_string(h5wrappers.size()) + ".");
319 }
320 for (H5PartWrapper* w : h5wrappers) {
321 h5Writers_m.push_back(h5Writer_t(new H5Writer(w, restart)));
322 }
323 } else if (!h5wrappers.empty()) {
324 throw OpalException("DataSink::init", "H5 wrappers passed while HDF5 is disabled.");
325 }
326}
ippl::Vector< T, Dim > Vector_t
void writeGeomToVtk(std::string fn)
void rewindLines()
Definition DataSink.cpp:275
std::vector< sddsWriter_t > sddsWriter_m
Definition DataSink.h:190
StatWriter::losses_t losses_t
Definition DataSink.h:50
void dumpH5(PartBunch_t &beam, Vector_t< double, 3 > FDext[]) const
Write H5 phase-space data for all particle containers.
Definition DataSink.cpp:71
void changeH5Wrappers(const std::vector< H5PartWrapper * > &h5wrappers)
Definition DataSink.cpp:180
void writeGeomToVtk(BoundaryGeometry &bg, std::string fn)
Definition DataSink.cpp:197
std::unique_ptr< SDDSWriter > sddsWriter_t
Definition DataSink.h:52
void writeImpactStatistics(const PartBunch_t &beam, long long int &step, size_t &impact, double &sey_num, size_t numberOfFieldEmittedParticles, bool nEmissionMode, std::string fn)
Definition DataSink.cpp:203
std::vector< h5Writer_t > h5Writers_m
Definition DataSink.h:188
void storeCavityInformation()
Write cavity information from H5 file.
Definition DataSink.cpp:172
static std::string diagnosticStemForContainer(const std::string &inputBasename, size_t numContainers, size_t index)
Definition DataSink.cpp:43
IpplTimings::TimerRef StatMarkerTimer_m
Timer to track statistics write time.
Definition DataSink.h:204
void init(bool restart, const std::vector< H5PartWrapper * > &h5wrappers, size_t numParticleContainers)
Definition DataSink.cpp:296
std::unique_ptr< H5Writer > h5Writer_t
Definition DataSink.h:53
unsigned int lossWrCounter_m
needed to create index for vtk file
Definition DataSink.h:201
void dumpBinConfig(long long step, double time, bool preMerge, const std::vector< std::size_t > &binCounts, const std::vector< double > &binWidths, double xMin, const std::string &fileName)
Append a binning configuration snapshot to a JSON file.
Definition DataSink.cpp:246
std::unique_ptr< BinConfigWriter > binConfigWriter_m
Definition DataSink.h:193
DataSink()
Default constructor.
Definition DataSink.cpp:51
std::vector< statWriter_t > statWriters_m
Definition DataSink.h:189
std::unique_ptr< StatWriter > statWriter_t
Definition DataSink.h:51
void dumpSDDS(PartBunch_t &beam, const std::vector< std::array< Vector_t< double, 3 >, 2 > > &fdextPerContainer, const double &azimuth) const
Write SDDS statistics with per-container external fields.
Definition DataSink.cpp:122
std::string getInputBasename()
get input file name without extension
Definition OpalData.cpp:571
static OpalData * getInstance()
Definition OpalData.cpp:193
void gatherLoadBalanceStatistics()
void updateMoments()
Definition PartBunch.h:338
double getTotalCharge() const
Get the total charge across all particle containers.
Definition PartBunch.h:457
void calcBeamParameters()
Update moments and set rmin_m / rmax_m from the primary (first) container.
double getT() const
Get the current simulation time.
Definition PartBunch.h:651
size_t calcNumPartsOutside(Vector_t< double, Dim >)
Stub; logs and returns 0.
Definition PartBunch.h:512
bool enableVTK
If true VTK files are written.
Definition Options.cpp:85
bool enableHDF5
If true HDF5 files are written.
Definition Options.cpp:83
double beamHaloBoundary
Definition Options.cpp:91
constexpr double s2ns
Definition Units.h:44
STL namespace.