OPALX (Object Oriented Parallel Accelerator Library for Exascal) MINIorX
OPALX
ParallelTracker.cpp
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//
23
24#include <cfloat>
25#include <cmath>
26#include <fstream>
27#include <iomanip>
28#include <iostream>
29#include <limits>
30#include <sstream>
31#include <string>
32
33#include <boost/numeric/ublas/io.hpp>
34
38#include "BasicActions/Option.h"
39
40#include "Beamlines/Beamline.h"
43#include "Physics/Units.h"
44
48#include "Utilities/Options.h"
49#include "Utilities/Timer.h"
50#include "Utilities/Util.h"
52
53#include "AbsBeamline/Offset.h"
56
57extern Inform* gmsg;
58
59class PartData;
60
62 const Beamline& beamline, const PartData& reference, bool revBeam, bool revTrack)
63 : Tracker(beamline, reference, revBeam, revTrack),
64 itsDataSink_m(nullptr),
65 itsOpalBeamline_m(beamline.getOrigin3D(), beamline.getInitialDirection()),
66 opalRing_m(nullptr),
67 globalEOL_m(false),
68 wakeStatus_m(false),
69 wakeFunction_m(nullptr),
70 pathLength_m(0.0),
71 zstart_m(0.0),
74 repartFreq_m(0),
75 emissionSteps_m(std::numeric_limits<unsigned int>::max()),
77 timeIntegrationTimer1_m(IpplTimings::getTimer("TIntegration1")),
78 timeIntegrationTimer2_m(IpplTimings::getTimer("TIntegration2")),
79 fieldEvaluationTimer_m(IpplTimings::getTimer("External field eval")),
80 PluginElemTimer_m(IpplTimings::getTimer("PluginElements")),
81 BinRepartTimer_m(IpplTimings::getTimer("Binaryrepart")),
82 OrbThreader_m(IpplTimings::getTimer("OrbThreader")) {
83}
84
86 const Beamline& beamline, PartBunch_t* bunch, DataSink& ds, const PartData& reference,
87 bool revBeam, bool revTrack, const std::vector<unsigned long long>& maxSteps, double zstart,
88 const std::vector<double>& zstop, const std::vector<double>& dt)
89 : Tracker(beamline, bunch, reference, revBeam, revTrack),
90 itsDataSink_m(&ds),
91 itsOpalBeamline_m(beamline.getOrigin3D(), beamline.getInitialDirection()),
92 opalRing_m(nullptr),
93 globalEOL_m(false),
94 wakeStatus_m(false),
95 wakeFunction_m(nullptr),
96 pathLength_m(0.0),
97 zstart_m(zstart),
100 repartFreq_m(0),
101 emissionSteps_m(std::numeric_limits<unsigned int>::max()),
103 timeIntegrationTimer1_m(IpplTimings::getTimer("TIntegration1")),
104 timeIntegrationTimer2_m(IpplTimings::getTimer("TIntegration2")),
105 fieldEvaluationTimer_m(IpplTimings::getTimer("External field eval")),
106 BinRepartTimer_m(IpplTimings::getTimer("Binaryrepart")),
107 OrbThreader_m(IpplTimings::getTimer("OrbThreader")) {
108
109 for (unsigned int i = 0; i < zstop.size(); ++i) {
110 stepSizes_m.push_back(dt[i], zstop[i], maxSteps[i]);
111 }
112
113 stepSizes_m.sortAscendingZStop();
114 stepSizes_m.resetIterator();
115}
116
119
121 *gmsg << "Adding ScalingFFAMagnet" << endl;
122 /*
123 if (opalRing_m != nullptr) {
124 ScalingFFAMagnet* newBend = bend.clone(); // setup the end field, if required
125 newBend->setupEndField();
126 opalRing_m->appendElement(*newBend);
127 } else {
128 throw OpalException("ParallelCyclotronTracker::visitScalingFFAMagnet",
129 "Need to define a RINGDEFINITION to use ScalingFFAMagnet element");
130 }
131 */
132}
133
135 double BcParameter[], ElementType elementType, Component* elptr) {
136 beamline_list::iterator sindex;
137
138 type_pair* localpair = new type_pair();
139 localpair->first = elementType;
140
141 for (int i = 0; i < 8; i++)
142 *(((localpair->second).first) + i) = *(BcParameter + i);
143
144 (localpair->second).second = elptr;
145
146 // always put cyclotron as the first element in the list.
147 if (elementType == ElementType::RING) {
148 sindex = FieldDimensions.begin();
149 } else {
150 sindex = FieldDimensions.end();
151 }
152 FieldDimensions.insert(sindex, localpair);
153}
154
155/*
156 * @param ring
157 */
158
160 *gmsg << "* ----------------------------- Ring ------------------------------------- *" << endl;
161
162 delete opalRing_m;
163
164 opalRing_m = dynamic_cast<Ring*>(ring.clone());
165
166 myElements.push_back(opalRing_m);
167
168 opalRing_m->initialise(itsBunch_m);
169
170 referenceR = opalRing_m->getBeamRInit();
171 referencePr = opalRing_m->getBeamPRInit();
172 referenceTheta = opalRing_m->getBeamPhiInit();
173
175 throw OpalException(
176 "Error in ParallelTracker::visitRing", "PHIINIT is out of [-180, 180)!");
177 }
178
179 referenceZ = 0.0;
180 referencePz = 0.0;
181
182 referencePtot = itsReference.getGamma() * itsReference.getBeta();
184
185 if (referencePtot < 0.0)
186 referencePt *= -1.0;
187
190
191 double BcParameter[8] = {}; // zero initialise array
192
194
195 // Finally print some diagnostic
196 *gmsg << "* Initial beam radius = " << referenceR << " [mm] " << endl;
197 *gmsg << "* Initial gamma = " << itsReference.getGamma() << endl;
198 *gmsg << "* Initial beta = " << itsReference.getBeta() << endl;
199 *gmsg << "* Total reference momentum = " << referencePtot << " [beta gamma]" << endl;
200 *gmsg << "* Reference azimuthal momentum = " << referencePt << " [beta gamma]" << endl;
201 *gmsg << "* Reference radial momentum = " << referencePr << " [beta gamma]" << endl;
202 *gmsg << "* " << opalRing_m->getSymmetry() << " fold field symmetry " << endl;
203 *gmsg << "* Harmonic number h = " << opalRing_m->getHarmonicNumber() << " " << endl;
204}
205
212 *gmsg << "Adding Vertical FFA Magnet" << endl;
213 if (opalRing_m != nullptr)
214 opalRing_m->appendElement(mag);
215 else
216 throw OpalException(
217 "ParallelCyclotronTracker::visitVerticalFFAMagnet",
218 "Need to define a RINGDEFINITION to use VerticalFFAMagnet element");
219}
220
222 const FlaggedBeamline* fbl = static_cast<const FlaggedBeamline*>(&bl);
223 if (fbl->getRelativeFlag()) {
224 OpalBeamline stash(fbl->getOrigin3D(), fbl->getInitialDirection());
225 stash.swap(itsOpalBeamline_m);
226 fbl->iterate(*this, false);
227 itsOpalBeamline_m.prepareSections();
228 itsOpalBeamline_m.compute3DLattice();
230 stash.swap(itsOpalBeamline_m);
231 } else {
232 fbl->iterate(*this, false);
233 }
234}
235
238 if (opalRing_m == nullptr)
239 throw OpalException(
240 "ParallelCylcotronTracker::visitOffset",
241 "Attempt to place an offset when Ring not defined");
242 Offset* offNonConst = const_cast<Offset*>(&off);
243 offNonConst->updateGeometry(opalRing_m->getNextPosition(), opalRing_m->getNextNormal());
244 opalRing_m->appendElement(off);
245}
246
247void ParallelTracker::updateRFElement(std::string elName, double maxPhase) {
248 FieldList cavities = itsOpalBeamline_m.getElementByType(ElementType::RFCAVITY);
249 FieldList travelingwaves = itsOpalBeamline_m.getElementByType(ElementType::TRAVELINGWAVE);
250 cavities.insert(cavities.end(), travelingwaves.begin(), travelingwaves.end());
251
252 for (FieldList::iterator fit = cavities.begin(); fit != cavities.end(); ++fit) {
253 if ((*fit).getElement()->getName() == elName) {
254 RFCavity* element = static_cast<RFCavity*>((*fit).getElement().get());
255
256 element->setPhasem(maxPhase);
257 element->setAutophaseVeto();
258
259 *ippl::Info << "Restored cavity phase from the h5 file. Name: " << element->getName()
260 << ", phase: " << maxPhase << " rad" << endl;
261 return;
262 }
263 }
264}
265
267 IpplTimings::startTimer(PluginElemTimer_m);
268
269 bool flag = false;
270 for (PluginElement* element : pluginElements_m) {
271 bool tmp = element->check(itsBunch_m, turnnumber_m, itsBunch_m->getT(), dt);
272 flag |= tmp;
273
274 if (tmp) {
275 itsBunch_m->updateNumTotal();
276 *gmsg << "* Total number of particles after PluginElement= "
277 << itsBunch_m->getTotalNum() << endl;
278 }
279 }
280
281 IpplTimings::stopTimer(PluginElemTimer_m);
282 return flag;
283}
284
286 itsDataSink_m->storeCavityInformation();
287}
288
290 typedef std::vector<MaxPhasesT>::iterator iterator_t;
291
292 if (OpalData::getInstance()->hasPriorTrack() || OpalData::getInstance()->inRestartRun()) {
295 for (; it < end; ++it) {
296 updateRFElement((*it).first, (*it).second);
297 }
298 }
299}
300
302 Inform msg("ParallelTracker ", *gmsg);
304 bool back_track = false;
305
307 const double globalTimeShift =
308 itsBunch_m->weHaveEnergyBins() ? OpalData::getInstance()->getGlobalPhaseShift() : 0.0;
310
311 // the time step needs to be positive in the setup
312 itsBunch_m->setdT(std::abs(itsBunch_m->getdT()));
313 dtCurrentTrack_m = itsBunch_m->getdT();
314
315 if (OpalData::getInstance()->hasPriorTrack() || OpalData::getInstance()->inRestartRun()) {
317 }
318
320
321 double minTimeStep = stepSizes_m.getMinTimeStep();
322
323 itsOpalBeamline_m.activateElements();
324
325 CoordinateSystemTrafo beamlineToLab = itsOpalBeamline_m.getCSTrafoLab2Local().inverted();
326
327 itsBunch_m->toLabTrafo_m = beamlineToLab;
328
329 itsBunch_m->RefPartR_m = beamlineToLab.transformTo(itsBunch_m->getParticleContainer()->getMeanR());
330 itsBunch_m->RefPartP_m = beamlineToLab.rotateTo(itsBunch_m->getParticleContainer()->getMeanP());
331
332 if (itsBunch_m->getTotalNum() > 0) {
333 if (zstart_m > pathLength_m) {
334 findStartPosition(pusher);
335 }
336
337 itsBunch_m->set_sPos(pathLength_m);
338 }
339
340 stepSizes_m.advanceToPos(zstart_m);
341
342 Vector_t<double, 3> rmin(0.0), rmax(0.0);
343 if (itsBunch_m->getTotalNum() > 0) {
344 itsBunch_m->get_bounds(rmin, rmax);
345 }
346
347 *gmsg << "ParallelTrack: momentum= " << itsBunch_m->getParticleContainer()->getMeanP()(2) << endl;
348 *gmsg << "itsBunch_m->RefPartR_m= " << itsBunch_m->RefPartR_m << endl;
349 *gmsg << "itsBunch_m->RefPartP_m= " << itsBunch_m->RefPartP_m << endl;
350
351 IpplTimings::startTimer(OrbThreader_m);
352
353 bool const psDump0 = 0;
354 bool const statDump0 = 0;
355
356 writePhaseSpace(0, psDump0, statDump0);
357 msg << level2 << "Dump initial phase space" << endl;
358
359
360 OrbitThreader oth(
361 itsReference, itsBunch_m->RefPartR_m, itsBunch_m->RefPartP_m, pathLength_m, -rmin(2),
362 itsBunch_m->getT(), (back_track ? -minTimeStep : minTimeStep), stepSizes_m,
364
365 oth.execute();
366 IpplTimings::stopTimer(OrbThreader_m);
367
368 BoundingBox globalBoundingBox = oth.getBoundingBox();
369
370 numParticlesInSimulation_m = itsBunch_m->getTotalNum();
371
372 setTime();
373
374 double time = itsBunch_m->getT() - globalTimeShift;
375 itsBunch_m->setT(time);
376
377 unsigned long long step = itsBunch_m->getGlobalTrackStep();
378 OPALTimer::Timer myt1;
379 *gmsg << "* Track start at: " << myt1.time() << ", t= " << Util::getTimeString(time) << "; "
380 << "zstart at: " << Util::getLengthString(pathLength_m) << endl;
381 *gmsg << "* Executing ParallelTracker\n"
382 << "* Initial dt = " << Util::getTimeString(itsBunch_m->getdT()) << "\n"
383 << "* Max integration steps = " << stepSizes_m.getMaxSteps() << ", next step = " << step
384 << endl
385 << endl;
386
388
389 globalEOL_m = false;
390 wakeStatus_m = false;
391 deletedParticles_m = false;
393
394 stepSizes_m.printDirect(*gmsg);
395
396 while (!stepSizes_m.reachedEnd()) {
397
398 unsigned long long trackSteps = stepSizes_m.getNumSteps() + step;
401
402 for (; step < trackSteps; ++step) {
403 Vector_t<double, 3> rmin(0.0), rmax(0.0);
404 if (itsBunch_m->getTotalNum() > 0) {
405 itsBunch_m->get_bounds(rmin, rmax);
406 }
407 // ADA
408 timeIntegration1(pusher);
409
411
412 // \todo for a drift we can neglect that
413 // computeExternalFields(oth);
414
415 timeIntegration2(pusher);
416
418 // \todo emitParticles(step);
419 //selectDT(back_track);
420
421 itsBunch_m->incrementT();
422
423 if (itsBunch_m->getT() > 0.0 || itsBunch_m->getdT() < 0.0) {
424 updateReference(pusher);
425 }
426
427 if (deletedParticles_m) {
428 // \todo doDelete
429 deletedParticles_m = false;
430 }
431
432 itsBunch_m->set_sPos(pathLength_m);
433
434 // if (hasEndOfLineReached(globalBoundingBox)) break;
435
436 bool const psDump =
437 ((itsBunch_m->getGlobalTrackStep() % Options::psDumpFreq) + 1
439 bool const statDump =
440 ((itsBunch_m->getGlobalTrackStep() % Options::statDumpFreq) + 1
442 dumpStats(step, psDump, statDump);
443
444 itsBunch_m->incTrackSteps();
445
446 ippl::Vector<double,3> pdivg = itsBunch_m->RefPartP_m / Util::getGamma(itsBunch_m->RefPartP_m);
447 double beta = euclidean_norm(pdivg);
448 double driftPerTimeStep = std::abs(itsBunch_m->getdT()) * Physics::c * beta;
449
450 if (std::abs(stepSizes_m.getZStop() - pathLength_m) < 0.5 * driftPerTimeStep) {
451 break;
452 }
453 }
454
455 if (globalEOL_m)
456 break;
457 ++stepSizes_m;
458 }
459 itsBunch_m->set_sPos(pathLength_m);
460
461 numParticlesInSimulation_m = itsBunch_m->getTotalNum();
462
463 bool const psDump =
464 (((itsBunch_m->getGlobalTrackStep() - 1) % Options::psDumpFreq) + 1 != Options::psDumpFreq);
465 bool const statDump =
466 (((itsBunch_m->getGlobalTrackStep() - 1) % Options::statDumpFreq) + 1
468
469 writePhaseSpace((step + 1), psDump, statDump);
470
471 *gmsg << "* Dump phase space of last step" << endl;
472
473 itsOpalBeamline_m.switchElementsOff();
474
475 OPALTimer::Timer myt3;
476 *gmsg << endl << "* Done executing ParallelTracker at " << myt3.time() << endl << endl;
477}
478 /*
479 OpalData::getInstance()->setPriorTrack();
480 */
481
483 itsBeamline_m.accept(*this);
484 itsOpalBeamline_m.prepareSections();
485 itsOpalBeamline_m.compute3DLattice();
486 itsOpalBeamline_m.save3DLattice();
487 itsOpalBeamline_m.save3DInput();
488}
489
491 IpplTimings::startTimer(timeIntegrationTimer1_m);
492 pushParticles(pusher);
493 IpplTimings::stopTimer(timeIntegrationTimer1_m);
494}
495
497 /*
498 transport and emit particles
499 that passed the cathode in the first
500 half-step or that would pass it in the
501 second half-step.
502
503 to make IPPL and the field solver happy
504 make sure that at least 10 particles are emitted
505
506 also remember that node 0 has
507 all the particles to be emitted
508
509 this has to be done *after* the calculation of the
510 space charges! thereby we neglect space charge effects
511 in the very first step of a new-born particle.
512
513 */
514
515 IpplTimings::startTimer(timeIntegrationTimer2_m);
516 kickParticles(pusher);
517 // switchElements();
518 pushParticles(pusher);
519
520
521 auto dtview = itsBunch_m->getParticleContainer()->dt.getView();
522 double newdT = itsBunch_m->getdT();
523
524 Kokkos::parallel_for(
525 "changeDT", ippl::getRangePolicy(dtview),
526 KOKKOS_LAMBDA(const int i) {
527 dtview(i) = newdT;
528 });
529
530 IpplTimings::stopTimer(timeIntegrationTimer2_m);
531}
532
533void ParallelTracker::selectDT(bool backTrack) {
534 double dt = dtCurrentTrack_m;
535 itsBunch_m->setdT(dt);
536
537 if (backTrack) {
538 itsBunch_m->setdT(-std::abs(itsBunch_m->getdT()));
539 }
540}
541
542void ParallelTracker::changeDT(bool backTrack) {
543
544 selectDT(backTrack);
545
546 auto dtview = itsBunch_m->getParticleContainer()->dt.getView();
547 double newdT = itsBunch_m->getdT();
548
549 Kokkos::parallel_for(
550 "changeDT", ippl::getRangePolicy(dtview),
551 KOKKOS_LAMBDA(const int i) {
552 dtview(i) = newdT;
553 });
554
555}
556
557void ParallelTracker::emitParticles(long long step) {
558
559}
560
561void ParallelTracker::computeSpaceChargeFields(unsigned long long step) {
562
563 if (!itsBunch_m->hasFieldSolver()) {
564 *gmsg << "no solver avaidable " << endl;
565 return;
566 }
567
568 itsBunch_m->calcBeamParameters();
569
570 Quaternion alignment = getQuaternion(itsBunch_m->get_pmean(), Vector_t<double, 3>(0, 0, 1));
571
572 CoordinateSystemTrafo beamToReferenceCSTrafo(
573 Vector_t<double, 3>(0, 0, pathLength_m), alignment.conjugate());
574
575 CoordinateSystemTrafo referenceToBeamCSTrafo = beamToReferenceCSTrafo.inverted();
576
584
585
586 const matrix_t rot = referenceToBeamCSTrafo.getRotationMatrix();
587 const ippl::Vector<double, 3> org = referenceToBeamCSTrafo.getOrigin();
588
589
590 typedef Kokkos::View<double**> ViewMatrixType;
591 ViewMatrixType Rot("Rot", 3, 3);
592 ViewMatrixType::HostMirror h_Rot = Kokkos::create_mirror_view(Rot);
593
594 // Initialize M matrix on host.
595 for ( int i = 0; i < 3; ++i ) {
596 for ( int j = 0; j < 3; ++j ) {
597 h_Rot( i, j ) = rot(i, j);
598 }
599 }
600
601 Kokkos::deep_copy( Rot, h_Rot );
602
603 auto Rview = itsBunch_m->getParticleContainer()->R.getView();
604 auto Eview = itsBunch_m->getParticleContainer()->E.getView();
605 auto Bview = itsBunch_m->getParticleContainer()->B.getView();
606
607 Kokkos::parallel_for(
608 "referenceToBeamCSTrafo", ippl::getRangePolicy(Rview),
609 KOKKOS_LAMBDA(const int i) {
610 ippl::Vector<double, 3> x({Rview(i)[0],Rview(i)[1],Rview(i)[2]});
611 x = x - org;
612 for ( int j = 0; j < 3; ++j ) {
613 for ( int i = 0; i < 3; ++i ) {
614 Rview(j) = Rot(i,j) * x(i);
615 }
616 }
617 Eview(i) = ippl::Vector<double, 3>(0.0); // was done outside of the routine in the past
618 Bview(i) = ippl::Vector<double, 3>(0.0);
619 });
620
621 itsBunch_m->boundp();
622
623 if (step % repartFreq_m + 1 == repartFreq_m) {
625 }
626
627 itsBunch_m->setGlobalMeanR(itsBunch_m->get_centroid());
628
629 itsBunch_m->computeSelfFields();
630
641
642 Kokkos::parallel_for(
643 "CSTrafo:transformTo", ippl::getRangePolicy(Rview),
644 KOKKOS_LAMBDA(const int i) {
645 ippl::Vector<double, 3> x({Rview(i)[0],Rview(i)[1],Rview(i)[2]});
646 ippl::Vector<double, 3> e({Eview(i)[0],Eview(i)[1],Eview(i)[2]});
647 ippl::Vector<double, 3> b({Bview(i)[0],Bview(i)[1],Bview(i)[2]});
648
649 // beamToReferenceCSTrafo.rotateTo
650 for ( int i = 0; i < 3; ++i ) {
651 for ( int j = 0; j < 3; ++j ) {
652 Eview(i) = Rot(i,j) * e(i);
653 Bview(i) = Rot(i,j) * b(i);
654 }
655 }
656 // beamToReferenceCSTrafo.transformTo
657 x = x + org;
658 for ( int j = 0; j < 3; ++j ) {
659 for ( int i = 0; i < 3; ++i ) {
660 Rview(i) = Rot(j,i) * x(i);
661 }
662 }
663 });
664
665}
666
668 IpplTimings::startTimer(fieldEvaluationTimer_m);
669 Inform msg("ParallelTracker ", *gmsg);
670 const unsigned int localNum = itsBunch_m->getLocalNum();
671 bool locPartOutOfBounds = false, globPartOutOfBounds = false;
672 Vector_t<double, 3> rmin(0.0), rmax(0.0);
673 if (itsBunch_m->getTotalNum() > 0)
674 itsBunch_m->get_bounds(rmin, rmax);
676
677 try {
678 elements = oth.query(pathLength_m + 0.5 * (rmax(2) + rmin(2)), rmax(2) - rmin(2));
679 } catch (IndexMap::OutOfBounds& e) {
680 globalEOL_m = true;
681 return;
682 }
683
684 IndexMap::value_t::const_iterator it = elements.begin();
685 const IndexMap::value_t::const_iterator end = elements.end();
686
687 for (; it != end; ++it) {
688
689 CoordinateSystemTrafo refToLocalCSTrafo = (itsOpalBeamline_m.getMisalignment((*it))
690 * (itsOpalBeamline_m.getCSTrafoLab2Local((*it))
691 * itsBunch_m->toLabTrafo_m));
692
693 CoordinateSystemTrafo localToRefCSTrafo = refToLocalCSTrafo.inverted();
694
695 (*it)->setCurrentSCoordinate(pathLength_m + rmin(2));
696
697 for (unsigned int i = 0; i < localNum; ++i) {
698 // \todo if (itsBunch_m->Bin[i] < 0)
699 // continue;
700
701 // \todo itsBunch_m->R[i] = refToLocalCSTrafo.transformTo(itsBunch_m->R[i]);
702 // \todo itsBunch_m->P[i] = refToLocalCSTrafo.rotateTo(itsBunch_m->P[i]);
703 double dt = 1.0; // \todo itsBunch_m->dt[i];
704
705 Vector_t<double, 3> localE(0.0), localB(0.0);
706
707 if ((*it)->apply(i, itsBunch_m->getT() + 0.5 * dt, localE, localB)) {
708 // itsBunch_m->R[i] = localToRefCSTrafo.transformTo(itsBunch_m->R[i]);
709 // itsBunch_m->P[i] = localToRefCSTrafo.rotateTo(itsBunch_m->P[i]);
710 // itsBunch_m->Bin[i] = -1;
711 locPartOutOfBounds = true;
712
713 continue;
714 }
715
716 // itsBunch_m->R[i] = localToRefCSTrafo.transformTo(itsBunch_m->R[i]);
717 // itsBunch_m->P[i] = localToRefCSTrafo.rotateTo(itsBunch_m->P[i]);
718 // itsBunch_m->Ef[i] += localToRefCSTrafo.rotateTo(localE);
719 // itsBunch_m->Bf[i] += localToRefCSTrafo.rotateTo(localB);
720 }
721 }
722
723 IpplTimings::stopTimer(fieldEvaluationTimer_m);
724
725 // \todo reduce(locPartOutOfBounds, globPartOutOfBounds, OpOrAssign());
726 ippl::Comm->reduce(locPartOutOfBounds, globPartOutOfBounds, 1, std::logical_or<bool>());
727
728 size_t ne = 0;
729 if (globPartOutOfBounds) {
730 if (itsBunch_m->hasFieldSolver()) {
731 ne = itsBunch_m->boundp_destroyT();
732 }
733
734 // \todo
735 // else {
736 // ne = itsBunch_m->destroyT();
737 // }
738 numParticlesInSimulation_m = itsBunch_m->getTotalNum();
739 deletedParticles_m = true;
740 }
741
742 size_t totalNum = itsBunch_m->getTotalNum();
744
745 if (ne > 0) {
746 msg << level1 << "* Deleted " << ne << " particles, "
747 << "remaining " << numParticlesInSimulation_m << " particles" << endl;
748 }
749}
750
752 if (itsBunch_m->hasFieldSolver()) {
753 *ippl::Info << "*****************************************************************" << endl;
754 *ippl::Info << "do repartition because of repartFreq_m" << endl;
755 *ippl::Info << "*****************************************************************" << endl;
756 itsBunch_m->do_binaryRepart();
757 ippl::Comm->barrier();
758 IpplTimings::stopTimer(BinRepartTimer_m);
759 *ippl::Info << "*****************************************************************" << endl;
760 *ippl::Info << "do repartition done" << endl;
761 *ippl::Info << "*****************************************************************" << endl;
762 }
763}
764
765void ParallelTracker::dumpStats(long long step, bool psDump, bool statDump) {
766 OPALTimer::Timer myt2;
767
768 /*
769 if (itsBunch_m->getGlobalTrackStep() % 1000 + 1 == 1000) {
770 *gmsg << level1;
771 } else if (itsBunch_m->getGlobalTrackStep() % 100 + 1 == 100) {
772 *gmsg << level2;
773 } else {
774 *gmsg << level3;
775 }
776 */
777
779 *gmsg << "* " << myt2.time() << " "
780 << "Step " << std::setw(6) << itsBunch_m->getGlobalTrackStep() << "; "
781 << " -- no emission yet -- "
782 << "t= " << Util::getTimeString(itsBunch_m->getT()) << endl;
783 return;
784 }
785
786 // \todo itsBunch_m->calcEMean();
787 // size_t totalParticles_f = numParticlesInSimulation_m;
788 if (std::isnan(pathLength_m) || std::isinf(pathLength_m)) {
789 throw OpalException(
790 "ParallelTracker::dumpStats()",
791 "there seems to be something wrong with the position of the bunch!");
792 } else {
793 *gmsg << "* " << myt2.time() << " "
794 << "Step " << std::setw(6) << itsBunch_m->getGlobalTrackStep() << " "
795 << "at " << Util::getLengthString(pathLength_m) << ", "
796 << "t= " << Util::getTimeString(itsBunch_m->getT()) << ", "
797 << "E=" << Util::getEnergyString(itsBunch_m->get_meanKineticEnergy()) << endl;
798
799 writePhaseSpace(step, psDump, statDump);
800 }
801}
802
804
805 /*
806 minStepforReBin_m = Options::minStepForRebin;
807 RealVariable* br =
808 dynamic_cast<RealVariable*>(OpalData::getInstance()->find("MINSTEPFORREBIN"));
809 if (br)
810 minStepforReBin_m = static_cast<int>(br->getReal());
811 msg << level2 << "MINSTEPFORREBIN " << minStepforReBin_m << endl;
812 */
813
814 // there is no point to do repartitioning with one node
815 if (ippl::Comm->size() == 1) {
816 repartFreq_m = std::numeric_limits<unsigned long long>::max();
817 } else {
819 RealVariable* rep =
820 dynamic_cast<RealVariable*>(OpalData::getInstance()->find("REPARTFREQ"));
821 if (rep)
822 repartFreq_m = static_cast<int>(rep->getReal());
823 *gmsg << "* REPARTFREQ " << repartFreq_m << endl;
824 }
825}
826
827bool ParallelTracker::hasEndOfLineReached(const BoundingBox& globalBoundingBox) {
828 // \todo check in IPPL 1.0 it was OpBitwiseAndAssign()
829 ippl::Comm->reduce(globalEOL_m, globalEOL_m, 1, std::logical_and<bool>());
830 globalEOL_m = globalEOL_m || globalBoundingBox.isOutside(itsBunch_m->RefPartR_m);
831 return globalEOL_m;
832}
833
835
836 auto dtview = itsBunch_m->getParticleContainer()->dt.getView();
837 double newdT = itsBunch_m->getdT();
838
839 Kokkos::parallel_for(
840 "changeDT", ippl::getRangePolicy(dtview),
841 KOKKOS_LAMBDA(const int i) {
842 dtview(i) = newdT;
843 });
844}
845
846void ParallelTracker::writePhaseSpace(const long long /*step*/, bool psDump, bool statDump) {
847 Vector_t<double, 3> externalE, externalB;
848 Vector_t<double, 3> FDext[2]; // FDext = {BHead, EHead, BRef, ERef, BTail, ETail}.
849
850 // Sample fields at (xmin, ymin, zmin), (xmax, ymax, zmax) and the centroid location. We
851 // are sampling the electric and magnetic fields at the back, front and
852 // center of the beam.
853 Vector_t<double, 3> rmin, rmax;
854 itsBunch_m->get_bounds(rmin, rmax);
855
856 if (psDump || statDump) {
857 externalB = Vector_t<double, 3>(0.0);
858 externalE = Vector_t<double, 3>(0.0);
859 itsOpalBeamline_m.getFieldAt(
860 itsBunch_m->RefPartR_m, itsBunch_m->RefPartP_m,
861 itsBunch_m->getT() - 0.5 * itsBunch_m->getdT(), externalE, externalB);
862 FDext[0] = externalB; // \todo itsBunch_m->toLabTrafo_m.rotateFrom(externalB);
863 FDext[1] =
864 (externalE * Units::Vpm2MVpm); // \todo itsBunch_m->toLabTrafo_m.rotateFrom(externalE *
865 // Units::Vpm2MVpm);
866 }
867
868 if (statDump) {
869 itsDataSink_m->dumpSDDS(itsBunch_m, FDext, -1.0);
870 *gmsg << "* Wrote beam statistics." << endl;
871 }
872
873 if (psDump && (itsBunch_m->getTotalNum() > 0)) {
874 // Write bunch to .h5 file.
875 itsDataSink_m->dumpH5(itsBunch_m, FDext);
876
877 /*
878 // Write fields to .h5 file.
879 const size_t localNum = itsBunch_m->getLocalNum();
880 double distToLastStop = stepSizes_m.getFinalZStop() - pathLength_m;
881 Vector_t<double, 3> beta = itsBunch_m->RefPartP_m / Util::getGamma(itsBunch_m->RefPartP_m);
882 Vector_t<double, 3> driftPerTimeStep =
883 itsBunch_m->getdT()
884 * Physics::c; // \todo * itsBunch_m->toLabTrafo_m.rotateFrom(beta);
885 bool driftToCorrectPosition =
886 std::abs(distToLastStop) < 0.5 * euclidean_norm(driftPerTimeStep);
887 // \todo Ppos_t stashedR;
888 Vector_t<double, 3> stashedR;
889 Vector_t<double, 3> stashedRefPartR;
890
891 if (driftToCorrectPosition) {
892 const double tau =
893 distToLastStop / euclidean_norm(driftPerTimeStep) * itsBunch_m->getdT();
894
895 if (localNum > 0) {
896
897 stashedR.create(localNum);
898 stashedR = itsBunch_m->R;
899 stashedRefPartR = itsBunch_m->RefPartR_m;
900
901 for (size_t i = 0; i < localNum; ++i) {
902 itsBunch_m->R[i] +=
903 tau
904 * (Physics::c * itsBunch_m->P[i] / Util::getGamma(itsBunch_m->P[i])
905 - driftPerTimeStep / itsBunch_m->getdT());
906 }
907
908 }
909
910 driftPerTimeStep = itsBunch_m->toLabTrafo_m.rotateTo(driftPerTimeStep);
911 itsBunch_m->RefPartR_m =
912 itsBunch_m->RefPartR_m + tau * driftPerTimeStep / itsBunch_m->getdT();
913 CoordinateSystemTrafo update(
914 tau * driftPerTimeStep / itsBunch_m->getdT(), Quaternion(1.0, 0.0, 0.0, 0.0));
915 itsBunch_m->toLabTrafo_m = itsBunch_m->toLabTrafo_m * update.inverted();
916
917 itsBunch_m->set_sPos(stepSizes_m.getFinalZStop());
918
919 itsBunch_m->calcBeamParameters();
920 }
921 if (!statDump && !driftToCorrectPosition)
922 itsBunch_m->calcBeamParameters();
923
924 msg << *itsBunch_m << endl;
925
926 itsDataSink_m->dumpH5(itsBunch_m, FDext);
927 */
928
929 /*
930
931 if (driftToCorrectPosition) {
932 if (localNum > 0) {
933 itsBunch_m->R = stashedR;
934 stashedR.destroy(localNum, 0);
935 }
936
937 itsBunch_m->RefPartR_m = stashedRefPartR;
938 itsBunch_m->set_sPos(pathLength_m);
939
940 itsBunch_m->calcBeamParameters();
941 }
942
943 */
944
945 *gmsg << level2 << "* Wrote beam phase space." << endl;
946 }
947}
948
953
955 const double direction = back_track ? -1 : 1;
956 const double dt = direction * std::min(itsBunch_m->getT(), direction * itsBunch_m->getdT());
957 const double scaleFactor = Physics::c * dt;
958 Vector_t<double, 3> Ef(0.0), Bf(0.0);
959
960 itsBunch_m->RefPartR_m /= scaleFactor;
961 pusher.push(itsBunch_m->RefPartR_m, itsBunch_m->RefPartP_m, dt);
962 itsBunch_m->RefPartR_m *= scaleFactor;
963
964 IndexMap::value_t elements = itsOpalBeamline_m.getElements(itsBunch_m->RefPartR_m);
965 IndexMap::value_t::const_iterator it = elements.begin();
966 const IndexMap::value_t::const_iterator end = elements.end();
967
968 for (; it != end; ++it) {
969 const CoordinateSystemTrafo& refToLocalCSTrafo =
970 itsOpalBeamline_m.getCSTrafoLab2Local((*it));
971
972 Vector_t<double, 3> localR = refToLocalCSTrafo.transformTo(itsBunch_m->RefPartR_m);
973 Vector_t<double, 3> localP = refToLocalCSTrafo.rotateTo(itsBunch_m->RefPartP_m);
974 Vector_t<double, 3> localE(0.0), localB(0.0);
975
976 if ((*it)->applyToReferenceParticle(
977 localR, localP, itsBunch_m->getT() - 0.5 * dt, localE, localB)) {
978 *gmsg << level1 << "The reference particle hit an element" << endl;
979 globalEOL_m = true;
980 }
981
982 Ef += refToLocalCSTrafo.rotateFrom(localE);
983 Bf += refToLocalCSTrafo.rotateFrom(localB);
984 }
985
986 pusher.kick(itsBunch_m->RefPartR_m, itsBunch_m->RefPartP_m, Ef, Bf, dt);
987
988 itsBunch_m->RefPartR_m /= scaleFactor;
989 pusher.push(itsBunch_m->RefPartR_m, itsBunch_m->RefPartP_m, dt);
990 itsBunch_m->RefPartR_m *= scaleFactor;
991}
992
994 const unsigned int localNum = itsBunch_m->getLocalNum();
995 for (unsigned int i = 0; i < localNum; ++i) {
996 /* \todo host device ....
997 itsBunch_m->R[i] = trafo.transformTo(itsBunch_m->R[i]);
998 itsBunch_m->P[i] = trafo.rotateTo(itsBunch_m->P[i]);
999 itsBunch_m->Ef[i] = trafo.rotateTo(itsBunch_m->Ef[i]);
1000 itsBunch_m->Bf[i] = trafo.rotateTo(itsBunch_m->Bf[i]);
1001 */
1002 }
1003}
1004
1006 /*
1007 Inform m("updateRefToLabCSTrafo ");
1008 m << " initial RefPartR: " << itsBunch_m->RefPartR_m << endl;
1009 m << " RefPartR after transformFrom( " << itsBunch_m->RefPartR_m << endl;
1010 itsBunch_m->toLabTrafo_m.rotateFrom(itsBunch_m->RefPartP_m);
1011 Vector_t<double, 3> P = itsBunch_m->RefPartP_m;
1012 m << " CS " << itsBunch_m->toLabTrafo_m << endl;
1013 m << " rotMat= " << itsBunch_m->toLabTrafo_m.getRotationMatrix() << endl;
1014 m << " initial: path Lenght= " << pathLength_m << endl;
1015 m << " dt= " << itsBunch_m->getdT() << " R=" << R << endl;
1016 */
1017
1018 Vector_t<double, 3> R = itsBunch_m->toLabTrafo_m.transformFrom(itsBunch_m->RefPartR_m);
1019 Vector_t<double, 3> P = itsBunch_m->toLabTrafo_m.transformFrom(itsBunch_m->RefPartP_m);
1020
1021 pathLength_m += std::copysign(1, itsBunch_m->getdT()) * euclidean_norm(R);
1022
1024
1025 transformBunch(update);
1026
1027 itsBunch_m->toLabTrafo_m = itsBunch_m->toLabTrafo_m * update.inverted();
1028}
1029
1030void ParallelTracker::applyFractionalStep(const BorisPusher& pusher, double tau) {
1031 double t = itsBunch_m->getT();
1032 t += tau;
1033 itsBunch_m->setT(t);
1034
1035 // the push method below pushes for half a time step. Hence the ref particle
1036 // should be pushed for 2 * tau
1037 itsBunch_m->RefPartR_m /= (Physics::c * 2 * tau);
1038 pusher.push(itsBunch_m->RefPartR_m, itsBunch_m->RefPartP_m, tau);
1039 itsBunch_m->RefPartR_m *= (Physics::c * 2 * tau);
1040
1042 itsBunch_m->toLabTrafo_m.transformFrom(itsBunch_m->RefPartR_m);
1043 Vector_t<double, 3> R = itsBunch_m->RefPartR_m;
1044 itsBunch_m->toLabTrafo_m.rotateFrom(itsBunch_m->RefPartP_m);
1045 Vector_t<double, 3> P = itsBunch_m->RefPartP_m;
1047 itsBunch_m->toLabTrafo_m = itsBunch_m->toLabTrafo_m * update.inverted();
1048}
1049
1051 StepSizeConfig stepSizesCopy(stepSizes_m);
1052 if (back_track) {
1053 stepSizesCopy.shiftZStopLeft(zstart_m);
1054 }
1055
1056 double t = 0.0;
1057 itsBunch_m->setT(t);
1058
1059 dtCurrentTrack_m = stepSizesCopy.getdT();
1060 selectDT();
1061
1062 while (true) {
1063 autophaseCavities(pusher);
1064
1065 t += itsBunch_m->getdT();
1066 itsBunch_m->setT(t);
1067
1068 Vector_t<double, 3> oldR = itsBunch_m->RefPartR_m;
1070
1071 // \todo should not need the tmp
1072 Vector_t<double, 3> tmp = itsBunch_m->RefPartR_m - oldR;
1074
1075 tmp = itsBunch_m->RefPartP_m * Physics::c / Util::getGamma(itsBunch_m->RefPartP_m);
1076 double speed = euclidean_norm(tmp);
1077
1078
1079 if (pathLength_m > stepSizesCopy.getZStop()) {
1080 ++stepSizesCopy;
1081
1082 if (stepSizesCopy.reachedEnd()) {
1083 --stepSizesCopy;
1084 double tau = (stepSizesCopy.getZStop() - pathLength_m) / speed;
1085 applyFractionalStep(pusher, tau);
1086
1087 break;
1088 }
1089
1090 dtCurrentTrack_m = stepSizesCopy.getdT();
1091 selectDT();
1092 }
1093
1094 if (std::abs(pathLength_m - zstart_m) <= 0.5 * itsBunch_m->getdT() * speed) {
1095 double tau = (zstart_m - pathLength_m) / speed;
1096 applyFractionalStep(pusher, tau);
1097
1098 break;
1099 }
1100 }
1101
1102 changeDT();
1103}
1104
1106 double t = itsBunch_m->getT();
1107 Vector_t<double, 3> nextR = itsBunch_m->RefPartR_m / (Physics::c * itsBunch_m->getdT());
1108 pusher.push(nextR, itsBunch_m->RefPartP_m, itsBunch_m->getdT());
1109 nextR *= Physics::c * itsBunch_m->getdT();
1110
1111 auto elementSet = itsOpalBeamline_m.getElements(nextR);
1112 for (auto element : elementSet) {
1113 if (element->getType() == ElementType::TRAVELINGWAVE) {
1114 const TravelingWave* TWelement = static_cast<const TravelingWave*>(element.get());
1115 if (!TWelement->getAutophaseVeto()) {
1116 CavityAutophaser ap(itsReference, element);
1118 itsOpalBeamline_m.transformToLocalCS(element, itsBunch_m->RefPartR_m),
1119 itsOpalBeamline_m.rotateToLocalCS(element, itsBunch_m->RefPartP_m), t,
1120 itsBunch_m->getdT());
1121 }
1122
1123 } else if (element->getType() == ElementType::RFCAVITY) {
1124 const RFCavity* RFelement = static_cast<const RFCavity*>(element.get());
1125 if (!RFelement->getAutophaseVeto()) {
1126 CavityAutophaser ap(itsReference, element);
1128 itsOpalBeamline_m.transformToLocalCS(element, itsBunch_m->RefPartR_m),
1129 itsOpalBeamline_m.rotateToLocalCS(element, itsBunch_m->RefPartP_m), t,
1130 itsBunch_m->getdT());
1131 }
1132 }
1133 }
1134}
1135
1137 unsigned int who;
1138 unsigned int whom;
1139 unsigned int howMany;
1140};
Inform * gmsg
Definition changes.cpp:7
ElementType
Definition ElementBase.h:88
PartBunch< PLayout_t< double, 3 >, double, 3 > PartBunch_t
elements
Definition IndexMap.cpp:162
Quaternion getQuaternion(ippl::Vector< double, 3 > u, ippl::Vector< double, 3 > ref)
boost::numeric::ublas::matrix< double > matrix_t
Definition BoostMatrix.h:23
ippl::Vector< T, Dim > Vector_t
PartBunch< T, Dim >::ConstIterator end(PartBunch< T, Dim > const &bunch)
std::list< ClassicField > FieldList
std::string::const_iterator iterator_t
Definition array.cpp:19
TBeamline< FlaggedElmPtr > FlaggedBeamline
A beam line with flagged elements.
KOKKOS_INLINE_FUNCTION double euclidean_norm(const Vector_t< T, D > &v)
Definition OPALTypes.h:35
STL namespace.
constexpr double c
The velocity of light in m/s.
Definition Physics.h:45
constexpr double Vpm2MVpm
Definition Units.h:125
constexpr double deg2rad
Definition Units.h:143
int psDumpFreq
The frequency to dump the phase space, i.e.dump data when steppsDumpFreq==0.
Definition Options.cpp:39
int repartFreq
The frequency to do particles repartition for better load balance between nodes.
Definition Options.cpp:49
int statDumpFreq
The frequency to dump statistical values, e.e. dump data when stepstatDumpFreq==0.
Definition Options.cpp:41
double getGamma(ippl::Vector< double, 3 > p)
Definition Util.h:44
std::string getEnergyString(double energyInMeV, unsigned int precision=3)
Definition Util.h:140
std::string getTimeString(double time, unsigned int precision=3)
Definition Util.h:70
std::string getLengthString(double spos, unsigned int precision=3)
Definition Util.h:93
Interface for a single beam element.
Definition Component.h:50
virtual const std::string & getName() const
Get element name.
void updateGeometry(Vector_t< double, 3 > startPosition, Vector_t< double, 3 > startDirection)
Definition Offset.cpp:177
virtual bool getAutophaseVeto() const
Definition RFCavity.h:380
virtual void setPhasem(double phase)
Definition RFCavity.h:344
virtual void setAutophaseVeto(bool veto=true)
Definition RFCavity.h:376
Ring describes a ring type geometry for tracking.
Definition Ring.h:62
virtual ElementBase * clone() const override
Definition Ring.h:155
std::vector< MaxPhasesT >::iterator getLastMaxPhases()
Definition OpalData.cpp:401
double getGlobalPhaseShift()
units: (sec)
Definition OpalData.cpp:450
std::vector< MaxPhasesT >::iterator getFirstMaxPhases()
Definition OpalData.cpp:397
Object * find(const std::string &name)
Find entry.
Definition OpalData.cpp:563
void setInPrepState(bool state)
Definition OpalData.cpp:299
void setGlobalPhaseShift(double shift)
units: (sec)
Definition OpalData.cpp:445
static OpalData * getInstance()
Definition OpalData.cpp:195
void setOpenMode(OpenMode openMode)
Definition OpalData.cpp:348
const PartData itsReference
The reference information.
double getPhaseAtMaxEnergy(const Vector_t< double, 3 > &R, const Vector_t< double, 3 > &P, double t, double dt)
ippl::Vector< double, 3 > getOrigin() const
ippl::Vector< double, 3 > rotateFrom(const ippl::Vector< double, 3 > &r) const
ippl::Vector< double, 3 > rotateTo(const ippl::Vector< double, 3 > &r) const
matrix_t getRotationMatrix() const
ippl::Vector< double, 3 > transformTo(const ippl::Vector< double, 3 > &r) const
CoordinateSystemTrafo inverted() const
std::set< std::shared_ptr< Component > > value_t
Definition IndexMap.h:47
IndexMap::value_t query(IndexMap::key_t::first_type step, IndexMap::key_t::second_type length)
BoundingBox getBoundingBox() const
virtual void visitScalingFFAMagnet(const ScalingFFAMagnet &bend)
Apply the algorithm to a scaling FFA.
void pushParticles(const BorisPusher &pusher)
void emitParticles(long long step)
void updateRFElement(std::string elName, double maxPhi)
void changeDT(bool backTrack=false)
IpplTimings::TimerRef BinRepartTimer_m
DataSink * itsDataSink_m
virtual void visitOffset(const Offset &)
Apply the algorithm to a offset (placement).
beamline_list FieldDimensions
void autophaseCavities(const BorisPusher &pusher)
bool applyPluginElements(const double dt)
IpplTimings::TimerRef OrbThreader_m
virtual void execute()
Apply the algorithm to the top-level beamline.
std::vector< PluginElement * > pluginElements_m
void kickParticles(const BorisPusher &pusher)
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)
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
void computeSpaceChargeFields(unsigned long long step)
std::pair< ElementType, element_pair > type_pair
bool hasEndOfLineReached(const BoundingBox &globalBoundingBox)
WakeFunction * wakeFunction_m
void dumpStats(long long step, bool psDump, bool statDump)
IpplTimings::TimerRef timeIntegrationTimer1_m
IpplTimings::TimerRef PluginElemTimer_m
void selectDT(bool backTrack=false)
void findStartPosition(const BorisPusher &pusher)
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
Quaternion conjugate() const
double getdT() const
void shiftZStopLeft(double back)
double getZStop() const
bool reachedEnd() const
Tracker(const Beamline &, const PartData &, bool backBeam, bool backTrack)
Constructor.
Definition Tracker.cpp:75
const Beamline & itsBeamline_m
Definition Tracker.h:119
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
bool getRelativeFlag() const
Definition TBeamline.h:423
Quaternion getInitialDirection() const
Definition TBeamline.h:413
Vector_t< double, 3 > getOrigin3D() const
Definition TBeamline.h:403
virtual void iterate(BeamlineVisitor &, bool r2l) const
Apply visitor to all elements of the line.
Definition TBeamline.h:197
void merge(OpalBeamline &rhs)
void swap(OpalBeamline &rhs)
KOKKOS_INLINE_FUNCTION void kick(const Vector_t< double, 3 > &R, Vector_t< double, 3 > &P, const Vector_t< double, 3 > &Ef, const Vector_t< double, 3 > &Bf, const double &dt) const
Definition BorisPusher.h:67
KOKKOS_INLINE_FUNCTION void push(Vector_t< double, 3 > &R, const Vector_t< double, 3 > &P, const double &dt) const
bool isOutside(const Vector_t< double, 3 > &position) const
Definition BoundingBox.h:60
The base class for all OPAL exceptions.
std::string time() const
Return time.
Definition Timer.cpp:42
virtual double getReal() const
Return value.