OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
MultiBunchHandler.cpp
Go to the documentation of this file.
1//
2// Class MultiBunchHandler
3// Helper class that stores bunch injection
4// information like azimuth, radius etc. of first
5// bunch in multi-bunch mode of ParallelCyclotronTracker.
6//
7// Copyright (c) 2007 - 2014, Jianjun Yang, Paul Scherrer Institut, Villigen PSI, Switzerland
8// Copyright (c) 2012 - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
9// All rights reserved
10//
11// Implemented as part of the PhD thesis
12// "Beam dynamics in high intensity cyclotrons including neighboring bunch effects"
13// and the paper
14// "Beam dynamics in high intensity cyclotrons including neighboring bunch effects:
15// Model, implementation, and application"
16// (https://journals.aps.org/prab/pdf/10.1103/PhysRevSTAB.13.064201)
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 "MultiBunchHandler.h"
29
30#include "Physics/Units.h"
32
33//FIXME Remove headers and dynamic_cast in
35#ifdef ENABLE_AMR
37#endif
38
39extern Inform *gmsg;
40
42 const int& numBunch,
43 const double& eta,
44 const double& para,
45 const std::string& mode,
46 const std::string& binning)
47 : onebunch_m(OpalData::getInstance()->getInputBasename() + "-onebunch.h5")
48 , numBunch_m(numBunch)
49 , eta_m(eta)
50 , coeffDBunches_m(para)
51 , radiusLastTurn_m(0.0)
52 , radiusThisTurn_m(0.0)
53 , bunchCount_m(1)
54{
55 PAssert_GT(numBunch, 1);
56
57 binfo_m.reserve(numBunch);
58 for (int i = 0; i < beam->getNumBunch(); ++i) {
59 binfo_m.push_back(beaminfo_t());
60 }
61
62 this->setBinning(binning);
63
64 // mode of generating new bunches:
65 // "FORCE" means generating one bunch after each revolution, until get "TURNS" bunches.
66 // "AUTO" means only when the distance between two neighbor bunches is below the limitation,
67 // then starts to generate new bunches after each revolution,until get "TURNS" bunches;
68 // otherwise, run single bunch track
69
70 *gmsg << "***---------------------------- MULTI-BUNCHES MULTI-ENERGY-BINS MODE "
71 << "----------------------------*** " << endl;
72
73 // only for regular run of multi bunches, instantiate the PartBins class
74 // note that for restart run of multi bunches, PartBins class is instantiated in function
75 // Distribution::doRestartOpalCycl()
76 if (!OpalData::getInstance()->inRestartRun()) {
77
78 // already exist bins number initially
79 const int BinCount = 1;
80 //allowed maximal bin
81 const int MaxBinNum = 1000;
82
83 // initialize particles number for each bin (both existed and not yet emmitted)
84 size_t partInBin[MaxBinNum] = {0};
85 partInBin[0] = beam->getTotalNum();
86
87 beam->setPBins(new PartBinsCyc(MaxBinNum, BinCount, partInBin));
88 // the allowed maximal bin number is set to 100
89 //beam->setPBins(new PartBins(100));
90
91 this->setMode(mode);
92
93 } else {
94 if(beam->pbin_m->getLastemittedBin() < 2) {
95 *gmsg << "In this restart job, the multi-bunches mode is forcely set to AUTO mode." << endl;
97 } else {
98 *gmsg << "In this restart job, the multi-bunches mode is forcely set to FORCE mode." << endl
99 << "If the existing bunch number is less than the specified number of TURN, "
100 << "readin the phase space of STEP#0 from h5 file consecutively" << endl;
102 }
103 }
104}
105
106
108{
109 static IpplTimings::TimerRef saveBunchTimer = IpplTimings::getTimer("Save Bunch H5");
110 IpplTimings::startTimer(saveBunchTimer);
111 *gmsg << endl;
112 *gmsg << "* Store beam to H5 file for multibunch simulation ... ";
113
114 Ppos_t coord, momentum;
115 ParticleAttrib<double> mass, charge;
117
118 std::size_t localNum = beam->getLocalNum();
119
120 coord.create(localNum);
121 coord = beam->R;
122
123 momentum.create(localNum);
124 momentum = beam->P;
125
126 mass.create(localNum);
127 mass = beam->M;
128
129 charge.create(localNum);
130 charge = beam->Q;
131
132 porigin.create(localNum);
133 porigin = beam->POrigin;
134
135 std::map<std::string, double> additionalAttributes = {
136 std::make_pair("REFPR", 0.0),
137 std::make_pair("REFPT", 0.0),
138 std::make_pair("REFPZ", 0.0),
139 std::make_pair("REFR", 0.0),
140 std::make_pair("REFTHETA", 0.0),
141 std::make_pair("REFZ", 0.0),
142 std::make_pair("AZIMUTH", 0.0),
143 std::make_pair("ELEVATION", 0.0),
144 std::make_pair("B-ref_x", 0.0),
145 std::make_pair("B-ref_z", 0.0),
146 std::make_pair("B-ref_y", 0.0),
147 std::make_pair("E-ref_x", 0.0),
148 std::make_pair("E-ref_z", 0.0),
149 std::make_pair("E-ref_y", 0.0),
150 std::make_pair("B-head_x", 0.0),
151 std::make_pair("B-head_z", 0.0),
152 std::make_pair("B-head_y", 0.0),
153 std::make_pair("E-head_x", 0.0),
154 std::make_pair("E-head_z", 0.0),
155 std::make_pair("E-head_y", 0.0),
156 std::make_pair("B-tail_x", 0.0),
157 std::make_pair("B-tail_z", 0.0),
158 std::make_pair("B-tail_y", 0.0),
159 std::make_pair("E-tail_x", 0.0),
160 std::make_pair("E-tail_z", 0.0),
161 std::make_pair("E-tail_y", 0.0)
162 };
163
164 H5PartWrapperForPC h5wrapper(onebunch_m, H5_O_WRONLY);
165 h5wrapper.writeHeader();
166 h5wrapper.writeStep(beam, additionalAttributes);
167 h5wrapper.close();
168
169 *gmsg << "Done." << endl;
170 IpplTimings::stopTimer(saveBunchTimer);
171}
172
173
175 const PartData& ref)
176{
177 static IpplTimings::TimerRef readBunchTimer = IpplTimings::getTimer("Read Bunch H5");
178 IpplTimings::startTimer(readBunchTimer);
179 *gmsg << endl;
180 *gmsg << "* Read beam from H5 file for multibunch simulation ... ";
181
182 std::size_t localNum = beam->getLocalNum();
183
184 /*
185 * 2nd argument: 0 --> step zero is fine since the file has only this step
186 * 3rd argument: "" --> onebunch_m is used
187 * 4th argument: H5_O_RDONLY does not work with this constructor
188 */
189 H5PartWrapperForPC h5wrapper(onebunch_m, 0, "", H5_O_WRONLY);
190
191 size_t numParticles = h5wrapper.getNumParticles();
192
193 const int bunchNum = bunchCount_m - 1;
194
195 beam->setTotalNumPerBunch(numParticles, bunchNum);
196
197 if ( numParticles == 0 ) {
198 throw OpalException("MultiBunchHandler::readBunch()",
199 "No particles in file " + onebunch_m + ".");
200 }
201
202 size_t numParticlesPerNode = numParticles / Ippl::getNodes();
203
204 size_t firstParticle = numParticlesPerNode * Ippl::myNode();
205 size_t lastParticle = firstParticle + numParticlesPerNode - 1;
206 if (Ippl::myNode() == Ippl::getNodes() - 1)
207 lastParticle = numParticles - 1;
208
209 PAssert_LT(firstParticle, lastParticle +1);
210
211 numParticles = lastParticle - firstParticle + 1;
212
213 beam->setLocalNumPerBunch(numParticles, bunchNum);
214
215 //FIXME
216 std::unique_ptr<PartBunchBase<double, 3> > tmpBunch = nullptr;
217#ifdef ENABLE_AMR
218 AmrPartBunch* amrbunch_p = dynamic_cast<AmrPartBunch*>(beam);
219 if ( amrbunch_p != nullptr ) {
220 tmpBunch.reset(new AmrPartBunch(&ref,
221 amrbunch_p->getAmrParticleBase()));
222 } else
223#endif
224 tmpBunch.reset(new PartBunch(&ref));
225
226 tmpBunch->create(numParticles);
227
228 h5wrapper.readStep(tmpBunch.get(), firstParticle, lastParticle);
229 h5wrapper.close();
230
231 beam->create(numParticles);
232
233 for(size_t ii = 0; ii < numParticles; ++ ii, ++ localNum) {
234 beam->R[localNum] = tmpBunch->R[ii];
235 beam->P[localNum] = tmpBunch->P[ii];
236 beam->M[localNum] = tmpBunch->M[ii];
237 beam->Q[localNum] = tmpBunch->Q[ii];
238 beam->POrigin[localNum] = ParticleOrigin::REGULAR;
239 beam->Bin[localNum] = bunchNum;
240 beam->bunchNum[localNum] = bunchNum;
241 }
242
243 beam->boundp();
244
245 binfo_m.push_back(beaminfo_t(injection_m));
246
247 *gmsg << "Done." << endl;
248
249 IpplTimings::stopTimer(readBunchTimer);
250 return true;
251}
252
253
255 const PartData& ref,
256 bool& flagTransition)
257{
258 short result = 0;
259 if ((bunchCount_m == 1) && (mode_m == MultiBunchMode::AUTO) && (!flagTransition)) {
260
261 // we have still a single bunch
262 beam->setTotalNumPerBunch(beam->getTotalNum(), 0);
263 beam->setLocalNumPerBunch(beam->getLocalNum(), 0);
264
265 // If all of the following conditions are met, this code will be executed
266 // to check the distance between two neighboring bunches:
267 // 1. Only one bunch exists (bunchCount_m == 1)
268 // 2. We are in multi-bunch mode, AUTO sub-mode (mode_m == 2)
269 // 3. It has been a full revolution since the last check (stepsNextCheck)
270
271 *gmsg << "* MBM: Checking for automatically injecting new bunch ..." << endl;
272
273 //beam->R *= Vector_t(0.001); // mm --> m
274 beam->calcBeamParameters();
275 //beam->R *= Vector_t(1000.0); // m --> mm
276
277 Vector_t Rmean = beam->get_centroid(); // m
278
279 radiusThisTurn_m = std::hypot(Rmean[0],Rmean[1]);
280
281 Vector_t Rrms = beam->get_rrms(); // m
282
283 double XYrms = std::hypot(Rrms[0], Rrms[1]);
284
285 // If the distance between two neighboring bunches is less than 5 times of its 2D rms size
286 // start multi-bunch simulation, fill current phase space to initialR and initialP arrays
288 // since next turn, start multi-bunches
289 saveBunch(beam);
290 flagTransition = true;
291 }
292
293 *gmsg << "* MBM: RLastTurn = " << radiusLastTurn_m << " [m]" << endl;
294 *gmsg << "* MBM: RThisTurn = " << radiusThisTurn_m << " [m]" << endl;
295 *gmsg << "* MBM: XYrms = " << XYrms << " [m]" << endl;
296
298 result = 1;
299 }
300
301 else if (bunchCount_m < numBunch_m) {
302 // Matthias: SteptoLastInj was used in MtsTracker, removed by DW in GenericTracker
303
304 // If all of the following conditions are met, this code will be executed
305 // to read new bunch from hdf5 format file:
306 // 1. We are in multi-bunch mode (numBunch_m > 1)
307 // 2. It has been a full revolution since the last check
308 // 3. Number of existing bunches is less than the desired number of bunches
309 // 4. FORCE mode, or AUTO mode with flagTransition = true
310 // Note: restart from 1 < BunchCount < numBunch_m must be avoided.
311 *gmsg << "* MBM: Injecting a new bunch ..." << endl;
312
313 bunchCount_m++;
314
316
317 // read initial distribution from h5 file
318 switch ( mode_m ) {
321 readBunch(beam, ref);
322 updateParticleBins(beam);
324 break;
325 default:
326 throw OpalException("MultiBunchHandler::injectBunch()",
327 "We shouldn't be here in single bunch mode.");
328 }
329
331
332 *gmsg << "* MBM: Bunch " << bunchCount_m
333 << " injected, total particle number = "
334 << beam->getTotalNum() << endl;
335 result = 2;
336 }
337 return result;
338}
339
340
342 if (bunchCount_m < 2)
343 return;
344
345 static IpplTimings::TimerRef binningTimer = IpplTimings::getTimer("Particle Binning");
346 IpplTimings::startTimer(binningTimer);
347 switch ( binning_m ) {
349 beam->resetPartBinID2(eta_m);
350 break;
352 beam->resetPartBinBunch();
353 break;
354 default:
355 beam->resetPartBinID2(eta_m);
356 }
357 IpplTimings::stopTimer(binningTimer);
358}
359
360
361void MultiBunchHandler::setMode(const std::string& mbmode) {
362 if ( mbmode.compare("FORCE") == 0 ) {
363 *gmsg << "FORCE mode: The multi bunches will be injected consecutively" << endl
364 << " after each revolution, until get \"TURNS\" bunches." << endl;
366 } else if ( mbmode.compare("AUTO") == 0 ) {
367 *gmsg << "AUTO mode: The multi bunches will be injected only when the" << endl
368 << " distance between two neighboring bunches is below" << endl
369 << " the limitation. The control parameter is set to "
370 << coeffDBunches_m << endl;
372 }
373}
374
375
376void MultiBunchHandler::setBinning(std::string binning) {
377
378 if ( binning.compare("BUNCH_BINNING") == 0 ) {
379 *gmsg << "Use 'BUNCH_BINNING' injection for binnning." << endl;
381 } else if ( binning.compare("GAMMA_BINNING") == 0 ) {
382 *gmsg << "Use 'GAMMA_BINNING' for binning." << endl;
384 }
385}
386
387
388void MultiBunchHandler::setRadiusTurns(const double& radius) {
390 return;
391
392 radiusLastTurn_m = radius;
394
395 if (OpalData::getInstance()->inRestartRun()) {
396 *gmsg << "Radial position at restart position = ";
397 } else {
398 *gmsg << "Initial radial position = ";
399 }
400 // New OPAL 2.0: Init in m -DW
401 *gmsg << radiusThisTurn_m << " m" << endl;
402}
403
404
406 short bunchNr)
407{
408 if ( !OpalData::getInstance()->isInOPALCyclMode() ) {
409 return false;
410 }
411
412 const unsigned long localNum = beam->getLocalNum();
413
414 long int bunchTotalNum = 0;
415 unsigned long bunchLocalNum = 0;
416
417 /* container:
418 *
419 * ekin, <x>, <y>, <z>, <p_x>, <p_y>, <p_z>,
420 * <x^2>, <y^2>, <z^2>, <p_x^2>, <p_y^2>, <p_z^2>,
421 * <xp_x>, <y_py>, <zp_z>,
422 * <x^3>, <y^3>, <z^3>, <x^4>, <y^4>, <z^4>
423 */
424 const unsigned int dim = PartBunchBase<double, 3>::Dimension;
425 std::vector<double> local(7 * dim + 1);
426
427 beaminfo_t& binfo = getBunchInfo(bunchNr);
428
429 for(unsigned long k = 0; k < localNum; ++k) {
430 if ( beam->bunchNum[k] != bunchNr ) { //|| ID[k] == 0 ) {
431 continue;
432 }
433
434 ++bunchTotalNum;
435 ++bunchLocalNum;
436
437 // ekin
438 local[0] += std::sqrt(dot(beam->P[k], beam->P[k]) + 1.0);
439
440 for (unsigned int i = 0; i < dim; ++i) {
441
442 double r = beam->R[k](i);
443 double p = beam->P[k](i);
444
445 // <x>, <y>, <z>
446 local[i + 1] += r;
447
448 // <p_x>, <p_y, <p_z>
449 local[i + dim + 1] += p;
450
451 // <x^2>, <y^2>, <z^2>
452 double r2 = r * r;
453 local[i + 2 * dim + 1] += r2;
454
455 // <p_x^2>, <p_y^2>, <p_z^2>
456 local[i + 3 * dim + 1] += p * p;
457
458 // <xp_x>, <y_py>, <zp_z>
459 local[i + 4 * dim + 1] += r * p;
460
461 // <x^3>, <y^3>, <z^3>
462 local[i + 5 * dim + 1] += r2 * r;
463
464 // <x^4>, <y^4>, <z^4>
465 local[i + 6 * dim + 1] += r2 * r2;
466 }
467 }
468
469 // inefficient
470 allreduce(bunchTotalNum, 1, std::plus<long int>());
471
472 // here we also update the number of particles of *this* bunch
473 if (bunchNr >= (short)beam->getNumBunch())
474 throw OpalException("MultiBunchHandler::calcBunchBeamParameters()",
475 "Bunch number " + std::to_string(bunchNr) +
476 " exceeds bunch index " + std::to_string(beam->getNumBunch() - 1));
477
478 beam->setTotalNumPerBunch(bunchTotalNum, bunchNr);
479 beam->setLocalNumPerBunch(bunchLocalNum, bunchNr);
480
481 if ( bunchTotalNum == 0 )
482 return false;
483
484 // ekin
485 const double m0 = beam->getM() * Units::eV2MeV;
486 local[0] -= bunchLocalNum;
487 local[0] *= m0;
488
489 allreduce(local.data(), local.size(), std::plus<double>());
490
491 double invN = 1.0 / double(bunchTotalNum);
492 binfo.ekin = local[0] * invN;
493
494 binfo.time = beam->getT() * Units::s2ns;
495 binfo.nParticles = bunchTotalNum;
496
497 for (unsigned int i = 0; i < dim; ++i) {
498
499 double w = local[i + 1] * invN;
500 double pw = local[i + dim + 1] * invN;
501 double w2 = local[i + 2 * dim + 1] * invN;
502 double pw2 = local[i + 3 * dim + 1] * invN;
503 double wpw = local[i + 4 * dim + 1] * invN;
504 double w3 = local[i + 5 * dim + 1] * invN;
505 double w4 = local[i + 6 * dim + 1] * invN;
506
507 // <x>, <y>, <z>
508 binfo.mean[i] = w;
509
510 // central: <p_w^2> - <p_w>^2 (w = x, y, z)
511 binfo.prms[i] = pw2 - pw * pw;
512 if ( binfo.prms[i] < 0 ) {
513 binfo.prms[i] = 0.0;
514 }
515
516 // central: <wp_w> - <w><p_w>
517 wpw = wpw - w * pw;
518
519 // central: <w^2> - <w>^2 (w = x, y, z)
520 binfo.rrms[i] = w2 - w * w;
521
522 // central: normalized emittance
523 binfo.emit[i] = (binfo.rrms[i] * binfo.prms[i] - wpw * wpw);
524 binfo.emit[i] = std::sqrt(std::max(binfo.emit[i], 0.0));
525
526 // central: <w^4> - 4 * <w> * <w^3> + 6 * <w>^2 * <w^2> - 3 * <w>^4
527 double tmp = w4
528 - 4.0 * w * w3
529 + 6.0 * w * w * w2
530 - 3.0 * w * w * w * w;
531 binfo.halo[i] = tmp / ( binfo.rrms[i] * binfo.rrms[i] );
532
533 // central: sqrt(<w^2> - <w>^2) (w = x, y, z)
534 binfo.rrms[i] = std::sqrt(binfo.rrms[i]);
535
536 // central: sqrt(<p_w^2> - <p_w>^2)
537 binfo.prms[i] = std::sqrt(binfo.prms[i]);
538
539 // central: rms correlation --> (<wp_w> - <w><p_w>) / sqrt(<w^2> * <p_w^2>)
540 double denom = 1.0 / (binfo.rrms[i] * binfo.prms[i]);
541 binfo.correlation[i] = (std::isfinite(denom)) ? wpw * denom : 0.0;
542 }
543
544 double tmp = 1.0 / std::pow(binfo.ekin / m0 + 1.0, 2.0);
545 binfo.dEkin = binfo.prms[1] * m0 * std::sqrt(1.0 - tmp);
546
547 return true;
548}
549
550
551void MultiBunchHandler::updateTime(const double& dt) {
552 for (short b = 0; b < bunchCount_m; ++b) {
553 binfo_m[b].time += dt;
554 }
555}
556
557
558void MultiBunchHandler::updatePathLength(const std::vector<double>& lpaths) {
559 PAssert_EQ(bunchCount_m, (short)lpaths.size() - 1);
560 for (short b = 0; b < bunchCount_m; ++b) {
561 binfo_m[b].pathlength += lpaths[b];
562 }
563}
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition: Vector3D.cpp:118
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
Inform * gmsg
Definition: Main.cpp:61
void allreduce(const T *input, T *output, int count, Op op)
Definition: GlobalComm.hpp:510
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:84
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
#define PAssert_LT(a, b)
Definition: PAssert.h:106
#define PAssert_EQ(a, b)
Definition: PAssert.h:104
#define PAssert_GT(a, b)
Definition: PAssert.h:108
constexpr double eV2MeV
Definition: Units.h:77
constexpr double s2ns
Definition: Units.h:44
ParticlePos_t & R
ParticleAttrib< int > Bin
bool resetPartBinID2(const double eta)
reset Bin[] for each particle according to the method given in paper PAST-AB(064402) by G....
void setNumBunch(short n)
size_t getLocalNum() const
ParticleAttrib< double > M
size_t getTotalNum() const
bool resetPartBinBunch()
ParticleAttrib< Vector_t > P
void setLocalNumPerBunch(size_t numpart, short n)
ParticleAttrib< ParticleOrigin > POrigin
Vector_t get_rrms() const
ParticleAttrib< double > Q
void calcBeamParameters()
PartBins * pbin_m
short getNumBunch() const
Vector_t get_centroid() const
ParticleAttrib< short > bunchNum
void setTotalNumPerBunch(size_t numpart, short n)
void setPBins(PartBins *pbin)
virtual void boundp()
void create(size_t M)
double getM() const
double getT() const
The global OPAL structure.
Definition: OpalData.h:49
static OpalData * getInstance()
Definition: OpalData.cpp:196
void saveBunch(PartBunchBase< double, 3 > *beam)
bool calcBunchBeamParameters(PartBunchBase< double, 3 > *beam, short bunchNr)
MultiBunchHandler(PartBunchBase< double, 3 > *beam, const int &numBunch, const double &eta, const double &para, const std::string &mode, const std::string &binning)
MultiBunchBinning binning_m
beaminfo_t & getBunchInfo(short bunchNr)
void setMode(const std::string &mbmode)
set the working sub-mode for multi-bunch mode: "FORCE" or "AUTO"
void updateTime(const double &dt)
MultiBunchMode mode_m
void setRadiusTurns(const double &radius)
short numBunch_m
The number of bunches specified in TURNS of RUN command.
bool readBunch(PartBunchBase< double, 3 > *beam, const PartData &ref)
void setBinning(std::string binning)
void updatePathLength(const std::vector< double > &lpaths)
short injectBunch(PartBunchBase< double, 3 > *beam, const PartData &ref, bool &flagTransition)
std::vector< beaminfo_t > binfo_m
void updateParticleBins(PartBunchBase< double, 3 > *beam)
pbase_t * getAmrParticleBase()
int getLastemittedBin()
Definition: PartBins.h:136
Particle reference data.
Definition: PartData.h:35
size_t getNumParticles() const
virtual void writeStep(PartBunchBase< double, 3 > *, const std::map< std::string, double > &additionalStepAttributes)
virtual void writeHeader()
virtual void readStep(PartBunchBase< double, 3 > *, h5_ssize_t firstParticle, h5_ssize_t lastParticle)
The base class for all OPAL exceptions.
Definition: OpalException.h:28
virtual void create(size_t)
void barrier(void)
Definition: Inform.h:42
static int getNodes()
Definition: IpplInfo.cpp:670
static int myNode()
Definition: IpplInfo.cpp:691
static Communicate * Comm
Definition: IpplInfo.h:84
Timing::TimerRef TimerRef
Definition: IpplTimings.h:176
static TimerRef getTimer(const char *nm)
Definition: IpplTimings.h:182
static void stopTimer(TimerRef t)
Definition: IpplTimings.h:192
static void startTimer(TimerRef t)
Definition: IpplTimings.h:187