OPALX (Object Oriented Parallel Accelerator Library for Exascal) MINIorX
OPALX
TrackRun.cpp
Go to the documentation of this file.
1// Class TrackRun
2// The RUN command.
3//
4// Copyright (c) 200x - 2022, Paul Scherrer Institut, Villigen PSI, Switzerland
5// All rights reserved
6//
7// This file is part of OPAL.
8//
9// OPAL is free software: you can redistribute it and/or modify
10// it under the terms of the GNU General Public License as published by
11// the Free Software Foundation, either version 3 of the License, or
12// (at your option) any later version.
13//
14// You should have received a copy of the GNU General Public License
15// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
16//
17#include "Track/TrackRun.h"
18
20
22
24
26
27#include "Beamlines/TBeamline.h"
28
29#include "BasicActions/Option.h"
30
32
34
36
38
39#include "Physics/Physics.h"
40#include "Physics/Units.h"
41
42#include "Track/Track.h"
43
45
46#include "Structure/Beam.h"
48#include "Structure/DataSink.h"
51
52#include "OPALconfig.h"
53#include "changes.h"
54
55#include <boost/assign.hpp>
56
57#include <cmath>
58#include <fstream>
59#include <iomanip>
60
61#include <unistd.h>
62
63extern Inform* gmsg;
64
65namespace TRACKRUN {
66 // The attributes of class TrackRun.
67 enum {
68 METHOD, // Tracking method to use.
69 TURNS, // The number of turns to be tracked, we keep that for the moment
70 BEAM, // The beam to track
71 FIELDSOLVER, // The field solver attached
72 BOUNDARYGEOMETRY, // The boundary geometry
73 DISTRIBUTION, // The particle distribution
74 TRACKBACK, // In case we run the beam backwards
76 };
77} // namespace TRACKRUN
78
79const boost::bimap<TrackRun::RunMethod, std::string> TrackRun::stringMethod_s =
80 boost::assign::list_of<const boost::bimap<TrackRun::RunMethod, std::string>::relation>(
81 RunMethod::PARALLEL, "PARALLEL");
82
84 : Action(
85 TRACKRUN::SIZE, "RUN",
86 "The \"RUN\" sub-command tracks the defined particles through "
87 "the given lattice."),
88 itsTracker_m(nullptr),
89 dist_m(nullptr),
90 fs_m(nullptr),
91 ds_m(nullptr),
92 phaseSpaceSink_m(nullptr),
93 isFollowupTrack_m(false),
95 macromass_m(0.0),
96 macrocharge_m(0.0){
97
99 "METHOD", "Name of tracking algorithm to use.", {"PARALLEL"});
100
102 "TURNS",
103 "Number of turns to be tracked; Number of neighboring bunches to be tracked in cyclotron.",
104 1.0);
105
106 itsAttr[TRACKRUN::BEAM] = Attributes::makeString("BEAM", "Name of beam.");
107
109 Attributes::makeString("FIELDSOLVER", "Field solver to be used.");
110
112 "BOUNDARYGEOMETRY", "Boundary geometry to be used NONE (default).", "NONE");
113
115 Attributes::makeStringArray("DISTRIBUTION", "List of particle distributions to be used.");
116
118 Attributes::makeBool("TRACKBACK", "Track in reverse direction, default: false.", false);
119
122}
123
124TrackRun::TrackRun(const std::string& name, TrackRun* parent)
125 : Action(name, parent),
126 itsTracker_m(nullptr),
127 dist_m(nullptr),
128 fs_m(nullptr),
129 ds_m(nullptr),
130 phaseSpaceSink_m(nullptr),
131 isFollowupTrack_m(false),
133 macromass_m(0.0),
134 macrocharge_m(0.0){
135 /*
136 the opal dictionary
137 */
138
140
141 const Vector_t<int, 3> nr(8);
142
143 ippl::NDIndex<3> domain;
144 for (unsigned i = 0; i < 3; i++) {
145 domain[i] = ippl::Index(nr[i]);
146 }
147
148 std::array<bool, 3> isParallel;
149
150 for (unsigned d = 0; d < 3; ++d) {
151 isParallel[d] = true;
152 }
153}
154
158
159TrackRun* TrackRun::clone(const std::string& name) {
160 return new TrackRun(name, this);
161}
162
164
165 const int currentVersion = ((OPAL_VERSION_MAJOR * 100) + OPAL_VERSION_MINOR) * 100;
166
167 if (Options::version < currentVersion) {
168 unsigned int fileVersion = Options::version / 100;
169 bool newerChanges = false;
170 for (auto it = Versions::changes.begin(); it != Versions::changes.end(); ++it) {
171 if (it->first > fileVersion) {
172 newerChanges = true;
173 break;
174 }
175 }
176 if (newerChanges) {
177 Inform errorMsg("Error");
178 errorMsg << "\n******************** V E R S I O N M I S M A T C H "
179 "***********************\n"
180 << endl;
181 for (auto it = Versions::changes.begin(); it != Versions::changes.end(); ++it) {
182 if (it->first > fileVersion) {
183 errorMsg << it->second << endl;
184 }
185 }
186 errorMsg << "\n"
187 << "* Make sure you do understand these changes and adjust your input file \n"
188 << "* accordingly. Then add\n"
189 << "* OPTION, VERSION = " << currentVersion << ";\n"
190 << "* to your input file. " << endl;
191 errorMsg << "\n************************************************************************"
192 "****\n"
193 << endl;
194 throw OpalException("TrackRun::execute", "Version mismatch");
195 }
196 }
197
198 isFollowupTrack_m = opal_m->hasBunchAllocated();
200 throw OpalException(
201 "TrackRun::execute", "\"DISTRIBUTION\" must be set in \"RUN\" command.");
202 }
204 throw OpalException("TrackRun::execute", "\"FIELDSOLVER\" must be set in \"RUN\" command.");
205 }
206 if (!itsAttr[TRACKRUN::BEAM]) {
207 throw OpalException("TrackRun::execute", "\"BEAM\" must be set in \"RUN\" command.");
208 }
209
211
212 if (isFollowupTrack_m) {
213 Track::block->bunch->setLocalTrackStep(0);
214 }
215
216 /*
217
218 Gather all data in order to initialize the particle bunch_m
219
220 */
221
222 /*
223 * Distribution(s) can be set via a single distribution or a list
224 * (array) of distributions. If an array is defined the first in the
225 * list is treated as the primary distribution. All others are added to
226 * it to create the full distribution.
227 */
228 std::vector<std::string> distributionArray =
230 const size_t numberOfDistributions = distributionArray.size();
231
232 *gmsg << "* Number of distributions " << numberOfDistributions << endl;
233
234
235 // \todo here we can loop over several distributions
236
237 dist_m = std::shared_ptr<Distribution>(Distribution::find(distributionArray[0]));
238 dist_m->setDistType();
239 *gmsg << *dist_m << endl;
240
242 *gmsg << *fs_m << endl;
243
244
246 *gmsg << *beam << endl;
247
250
251 /*
252 Here we can allocate the bunch
253
254 */
255
256 // There's a change of units for particle mass that seems strange -> gives consistent Kinetic Energy
257 bunch_m = std::make_shared<bunch_type>(macrocharge_m,
258 beam->getMass()*1e9*Units::eV2MeV,
259 beam->getNumberOfParticles(), 10, 1.0, "LF2", dist_m, fs_m);
260 bunch_m->setT(0.0);
261 bunch_m->setBeamFrequency(beam->getFrequency() * Units::MHz2Hz);
262
263 double cc = 1.0 / (4 * Physics::pi * Physics::epsilon_0);
264 bunch_m->setCouplingConstant(cc);
265
267
268 // Get algorithm to use.
269 setRunMethod();
270
271 switch (method_m) {
272 case RunMethod::PARALLEL: {
273 break;
274 }
275 default: {
276 throw OpalException("TrackRun::execute", "Unknown \"METHOD\" for the \"RUN\" command");
277 }
278 }
279
280
281 /*
282 \todo Mohsen here we need to create the particles based on dist_m
283
284
285 We have 3 main modes: emit particles, inject particles or get particles from a restart run
286
287 Lets start with the inject particles.
288
289
290 Note: in the pre_run (bunch_m) I disables the particle generation.
291
292 */
293
294 //double deltaP = Attributes::getReal(itsAttr[Distribution::OFFSETP]);
295 //if (inputMoUnits_m == InputMomentumUnits::EVOVERC) {
296 // deltaP = Util::convertMomentumEVoverCToBetaGamma(deltaP, beam->getM());
297 //}
298
299 if (ippl::Comm->rank() == 0) {
300 long number_of_processors = sysconf(_SC_NPROCESSORS_ONLN);
301 *gmsg << "number_of_processors " << number_of_processors << endl;
302
303// *gmsg << "omp_get_max_threads() " << omp_get_max_threads() << endl;
304
305 int world_size;
306 MPI_Comm_size( MPI_COMM_WORLD, &world_size );
307 *gmsg << "MPI_Comm_size " << world_size << endl;
308 }
309
310 static IpplTimings::TimerRef samplingTime = IpplTimings::getTimer("samplingTime");
311 IpplTimings::startTimer(samplingTime);
312
313 // set distribution type
314 dist_m->setDist();
315 dist_m->setAvrgPz( beam->getMomentum()/beam->getMass() );
316
317 // sample particles
318 auto pc = bunch_m->getParticleContainer();
319 auto fc = bunch_m->getFieldContainer();
320 size_type Np = beam->getNumberOfParticles();
322
323 std::shared_ptr<Distribution> opalDist(dist_m);
324
325 switch (opalDist->getType()){
327 sampler_m = std::make_shared<Gaussian>(pc, fc, opalDist);
328 break;
330 sampler_m = std::make_shared<MultiVariateGaussian>(pc, fc, opalDist);
331 break;
333 sampler_m = std::make_shared<FlatTop>(pc, fc, opalDist);
334 break;
335 default:
336 throw OpalException("Distribution::create", "Unknown \"TYPE\" of \"DISTRIBUTION\"");
337 }
338
339 *gmsg << "* About to create particles ..." << endl;
340
341 static IpplTimings::TimerRef GenParticlesTimer = IpplTimings::getTimer("GenParticles");
342 IpplTimings::startTimer(GenParticlesTimer);
343
344 sampler_m->generateParticles(Np, nr);
345
346 IpplTimings::stopTimer(GenParticlesTimer);
347
348 *gmsg << "* Particle creation done" << endl;
349
350 IpplTimings::stopTimer(samplingTime);
351
352 /*
353 reset the fieldsolver with correct hr_m
354 based on the distribution
355 */
356
357 bunch_m->setCharge();
358 bunch_m->setMass();
359 bunch_m->bunchUpdate();
360 bunch_m->print(*gmsg);
361 initDataSink();
362
363 /*
364 if (!isFollowupTrack_m) {
365 *gmsg << std::scientific;
366 *gmsg << *dist_m << endl;
367 }
368 */
369
370 if (bunch_m->getTotalNum() > 0) {
371 double spos = Track::block->zstart;
372 auto& zstop = Track::block->zstop;
373 auto it = Track::block->dT.begin();
374
375 unsigned int i = 0;
376 while (i + 1 < zstop.size() && zstop[i + 1] < spos) {
377 ++i;
378 ++it;
379 }
380
381 bunch_m->setdT(*it);
382 } else {
383 Track::block->zstart = 0.0;
384 }
385
386 /* \todo this is also not unsed in the master.
387 This needs to come back as soon as we have RF
388
389 findPhasesForMaxEnergy();
390
391 */
392
394 *Track::block->use->fetchLine(), bunch_m.get(), *ds_m, Track::block->reference, false,
396 Track::block->zstart, Track::block->zstop, Track::block->dT);
397
398 itsTracker_m->execute();
399
400 /*
401 opal_m->setRestartRun(false);
402
403 opal_m->bunchIsAllocated();
404 */
405
407}
408
411 throw OpalException(
412 "TrackRun::setRunMethod", "The attribute \"METHOD\" isn't set for the \"RUN\" command");
413 } else {
415 if (it != stringMethod_s.right.end()) {
416 method_m = it->second;
417 }
418 }
419}
420
421std::string TrackRun::getRunMethodName() const {
422 return stringMethod_s.left.at(method_m);
423}
424
425/*
426
427void TrackRun::setupFieldsolver() {
428 if (fs_m->getFieldSolverType() != FieldSolverType::NONE) {
429 size_t numGridPoints =
430 fs_m->getMX() * fs_m->getMY() * fs_m->getMZ(); // total number of gridpoints
431 Beam* beam = Beam::find(Attributes::getString(itsAttr[TRACKRUN::BEAM]));
432 size_t numParticles = beam->getNumberOfParticles();
433
434 if (!opal->inRestartRun() && numParticles < numGridPoints) {
435 throw OpalException(
436 "TrackRun::setupFieldsolver()",
437 "The number of simulation particles (" + std::to_string(numParticles) + ") \n"
438 + "is smaller than the number of gridpoints (" + std::to_string(numGridPoints)
439 + ").\n"
440 + "Please increase the number of particles or reduce the size of the mesh.\n");
441 }
442
443 OpalData::getInstance()->addProblemCharacteristicValue("MX", fs_m->getMX());
444 OpalData::getInstance()->addProblemCharacteristicValue("MY", fs_m->getMY());
445 OpalData::getInstance()->addProblemCharacteristicValue("MT", fs_m->getMZ());
446 }
447// fs_m->initCartesianFields();
448// Track::block->bunch->setSolver(fs_m);
449
450if (fs_m->hasPeriodicZ()) {
451 Track::block->bunch->setBCForDCBeam();
452} else {
453 Track::block->bunch->setBCAllOpen();
454}
455
456}
457*/
458
460 if (opal_m->inRestartRun()) {
462 opal_m->getInputBasename() + std::string(".h5"), opal_m->getRestartStep(),
463 OpalData::getInstance()->getRestartFileName(), H5_O_WRONLY);
464 } else if (isFollowupTrack_m) {
466 opal_m->getInputBasename() + std::string(".h5"), -1,
467 opal_m->getInputBasename() + std::string(".h5"), H5_O_WRONLY);
468 } else {
470 new H5PartWrapperForPT(opal_m->getInputBasename() + std::string(".h5"), H5_O_WRONLY);
471 }
472
473 if (!opal_m->inRestartRun()) {
474 if (!opal_m->hasDataSinkAllocated()) {
475 opal_m->setDataSink(new DataSink(phaseSpaceSink_m, false));
476 } else {
477 ds_m = opal_m->getDataSink();
478 ds_m->changeH5Wrapper(phaseSpaceSink_m);
479 }
480 } else {
481 opal_m->setDataSink(new DataSink(phaseSpaceSink_m, true));
482 }
483 ds_m = opal_m->getDataSink();
484}
485
488 // Ask the dictionary if BoundaryGeometry is allocated.
489 // If it is allocated use the allocated BoundaryGeometry
490 if (!OpalData::getInstance()->hasGlobalGeometry()) {
491 const std::string geomDescriptor =
493 BoundaryGeometry* bg = BoundaryGeometry::find(geomDescriptor)->clone(geomDescriptor);
495 }
496 }
497}
498
499Inform& TrackRun::print(Inform& os) const {
500 os << endl;
501 os << "* ************* T R A C K R U N *************************************************** "
502 << endl;
503 if (!isFollowupTrack_m) {
504 os << "* Selected Tracking Method == " << getRunMethodName() << ", NEW TRACK" << '\n'
505 << "* "
506 "********************************************************************************** "
507 << '\n';
508 } else {
509 os << "* Selected Tracking Method == " << getRunMethodName() << ", FOLLOWUP TRACK" << '\n'
510 << "* "
511 "********************************************************************************** "
512 << '\n';
513 }
514 os << "* Phase space dump frequency = " << Options::psDumpFreq << '\n'
515 << "* Statistics dump frequency = " << Options::statDumpFreq << " w.r.t. the time step."
516 << '\n'
517 << "* DT = " << Track::block->dT.front() << " [s]\n"
518 << "* MAXSTEPS = " << Track::block->localTimeSteps.front() << '\n'
519 << "* Mass of simulation particle = " << Beam::find(Attributes::getString(itsAttr[TRACKRUN::BEAM]))->getChargePerParticle() << " [GeV/c^2]" << '\n'
520 << "* Charge of simulation particle = " << Beam::find(Attributes::getString(itsAttr[TRACKRUN::BEAM]))->getMassPerParticle() << " [C]" << '\n';
521 os << "* ********************************************************************************** ";
522 return os;
523}
#define OPAL_VERSION_MINOR
Definition OPALconfig.h:7
#define OPAL_VERSION_MAJOR
Definition OPALconfig.h:6
Inform * gmsg
Definition changes.cpp:7
@ SIZE
Definition IndexMap.cpp:173
ippl::Vector< T, Dim > Vector_t
PartBunch< T, Dim >::ConstIterator begin(PartBunch< T, Dim > const &bunch)
Defines the FlatTop class used for sampling emitting particles.
const int nr
ippl::detail::size_type size_type
Attribute makeBool(const std::string &name, const std::string &help)
Make logical attribute.
Attribute makeStringArray(const std::string &name, const std::string &help)
Create a string array attribute.
Attribute makePredefinedString(const std::string &name, const std::string &help, const std::initializer_list< std::string > &predefinedStrings)
Make predefined string attribute.
Attribute makeReal(const std::string &name, const std::string &help)
Make real attribute.
bool getBool(const Attribute &attr)
Return logical value.
std::vector< std::string > getStringArray(const Attribute &attr)
Get string array value.
std::string getString(const Attribute &attr)
Get string value.
Attribute makeString(const std::string &name, const std::string &help)
Make string attribute.
std::map< unsigned int, std::string > changes
Definition changes.cpp:10
constexpr double epsilon_0
The permittivity of vacuum in As/Vm.
Definition Physics.h:51
constexpr double pi
The value of.
Definition Physics.h:30
constexpr double MHz2Hz
Definition Units.h:113
constexpr double eV2MeV
Definition Units.h:77
@ DISTRIBUTION
Definition TrackRun.cpp:73
@ BOUNDARYGEOMETRY
Definition TrackRun.cpp:72
@ FIELDSOLVER
Definition TrackRun.cpp:71
int psDumpFreq
The frequency to dump the phase space, i.e.dump data when steppsDumpFreq==0.
Definition Options.cpp:39
int version
opal version of input file
Definition Options.cpp:97
int statDumpFreq
The frequency to dump statistical values, e.e. dump data when stepstatDumpFreq==0.
Definition Options.cpp:41
Action(int size, const char *name, const char *help)
Constructor for exemplars.
Definition Action.cpp:54
void registerOwnership(const AttributeHandler::OwnerType &itsClass) const
Definition Object.cpp:189
std::vector< Attribute > itsAttr
The object attributes.
Definition Object.h:216
static OpalData * getInstance()
Definition OpalData.cpp:195
void setInOPALTMode()
Definition OpalData.cpp:287
void setGlobalGeometry(BoundaryGeometry *bg)
Definition OpalData.cpp:455
static Distribution * find(const std::string &name)
Definition Beam.h:31
double getChargePerParticle() const
Charge per macro particle in C.
Definition Beam.cpp:182
double getMomentum() const
Definition Beam.cpp:170
static Beam * find(const std::string &name)
Find named BEAM.
Definition Beam.cpp:132
double getFrequency() const
Return the beam frequency in MHz.
Definition Beam.cpp:178
size_t getNumberOfParticles() const
Return the number of (macro)particles.
Definition Beam.cpp:142
double getMassPerParticle() const
Mass per macro particle in GeV/c^2.
Definition Beam.cpp:187
double getMass() const
Return Particle's rest mass in GeV.
Definition Beam.cpp:166
static BoundaryGeometry * find(const std::string &name)
virtual BoundaryGeometry * clone(const std::string &name)
Return a clone.
static FieldSolverCmd * find(const std::string &name)
Find named FieldSolverCmd.
static Track * block
The block of track data.
Definition Track.h:55
DataSink * ds_m
Definition TrackRun.h:86
RunMethod method_m
Definition TrackRun.h:104
void setupBoundaryGeometry()
Definition TrackRun.cpp:486
std::shared_ptr< SamplingBase > sampler_m
Definition TrackRun.h:82
H5PartWrapper * phaseSpaceSink_m
Definition TrackRun.h:88
virtual void execute()
Execute the command.
Definition TrackRun.cpp:163
void initDataSink()
Definition TrackRun.cpp:459
bool isFollowupTrack_m
Definition TrackRun.h:100
void setRunMethod()
Definition TrackRun.cpp:409
virtual ~TrackRun()
Definition TrackRun.cpp:155
std::shared_ptr< FieldSolverCmd > fs_m
Definition TrackRun.h:84
std::shared_ptr< Distribution > dist_m
Definition TrackRun.h:78
TrackRun()
Exemplar constructor.
Definition TrackRun.cpp:83
double macromass_m
Definition TrackRun.h:108
OpalData * opal_m
Definition TrackRun.h:90
Tracker * itsTracker_m
Definition TrackRun.h:76
std::shared_ptr< bunch_type > bunch_m
Definition TrackRun.h:98
virtual TrackRun * clone(const std::string &name)
Make clone.
Definition TrackRun.cpp:159
std::string getRunMethodName() const
Definition TrackRun.cpp:421
double macrocharge_m
Definition TrackRun.h:109
Inform & print(Inform &os) const
Definition TrackRun.cpp:499
static const boost::bimap< RunMethod, std::string > stringMethod_s
Definition TrackRun.h:105
The base class for all OPAL exceptions.