OPALX (Object Oriented Parallel Accelerator Library for Exascal) MINIorX
OPALX
ParallelTracker.h
Go to the documentation of this file.
1//
2// Class ParallelTracker
3// OPAL-T tracker.
4// The visitor class for tracking particles with time as independent
5// variable.
6//
7// Copyright (c) 200x - 2014, Christof Kraus, Paul Scherrer Institut, Villigen PSI, Switzerland
8// 2015 - 2016, Christof Metzger-Kraus, Helmholtz-Zentrum Berlin, Germany
9// 2017 - 2020, Christof Metzger-Kraus
10// All rights reserved
11//
12// This file is part of OPAL.
13//
14// OPAL is free software: you can redistribute it and/or modify
15// it under the terms of the GNU General Public License as published by
16// the Free Software Foundation, either version 3 of the License, or
17// (at your option) any later version.
18//
19// You should have received a copy of the GNU General Public License
20// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
21//
22#ifndef OPAL_ParallelTracker_HH
23#define OPAL_ParallelTracker_HH
24
26#include "Algorithms/Tracker.h"
28#include "Structure/DataSink.h"
29
30#include "BasicActions/Option.h"
31#include "Utilities/Options.h"
32
33#include "Physics/Physics.h"
34
35#include "Algorithms/IndexMap.h"
37
38#include "AbsBeamline/Drift.h"
40#include "AbsBeamline/Marker.h"
44#include "AbsBeamline/Ring.h"
48#include "Beamlines/Beamline.h"
50
51#include <list>
52#include <memory>
53#include <tuple>
54#include <vector>
55
56class ParticleMatterInteractionHandler;
57class PluginElement;
58
59class ParallelTracker : public Tracker {
60
62
64
65 /*
66 Ring specifics
67 */
68
69 // we store a pointer explicitly to the Ring
71
73
75
77
78 WakeFunction* wakeFunction_m;
79
81
83 double zstart_m;
84
90
92
93 // This variable controls the minimal number of steps of emission (using bins)
94 // before we can merge the bins
96
97 // this variable controls the minimal number of steps until we repartition the particles
98 unsigned long long repartFreq_m;
99
100 unsigned int emissionSteps_m;
101
103
104 IpplTimings::TimerRef timeIntegrationTimer1_m;
105 IpplTimings::TimerRef timeIntegrationTimer2_m;
106 IpplTimings::TimerRef fieldEvaluationTimer_m;
107 IpplTimings::TimerRef WakeFieldTimer_m;
108 IpplTimings::TimerRef PluginElemTimer_m;
109 IpplTimings::TimerRef BinRepartTimer_m;
110 IpplTimings::TimerRef OrbThreader_m;
111
112 std::set<ParticleMatterInteractionHandler*> activeParticleMatterInteractionHandlers_m;
114
115public:
116 typedef std::vector<double> dvector_t;
117 typedef std::vector<int> ivector_t;
118 typedef std::pair<double[8], Component*> element_pair;
119 typedef std::pair<ElementType, element_pair> type_pair;
120 typedef std::list<type_pair*> beamline_list;
121
123 // The beam line to be tracked is "bl".
124 // The particle reference data are taken from "data".
125 // The particle bunch tracked is initially empty.
126 // If [b]revBeam[/b] is true, the beam runs from s = C to s = 0.
127 // If [b]revTrack[/b] is true, we track against the beam.
128 explicit ParallelTracker(const Beamline& bl, const PartData& data, bool revBeam, bool revTrack);
129
131 // The beam line to be tracked is "bl".
132 // The particle reference data are taken from "data".
133 // The particle bunch tracked is taken from [b]bunch[/b].
134 // If [b]revBeam[/b] is true, the beam runs from s = C to s = 0.
135 // If [b]revTrack[/b] is true, we track against the beam.
136 explicit ParallelTracker(
137 const Beamline& bl, PartBunch_t* bunch, DataSink& ds, const PartData& data, bool revBeam,
138 bool revTrack, const std::vector<unsigned long long>& maxSTEPS, double zstart,
139 const std::vector<double>& zstop, const std::vector<double>& dt);
140
141 virtual ~ParallelTracker();
142
144 // overwrite the execute-methode from DefaultVisitor
145 virtual void execute();
146
148 // overwrite the execute-methode from DefaultVisitor
149 virtual void visitBeamline(const Beamline&);
150
152 virtual void visitDrift(const Drift&);
153
155 virtual void visitRing(const Ring& ring);
156
158 virtual void visitMarker(const Marker&);
159
161 virtual void visitMultipole(const Multipole&);
162
164 virtual void visitMultipoleT(const MultipoleT&);
165
167 virtual void visitOffset(const Offset&);
168
170 virtual void visitRFCavity(const RFCavity&);
171
173 virtual void visitSolenoid(const Solenoid&);
174
176 virtual void visitTravelingWave(const TravelingWave&);
177
179 virtual void visitScalingFFAMagnet(const ScalingFFAMagnet& bend);
180
182 virtual void visitVerticalFFAMagnet(const VerticalFFAMagnet& bend);
183
184 // made following public: __host__ __device__ lambda cannot have private or protected access within its class
185 void kickParticles(const BorisPusher& pusher);
186
187 void pushParticles(const BorisPusher& pusher);
188
189 void timeIntegration2(BorisPusher& pusher);
190
191 void changeDT(bool backTrack = false);
192
193 void computeSpaceChargeFields(unsigned long long step);
194
195 void setTime();
196private:
197 // Not implemented.
201
202 /*
203 Ring specifics
204 */
205
206 unsigned turnnumber_m;
207
208 std::list<Component*> myElements;
211 double bega;
214 double referenceZ = 0.0;
215
218 double referencePz = 0.0;
220
223
226
227 void buildupFieldList(double BcParameter[], ElementType elementType, Component* elptr);
228
229 std::vector<PluginElement*> pluginElements_m;
230
231
232
233
234
235 /********************** END VARIABLES ***********************************/
236
237 void updateReferenceParticle(const BorisPusher& pusher);
238
239 void writePhaseSpace(const long long step, bool psDump, bool statDump);
240
241 /********** BEGIN AUTOPHSING STUFF **********/
242 void updateRFElement(std::string elName, double maxPhi);
244 void saveCavityPhases();
245 void restoreCavityPhases();
246 /************ END AUTOPHSING STUFF **********/
247
248 void prepareSections();
249
250 void timeIntegration1(BorisPusher& pusher);
251 void selectDT(bool backTrack = false);
252 void emitParticles(long long step);
256
257 // void prepareOpalBeamlineSections();
258 void dumpStats(long long step, bool psDump, bool statDump);
260 bool hasEndOfLineReached(const BoundingBox& globalBoundingBox);
262
263 void doBinaryRepartition();
264
265 void transformBunch(const CoordinateSystemTrafo& trafo);
266
267 void updateReference(const BorisPusher& pusher);
269 void applyFractionalStep(const BorisPusher& pusher, double tau);
270 void findStartPosition(const BorisPusher& pusher);
271 void autophaseCavities(const BorisPusher& pusher);
272
273 bool applyPluginElements(const double dt);
274};
275
276inline void ParallelTracker::visitDrift(const Drift& drift) {
277 itsOpalBeamline_m.visit(drift, *this, itsBunch_m);
278}
279
280inline void ParallelTracker::visitMarker(const Marker& marker) {
281 itsOpalBeamline_m.visit(marker, *this, itsBunch_m);
282}
283
285 itsOpalBeamline_m.visit(mult, *this, itsBunch_m);
286}
287
289 itsOpalBeamline_m.visit(mult, *this, itsBunch_m);
290}
291
293 itsOpalBeamline_m.visit(as, *this, itsBunch_m);
294}
295
297 itsOpalBeamline_m.visit(so, *this, itsBunch_m);
298}
299
301 itsOpalBeamline_m.visit(as, *this, itsBunch_m);
302}
303
304inline void ParallelTracker::kickParticles(const BorisPusher& pusher) {
305
306 auto Rview = itsBunch_m->getParticleContainer()->R.getView();
307 auto Pview = itsBunch_m->getParticleContainer()->P.getView();
308 auto dtview = itsBunch_m->getParticleContainer()->dt.getView();
309 auto Efview = itsBunch_m->getParticleContainer()->E.getView();
310 auto Bfview = itsBunch_m->getParticleContainer()->B.getView();
311
312
313 const double mass = itsReference.getM();
314 const double charge = itsReference.getQ();
315
316 Kokkos::parallel_for(
317 "kickParticles", ippl::getRangePolicy(Rview),
318 KOKKOS_LAMBDA(const int i) {
319 Vector_t<double, 3> p = {Pview(i)[0],Pview(i)[1],Pview(i)[2]};
320
321 Vector_t<double, 3> e = {Efview(i)[0],Efview(i)[1],Efview(i)[2]};
322 Vector_t<double, 3> b = {Bfview(i)[0],Bfview(i)[1],Bfview(i)[2]};
323 double dt = dtview(i);
324
325 // pusher.kick(x,p,e,b,dt);
326 // Implementation follows chapter 4-4, p. 61 - 63 from
327 // Birdsall, C. K. and Langdon, A. B. (1985). Plasma physics
328 // via computer simulation.
329 //
330 // Up to finite precision effects, the new implementation is equivalent to the
331 // old one, but uses less floating point operations.
332 //
333 // Relativistic variant implemented below is described in
334 // chapter 15-4, p. 356 - 357.
335 // However, since other units are used here, small
336 // modifications are required. The relativistic variant can be derived
337 // from the nonrelativistic one by replacing
338 // mass
339 // by
340 // gamma * rest mass
341 // and transforming the units.
342 //
343 // Parameters:
344 // R = x / (c * dt): Scaled position x, not used in here
345 // P = v / c * gamma: Scaled velocity v
346 // Ef: Electric field
347 // Bf: Magnetic field
348 // dt: Timestep
349 // mass = rest energy = rest mass * c * c
350 // charge
351
352 // Half step E
353 p += 0.5 * dt * charge * Physics::c / mass * e;
354
355 // Full step B
356
357 const double gamma = Kokkos::sqrt(1.0 + dot(p, p));
358 Vector_t<double, 3> const t = 0.5 * dt * charge * Physics::c * Physics::c / (gamma * mass) * b;
359 Vector_t<double, 3> const w = p + cross(p, t);
360 Vector_t<double, 3> const s = 2.0 / (1.0 + dot(t, t)) * t;
361 p += cross(w, s);
362
363
364 // Half step E
365 p += 0.5 * dt * charge * Physics::c / mass * e;
366
367 Pview(i) = p;
368
369 });
370
371 itsBunch_m->getParticleContainer()->update();
372 ippl::Comm->barrier();
373}
374
375inline void ParallelTracker::pushParticles(const BorisPusher& pusher) {
376
377 itsBunch_m->switchToUnitlessPositions(true);
378
379 auto Rview = itsBunch_m->getParticleContainer()->R.getView();
380 auto Pview = itsBunch_m->getParticleContainer()->P.getView();
381 auto dtview = itsBunch_m->getParticleContainer()->dt.getView();
382
383 Kokkos::parallel_for(
384 "pushParticles", ippl::getRangePolicy(Rview),
385 KOKKOS_LAMBDA(const int i) {
386 Vector_t<double, 3> x = {Rview(i)[0],Rview(i)[1],Rview(i)[2]};
387 Vector_t<double, 3> p = {Pview(i)[0],Pview(i)[1],Pview(i)[2]};
388 double dt = dtview(i);
389
397 // \TODO check +-
398
399 // pusher.push(x,p,dt);
400 x = 0.5 * dt * p / Kokkos::sqrt(1.0 + dot(p));
401 Rview(i) += x;
402 });
403
404
405 itsBunch_m->switchOffUnitlessPositions(true);
406 itsBunch_m->getParticleContainer()->update();
407 ippl::Comm->barrier();
408}
409
410#endif // OPAL_ParallelTracker_HH
Vector3D cross(const Vector3D &lhs, const Vector3D &rhs)
Vector cross product.
Definition Vector3D.cpp:111
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition Vector3D.cpp:118
ElementType
Definition ElementBase.h:88
PartBunch< PLayout_t< double, 3 >, double, 3 > PartBunch_t
elements
Definition IndexMap.cpp:162
ippl::Vector< T, Dim > Vector_t
constexpr double c
The velocity of light in m/s.
Definition Physics.h:45
Interface for a single beam element.
Definition Component.h:50
Interface for drift space.
Definition Drift.h:31
Interface for a marker.
Definition Marker.h:32
Interface for general multipole.
Definition Multipole.h:45
Ring describes a ring type geometry for tracking.
Definition Ring.h:62
Interface for solenoids.
Definition Solenoid.h:34
const PartData itsReference
The reference information.
std::set< std::shared_ptr< Component > > value_t
Definition IndexMap.h:47
virtual void visitScalingFFAMagnet(const ScalingFFAMagnet &bend)
Apply the algorithm to a scaling FFA.
ParallelTracker(const ParallelTracker &)
void pushParticles(const BorisPusher &pusher)
void emitParticles(long long step)
void updateRFElement(std::string elName, double maxPhi)
void changeDT(bool backTrack=false)
std::vector< int > ivector_t
IpplTimings::TimerRef BinRepartTimer_m
virtual void visitSolenoid(const Solenoid &)
Apply the algorithm to a RF cavity.
std::list< type_pair * > beamline_list
DataSink * itsDataSink_m
virtual void visitOffset(const Offset &)
Apply the algorithm to a offset (placement).
beamline_list FieldDimensions
void autophaseCavities(const BorisPusher &pusher)
void printRFPhases()
double bega
The reference variables.
std::set< ParticleMatterInteractionHandler * > activeParticleMatterInteractionHandlers_m
IpplTimings::TimerRef WakeFieldTimer_m
bool applyPluginElements(const double dt)
IpplTimings::TimerRef OrbThreader_m
virtual void visitMultipole(const Multipole &)
Apply the algorithm to a multipole.
virtual void visitDrift(const Drift &)
Apply the algorithm to a drift space.
virtual void execute()
Apply the algorithm to the top-level beamline.
std::vector< PluginElement * > pluginElements_m
void kickParticles(const BorisPusher &pusher)
virtual void visitMultipoleT(const MultipoleT &)
Apply the algorithm to an arbitrary multipole.
std::vector< double > dvector_t
unsigned long long repartFreq_m
void transformBunch(const CoordinateSystemTrafo &trafo)
virtual void visitRing(const Ring &ring)
Apply the algorithm to a ring.
void writePhaseSpace(const long long step, bool psDump, bool statDump)
void timeIntegration2(BorisPusher &pusher)
void computeWakefield(IndexMap::value_t &elements)
virtual void visitBeamline(const Beamline &)
Apply the algorithm to a beam line.
double zstart_m
where to start
size_t numParticlesInSimulation_m
void applyFractionalStep(const BorisPusher &pusher, double tau)
std::list< Component * > myElements
void updateReference(const BorisPusher &pusher)
void updateReferenceParticle(const BorisPusher &pusher)
void buildupFieldList(double BcParameter[], ElementType elementType, Component *elptr)
IpplTimings::TimerRef timeIntegrationTimer2_m
void computeExternalFields(OrbitThreader &oth)
unsigned int emissionSteps_m
virtual void visitTravelingWave(const TravelingWave &)
Apply the algorithm to a traveling wave.
void computeSpaceChargeFields(unsigned long long step)
std::pair< ElementType, element_pair > type_pair
bool hasEndOfLineReached(const BoundingBox &globalBoundingBox)
std::pair< double[8], Component * > element_pair
ParallelTracker(const Beamline &bl, const PartData &data, bool revBeam, bool revTrack)
Constructor.
WakeFunction * wakeFunction_m
void dumpStats(long long step, bool psDump, bool statDump)
void computeParticleMatterInteraction(IndexMap::value_t elements, OrbitThreader &oth)
void handleRestartRun()
void operator=(const ParallelTracker &)
IpplTimings::TimerRef timeIntegrationTimer1_m
IpplTimings::TimerRef PluginElemTimer_m
void selectDT(bool backTrack=false)
virtual void visitMarker(const Marker &)
Apply the algorithm to a marker.
void findStartPosition(const BorisPusher &pusher)
virtual void visitRFCavity(const RFCavity &)
Apply the algorithm to a RF cavity.
IpplTimings::TimerRef fieldEvaluationTimer_m
void timeIntegration1(BorisPusher &pusher)
StepSizeConfig stepSizes_m
OpalBeamline itsOpalBeamline_m
virtual void visitVerticalFFAMagnet(const VerticalFFAMagnet &bend)
Apply the algorithm to a vertical FFA magnet.
Particle reference data.
Definition PartData.h:37
Tracker(const Beamline &, const PartData &, bool backBeam, bool backTrack)
Constructor.
Definition Tracker.cpp:75
PartBunch_t * itsBunch_m
The bunch of particles to be tracked.
Definition Tracker.h:123
An abstract sequence of beam line components.
Definition Beamline.h:34