OPAL (Object Oriented Parallel Accelerator Library) 2022.1
OPAL
PartBunchBase.hpp
Go to the documentation of this file.
1//
2// Class PartBunchBase
3// Base class for representing particle bunches.
4//
5// Copyright (c) 2008 - 2021, Paul Scherrer Institut, Villigen PSI, Switzerland
6// All rights reserved
7//
8// This file is part of OPAL.
9//
10// OPAL is free software: you can redistribute it and/or modify
11// it under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// You should have received a copy of the GNU General Public License
16// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
17//
18#ifndef PART_BUNCH_BASE_HPP
19#define PART_BUNCH_BASE_HPP
20
22#include "Algorithms/PartBins.h"
24#include "Algorithms/PartData.h"
27#include "Physics/Physics.h"
31#include "Utilities/Options.h"
33#include "Utilities/Util.h"
34
35#include <cmath>
36#include <numeric>
37
38extern Inform* gmsg;
39
40template <class T, unsigned Dim>
42 : R(*(pb->R_p)),
43 ID(*(pb->ID_p)),
44 pbin_m(nullptr),
45 pmsg_m(nullptr),
46 f_stream(nullptr),
47 fixed_grid(false),
48 reference(ref),
49 unit_state_(units),
50 stateOfLastBoundP_(unitless),
51 dt_m(0.0),
52 t_m(0.0),
53 spos_m(0.0),
54 globalMeanR_m(Vector_t(0.0, 0.0, 0.0)),
55 globalToLocalQuaternion_m(Quaternion_t(1.0, 0.0, 0.0, 0.0)),
56 rmax_m(0.0),
57 rmin_m(0.0),
58 rmsDensity_m(0.0),
59 hr_m(-1.0),
60 nr_m(0),
61 fs_m(nullptr),
62 couplingConstant_m(0.0),
63 qi_m(0.0),
64 massPerParticle_m(0.0),
65 distDump_m(0),
66 dh_m(1e-12),
67 tEmission_m(0.0),
68 bingamma_m(nullptr),
69 binemitted_m(nullptr),
70 stepsPerTurn_m(0),
71 localTrackStep_m(0),
72 globalTrackStep_m(0),
73 numBunch_m(1),
74 bunchTotalNum_m(1),
75 bunchLocalNum_m(1),
76 SteptoLastInj_m(0),
77 globalPartPerNode_m(nullptr),
78 dist_m(nullptr),
79 dcBeam_m(false),
80 periodLength_m(Physics::c / 1e9),
81 pbase_m(pb)
82{
83 setup(pb);
84}
86/*
87 * Bunch common member functions
88 */
90template <class T, unsigned Dim>
92 if (dist_m != nullptr) {
93 size_t isBeamEmitted = dist_m->getIfDistEmitting();
94 reduce(isBeamEmitted, isBeamEmitted, OpAddAssign());
95 if (isBeamEmitted > 0)
96 return true;
97 else
98 return false;
99 } else
100 return false;
101}
102
103
104template <class T, unsigned Dim>
106 /*
107 * Get maximum last emitted energy bin.
108 */
109 int lastEmittedBin = dist_m->getLastEmittedEnergyBin();
110 reduce(lastEmittedBin, lastEmittedBin, OpMaxAssign());
111 return lastEmittedBin;
112}
114
115template <class T, unsigned Dim>
117 return dist_m->getNumberOfEmissionSteps();
118}
120
121template <class T, unsigned Dim>
123 return dist_m->getNumberOfEnergyBins();
124}
125
126
127template <class T, unsigned Dim>
130 size_t isBeamEmitting = dist_m->getIfDistEmitting();
131 reduce(isBeamEmitting, isBeamEmitting, OpAddAssign());
132 if (isBeamEmitting > 0) {
133 *gmsg << "*****************************************************" << endl
134 << "Warning: attempted to rebin, but not all distribution" << endl
135 << "particles have been emitted. Rebin failed." << endl
136 << "*****************************************************" << endl;
137 } else {
138 if (dist_m->Rebin())
139 this->Bin = 0;
141}
143
144template <class T, unsigned Dim>
145void PartBunchBase<T, Dim>::setEnergyBins(int numberOfEnergyBins) {
146 bingamma_m = std::unique_ptr<double[]>(new double[numberOfEnergyBins]);
147 binemitted_m = std::unique_ptr<size_t[]>(new size_t[numberOfEnergyBins]);
148 for (int i = 0; i < numberOfEnergyBins; i++)
149 binemitted_m[i] = 0;
150}
152
153template <class T, unsigned Dim>
155
156 if (dist_m != nullptr)
157 return dist_m->getNumberOfEnergyBins() > 0;
158 else
159 return false;
160}
161
163template <class T, unsigned Dim>
165
166 if (unit_state_ == unitless)
167 throw SwitcherError("PartBunch::switchToUnitlessPositions",
168 "Cannot make a unitless PartBunch unitless");
169
170 bool hasToReset = false;
171 if (!R.isDirty()) hasToReset = true;
172
173 for (size_t i = 0; i < getLocalNum(); i++) {
174 double dt = getdT();
175 if (use_dt_per_particle)
176 dt = this->dt[i];
177
178 R[i] /= Vector_t(Physics::c * dt);
179 }
180
181 unit_state_ = unitless;
183 if (hasToReset) R.resetDirtyFlag();
184}
186//FIXME: unify methods, use convention that all particles have own dt
187template <class T, unsigned Dim>
190 if (unit_state_ == units)
191 throw SwitcherError("PartBunch::switchOffUnitlessPositions",
192 "Cannot apply units twice to PartBunch");
194 bool hasToReset = false;
195 if (!R.isDirty()) hasToReset = true;
196
197 for (size_t i = 0; i < getLocalNum(); i++) {
198 double dt = getdT();
199 if (use_dt_per_particle)
200 dt = this->dt[i];
202 R[i] *= Vector_t(Physics::c * dt);
204
205 unit_state_ = units;
206
207 if (hasToReset) R.resetDirtyFlag();
208}
210
211template <class T, unsigned Dim>
213 // do nothing here
214}
216
217template <class T, unsigned Dim>
219 std::vector<Distribution*> addedDistributions,
220 size_t& np) {
221 Inform m("setDistribution " );
222 dist_m = d;
223 dist_m->createOpalT(this, addedDistributions, np);
224
225// if (Options::cZero)
226// dist_m->create(this, addedDistributions, np / 2);
227// else
228// dist_m->create(this, addedDistributions, np);
229}
230
231template <class T, unsigned Dim>
233 size_t numberOfParticles,
234 double current,
235 const Beamline& bl) {
236 dist_m = d;
237 dist_m->createOpalCycl(this, numberOfParticles, current, bl);
238}
239
240
241template <class T, unsigned Dim>
243 return fixed_grid;
244}
245
246
247template <class T, unsigned Dim>
249 return (pbin_m != nullptr);
250}
251
252
253template <class T, unsigned Dim>
255 tEmission_m = t;
256}
257
258
259template <class T, unsigned Dim>
261 return tEmission_m;
262}
263
264
265template <class T, unsigned Dim>
267 if (dist_m != nullptr)
268 return dist_m->getIfDistEmitting();
269 else
270 return false;
271}
272
273
274template <class T, unsigned Dim>
276 if (pbin_m != nullptr)
277 return pbin_m->weHaveBins();
278 else
279 return false;
280}
281
282
283template <class T, unsigned Dim>
285 pbin_m = pbin;
286 *gmsg << *pbin_m << endl;
287 setEnergyBins(pbin_m->getNBins());
288}
289
290
291template <class T, unsigned Dim>
293 pbin_m = pbin;
294 setEnergyBins(pbin_m->getNBins());
296
298template <class T, unsigned Dim>
300 return dist_m->emitParticles(this, eZ);
301}
302
303
304template <class T, unsigned Dim>
306 size_t numParticles = getLocalNum();
307 reduce(numParticles, numParticles, OpAddAssign());
308 setTotalNum(numParticles);
310
312template <class T, unsigned Dim>
314 this->Bin = 0;
315 pbin_m->resetBins();
316 // delete pbin_m; we did not allocate it!
317 pbin_m = nullptr;
321template <class T, unsigned Dim>
323 if (pbin_m != nullptr)
324 return pbin_m->getLastemittedBin();
325 else
326 return 0;
330template <class T, unsigned Dim>
332 if (pbin_m != nullptr) {
333 pbin_m->setPartNum(bin, num);
338template <class T, unsigned Dim>
341 const int emittedBins = dist_m->getNumberOfEnergyBins();
343 size_t s = 0;
345 for (int i = 0; i < emittedBins; i++)
346 bingamma_m[i] = 0.0;
348 for (unsigned int n = 0; n < getLocalNum(); n++)
349 bingamma_m[this->Bin[n]] += std::sqrt(1.0 + dot(this->P[n], this->P[n]));
350
351 std::unique_ptr<size_t[]> particlesInBin(new size_t[emittedBins]);
352 reduce(bingamma_m.get(), bingamma_m.get() + emittedBins, bingamma_m.get(), OpAddAssign());
353 reduce(binemitted_m.get(), binemitted_m.get() + emittedBins, particlesInBin.get(), OpAddAssign());
354 for (int i = 0; i < emittedBins; i++) {
355 size_t &pInBin = particlesInBin[i];
356 if (pInBin != 0) {
357 bingamma_m[i] /= pInBin;
358 INFOMSG(level2 << "Bin " << std::setw(3) << i
359 << " gamma = " << std::setw(8) << std::scientific
360 << std::setprecision(5) << bingamma_m[i]
361 << "; NpInBin= " << std::setw(8)
362 << std::setfill(' ') << pInBin << endl);
363 } else {
364 bingamma_m[i] = 1.0;
365 INFOMSG(level2 << "Bin " << std::setw(3) << i << " has no particles " << endl);
366 }
367 s += pInBin;
368 }
369 particlesInBin.reset();
371
372 if (s != getTotalNum() && !OpalData::getInstance()->hasGlobalGeometry())
373 ERRORMSG("sum(Bins)= " << s << " != sum(R)= " << getTotalNum() << endl;);
375 if (emittedBins >= 2) {
376 for (int i = 1; i < emittedBins; i++) {
377 if (binemitted_m[i - 1] != 0 && binemitted_m[i] != 0)
378 INFOMSG(level2 << "d(gamma)= " << 100.0 * std::abs(bingamma_m[i - 1] - bingamma_m[i]) / bingamma_m[i] << " [%] "
379 << "between bin " << i - 1 << " and " << i << endl);
382}
383
385template <class T, unsigned Dim>
387
388 const int emittedBins = pbin_m->getLastemittedBin();
390 for (int i = 0; i < emittedBins; i++)
391 bingamma_m[i] = 0.0;
392 for (unsigned int n = 0; n < getLocalNum(); n++) {
393 if ( this->Bin[n] > -1 ) {
394 bingamma_m[this->Bin[n]] += std::sqrt(1.0 + dot(this->P[n], this->P[n]));
395 }
398 allreduce(*bingamma_m.get(), emittedBins, std::plus<double>());
400 for (int i = 0; i < emittedBins; i++) {
401 if (pbin_m->getTotalNumPerBin(i) > 0) {
402 bingamma_m[i] /= pbin_m->getTotalNumPerBin(i);
403 } else {
404 bingamma_m[i] = 0.0;
406 INFOMSG("Bin " << i << " : particle number = " << pbin_m->getTotalNumPerBin(i)
407 << " gamma = " << bingamma_m[i] << endl);
411
412template <class T, unsigned Dim>
414 momentsComputer_m.computeDebyeLength(*this, rmsDensity_m);
415
417
418
419template <class T, unsigned Dim>
421 return bingamma_m[bin];
422}
423
425template <class T, unsigned Dim>
426void PartBunchBase<T, Dim>::setBinCharge(int bin, double q) {
427 this->Q = where(eq(this->Bin, bin), q, 0.0);
431template <class T, unsigned Dim>
433 this->Q = where(eq(this->Bin, bin), this->qi_m, 0.0);
437template <class T, unsigned Dim>
440 std::size_t localnum = 0;
441 const Vector_t meanR = get_rmean();
443 for (unsigned long k = 0; k < getLocalNum(); ++ k)
444 if (std::abs(R[k](0) - meanR(0)) > x(0) ||
445 std::abs(R[k](1) - meanR(1)) > x(1) ||
446 std::abs(R[k](2) - meanR(2)) > x(2)) {
447
448 ++localnum;
449 }
450
451 gather(&localnum, &globalPartPerNode_m[0], 1);
452
453 size_t npOutside = std::accumulate(globalPartPerNode_m.get(),
454 globalPartPerNode_m.get() + Ippl::getNodes(), 0,
455 std::plus<size_t>());
456
457 return npOutside;
458}
460
470template <class T, unsigned Dim>
472 std::vector<double>& lineDensity,
473 std::pair<double, double>& meshInfo) {
474 Vector_t rmin, rmax;
475 get_bounds(rmin, rmax);
476
477 if (nBins < 2) {
478 Vektor<int, 3>/*NDIndex<3>*/ grid;
479 this->updateDomainLength(grid);
480 nBins = grid[2];
481 }
482
483 double length = rmax(2) - rmin(2);
484 double zmin = rmin(2) - dh_m * length, zmax = rmax(2) + dh_m * length;
485 double hz = (zmax - zmin) / (nBins - 2);
486 double perMeter = 1.0 / hz;//(zmax - zmin);
487 zmin -= hz;
488
489 lineDensity.resize(nBins, 0.0);
490 std::fill(lineDensity.begin(), lineDensity.end(), 0.0);
491
492 const unsigned int lN = getLocalNum();
493 for (unsigned int i = 0; i < lN; ++ i) {
494 const double z = R[i](2) - 0.5 * hz;
495 unsigned int idx = (z - zmin) / hz;
496 double tau = (z - zmin) / hz - idx;
497
498 lineDensity[idx] += Q[i] * (1.0 - tau) * perMeter;
499 lineDensity[idx + 1] += Q[i] * tau * perMeter;
500 }
501
502 reduce(&(lineDensity[0]), &(lineDensity[0]) + nBins, &(lineDensity[0]), OpAddAssign());
503
504 meshInfo.first = zmin;
505 meshInfo.second = hz;
506}
507
508
509template <class T, unsigned Dim>
511 /*
512 Assume rmin_m < 0.0
513 */
514
516 //if (!R.isDirty() && stateOfLastBoundP_ == unit_state_) return;
517 if ( !(R.isDirty() || ID.isDirty() ) && stateOfLastBoundP_ == unit_state_) return; //-DW
519 stateOfLastBoundP_ = unit_state_;
520
521 if (!isGridFixed()) {
522 const int dimIdx = (dcBeam_m? 2: 3);
523
530 this->updateDomainLength(nr_m);
531 IpplTimings::startTimer(boundpBoundsTimer_m);
532 get_bounds(rmin_m, rmax_m);
533 IpplTimings::stopTimer(boundpBoundsTimer_m);
534 Vector_t len = rmax_m - rmin_m;
536 double volume = 1.0;
537 for (int i = 0; i < dimIdx; i++) {
538 double length = std::abs(rmax_m[i] - rmin_m[i]);
539 if (length < 1e-10) {
540 rmax_m[i] += 1e-10;
541 rmin_m[i] -= 1e-10;
542 } else {
543 rmax_m[i] += dh_m * length;
544 rmin_m[i] -= dh_m * length;
546 hr_m[i] = (rmax_m[i] - rmin_m[i]) / (nr_m[i] - 1);
547 }
548 if (dcBeam_m) {
549 rmax_m[2] = rmin_m[2] + periodLength_m;
550 hr_m[2] = periodLength_m / (nr_m[2] - 1);
551 }
552 for (int i = 0; i < dimIdx; ++ i) {
553 volume *= std::abs(rmax_m[i] - rmin_m[i]);
554 }
555
556 if (getIfBeamEmitting() && dist_m != nullptr) {
557 // keep particles per cell ratio high, don't spread a hand full particles across the whole grid
558 double percent = std::max(1.0 / (nr_m[2] - 1), dist_m->getPercentageEmitted());
559 double length = std::abs(rmax_m[2] - rmin_m[2]) / (1.0 + 2 * dh_m);
560 if (percent < 1.0 && percent > 0.0) {
561 rmax_m[2] -= dh_m * length;
562 rmin_m[2] = rmax_m[2] - length / percent;
563
564 length /= percent;
565
566 rmax_m[2] += dh_m * length;
567 rmin_m[2] -= dh_m * length;
568
569 hr_m[2] = (rmax_m[2] - rmin_m[2]) / (nr_m[2] - 1);
570 }
571 }
572
573 if (volume < 1e-21 && getTotalNum() > 1 && std::abs(sum(Q)) > 0.0) {
574 WARNMSG(level1 << "!!! Extremely high particle density detected !!!" << endl);
575 }
576 //INFOMSG("It is a full boundp hz= " << hr_m << " rmax= " << rmax_m << " rmin= " << rmin_m << endl);
577
578 if (hr_m[0] * hr_m[1] * hr_m[2] <= 0) {
579 throw GeneralClassicException("boundp() ", "h<0, can not build a mesh");
580 }
581
582 Vector_t origin = rmin_m - Vector_t(hr_m[0] / 2.0, hr_m[1] / 2.0, hr_m[2] / 2.0);
583 this->updateFields(hr_m, origin);
584
585 if (fs_m->getFieldSolverType() == FieldSolverType::P3M) {
586 Layout_t* layoutp = static_cast<Layout_t*>(&getLayout());
587 layoutp->setCacheDimension(0,fs_m->solver_m->getinteractionRadius());
588 layoutp->setCacheDimension(1,fs_m->solver_m->getinteractionRadius());
589
590 double gammaz = sum(this->P)[2] / getTotalNum();
591 gammaz *= gammaz;
592 gammaz = std::sqrt(gammaz + 1.0);
593
594 //Interaction radius is set in the boosted frame but ghost particles
595 //are identified in the lab frame that's why we divide by gammaz here
596 layoutp->setCacheDimension(2,fs_m->solver_m->getinteractionRadius()/gammaz);
597 layoutp->enableCaching();
598 }
599
600 }
601 IpplTimings::startTimer(boundpUpdateTimer_m);
602 update();
603 IpplTimings::stopTimer(boundpUpdateTimer_m);
604 R.resetDirtyFlag();
605
606 IpplTimings::stopTimer(boundpTimer_m);
607}
608
610template <class T, unsigned Dim>
612
613 Vector_t len;
614 const int dimIdx = 3;
615 IpplTimings::startTimer(boundpTimer_m);
616
617 std::unique_ptr<size_t[]> countLost;
618 if (weHaveBins()) {
619 const int tempN = pbin_m->getLastemittedBin();
620 countLost = std::unique_ptr<size_t[]>(new size_t[tempN]);
621 for (int ii = 0; ii < tempN; ii++) countLost[ii] = 0;
622 }
623
624 this->updateDomainLength(nr_m);
625
626 IpplTimings::startTimer(boundpBoundsTimer_m);
627 get_bounds(rmin_m, rmax_m);
628 IpplTimings::stopTimer(boundpBoundsTimer_m);
629
630 len = rmax_m - rmin_m;
631
632 calcBeamParameters();
633
634 int checkfactor = Options::remotePartDel;
635 if (checkfactor != 0) {
636 //INFOMSG("checkfactor= " << checkfactor << endl);
637 // check the bunch if its full size is larger than checkfactor times of its rms size
638 Vector_t rmean = momentsComputer_m.getMeanPosition();
639 Vector_t rrms = momentsComputer_m.getStandardDeviationPosition();
640 if(checkfactor < 0) {
641 checkfactor *= -1;
642 if (len[0] > checkfactor * rrms[0] ||
643 len[1] > checkfactor * rrms[1] ||
644 len[2] > checkfactor * rrms[2])
645 {
646 for(unsigned int ii = 0; ii < this->getLocalNum(); ii++) {
647 /* delete the particle if the distance to the beam center
648 * is larger than 8 times of beam's rms size
649 */
650 if (std::abs(R[ii](0) - rmean(0)) > checkfactor * rrms[0] ||
651 std::abs(R[ii](1) - rmean(1)) > checkfactor * rrms[1] ||
652 std::abs(R[ii](2) - rmean(2)) > checkfactor * rrms[2])
653 {
654 // put particle onto deletion list
655 destroy(1, ii);
656 //update bin parameter
657 if (weHaveBins())
658 countLost[Bin[ii]] += 1 ;
659 /* INFOMSG("REMOTE PARTICLE DELETION: ID = " << ID[ii] << ", R = " << R[ii]
660 * << ", beam rms = " << rrms_m << endl;);
661 */
662 }
663 }
664 }
665 }
666 else {
667 if (len[0] > checkfactor * rrms[0] ||
668 len[2] > checkfactor * rrms[2])
669 {
670 for(unsigned int ii = 0; ii < this->getLocalNum(); ii++) {
671 /* delete the particle if the distance to the beam center
672 * is larger than 8 times of beam's rms size
673 */
674 if (std::abs(R[ii](0) - rmean(0)) > checkfactor * rrms[0] ||
675 std::abs(R[ii](2) - rmean(2)) > checkfactor * rrms[2])
676 {
677 // put particle onto deletion list
678 destroy(1, ii);
679 //update bin parameter
680 if (weHaveBins())
681 countLost[Bin[ii]] += 1 ;
682 /* INFOMSG("REMOTE PARTICLE DELETION: ID = " << ID[ii] << ", R = " << R[ii]
683 * << ", beam rms = " << rrms_m << endl;);
684 */
685 }
686 }
687 }
688 }
689 }
690
691 for (int i = 0; i < dimIdx; i++) {
692 double length = std::abs(rmax_m[i] - rmin_m[i]);
693 rmax_m[i] += dh_m * length;
694 rmin_m[i] -= dh_m * length;
695 hr_m[i] = (rmax_m[i] - rmin_m[i]) / (nr_m[i] - 1);
696 }
697
698 // rescale mesh
699 this->updateFields(hr_m, rmin_m);
700
701 if (weHaveBins()) {
702 pbin_m->updatePartInBin_cyc(countLost.get());
703 }
704
705 /* we also need to update the number of particles per bunch
706 * expensive since does an allreduce!
707 */
708 countTotalNumPerBunch();
709
710 IpplTimings::startTimer(boundpUpdateTimer_m);
711 update();
712 IpplTimings::stopTimer(boundpUpdateTimer_m);
713
714 IpplTimings::stopTimer(boundpTimer_m);
715}
716
717
718template <class T, unsigned Dim>
720
721 this->updateDomainLength(nr_m);
722
723 std::vector<size_t> tmpbinemitted;
724
725 boundp();
726
727 size_t ne = 0;
728 const size_t localNum = getLocalNum();
729
730 double rzmean = momentsComputer_m.getMeanPosition()(2);
731 double rzrms = momentsComputer_m.getStandardDeviationPosition()(2);
732 const bool haveEnergyBins = weHaveEnergyBins();
733 if (haveEnergyBins) {
734 tmpbinemitted.resize(getNumberOfEnergyBins(), 0.0);
735 }
736 for (unsigned int i = 0; i < localNum; i++) {
737 if (Bin[i] < 0 || (Options::remotePartDel > 0 && std::abs(R[i](2) - rzmean) < Options::remotePartDel * rzrms)) {
738 ne++;
739 destroy(1, i);
740 } else if (haveEnergyBins) {
741 tmpbinemitted[Bin[i]]++;
742 }
743 }
744
745 boundp();
746
747 calcBeamParameters();
748 gatherLoadBalanceStatistics();
749
750 if (haveEnergyBins) {
751 const int lastBin = dist_m->getLastEmittedEnergyBin();
752 for (int i = 0; i < lastBin; i++) {
753 binemitted_m[i] = tmpbinemitted[i];
754 }
755 }
756 reduce(ne, ne, OpAddAssign());
757 return ne;
758}
759
760
761template <class T, unsigned Dim>
763
764 std::unique_ptr<size_t[]> tmpbinemitted;
765
766 const size_t localNum = getLocalNum();
767 const size_t totalNum = getTotalNum();
768 size_t ne = 0;
769
770 if (weHaveEnergyBins()) {
771 tmpbinemitted = std::unique_ptr<size_t[]>(new size_t[getNumberOfEnergyBins()]);
772 for (int i = 0; i < getNumberOfEnergyBins(); i++) {
773 tmpbinemitted[i] = 0;
774 }
775 for (unsigned int i = 0; i < localNum; i++) {
776 if (Bin[i] < 0) {
777 destroy(1, i);
778 ++ ne;
779 } else
780 tmpbinemitted[Bin[i]]++;
781 }
782 } else {
783 Inform dmsg("destroy: ", INFORM_ALL_NODES);
784 for (size_t i = 0; i < localNum; i++) {
785 if ((Bin[i] < 0)) {
786 ne++;
787 destroy(1, i);
788 }
789 }
790 }
791
792 if (ne > 0) {
793 performDestroy(true);
794 }
795
796 calcBeamParameters();
797 gatherLoadBalanceStatistics();
798
799 if (weHaveEnergyBins()) {
800 const int lastBin = dist_m->getLastEmittedEnergyBin();
801 for (int i = 0; i < lastBin; i++) {
802 binemitted_m[i] = tmpbinemitted[i];
803 }
804 }
805 size_t newTotalNum = getLocalNum();
806 reduce(newTotalNum, newTotalNum, OpAddAssign());
807
808 setTotalNum(newTotalNum);
809
810 return totalNum - newTotalNum;
811}
812
813
814template <class T, unsigned Dim>
816 return 0.0;
817}
818
819template <class T, unsigned Dim>
821 return 0.0;
822}
823
824template <class T, unsigned Dim>
826 return 0.0;
827}
828
829template <class T, unsigned Dim>
831 return 0.0;
832}
833
834template <class T, unsigned Dim>
836 return 0;
837}
838
839//ff
840template <class T, unsigned Dim>
842 return this->R[i](0);
843}
844
845//ff
846template <class T, unsigned Dim>
848 return this->R[i](1);
849}
850
851//ff
852template <class T, unsigned Dim>
854 return this->R[i](2);
855}
856
857//ff
858template <class T, unsigned Dim>
860 return 0.0;
861}
862
863//ff
864template <class T, unsigned Dim>
866 return 0.0;
867}
868
869
870template <class T, unsigned Dim>
871void PartBunchBase<T, Dim>::setZ(int /*i*/, double /*zcoo*/) {
872};
873
874
875template <class T, unsigned Dim>
877
878 this->getLocalBounds(rmin, rmax);
879
880 double min[2*Dim];
881
882 for (unsigned int i = 0; i < Dim; ++i) {
883 min[2*i] = rmin[i];
884 min[2*i + 1] = -rmax[i];
885 }
886
887 allreduce(min, 2*Dim, std::less<double>());
888
889 for (unsigned int i = 0; i < Dim; ++i) {
890 rmin[i] = min[2*i];
891 rmax[i] = -min[2*i + 1];
892 }
893}
894
895
896template <class T, unsigned Dim>
898 const size_t localNum = getLocalNum();
899 if (localNum == 0) {
900 double maxValue = 1e8;
901 rmin = Vector_t(maxValue, maxValue, maxValue);
902 rmax = Vector_t(-maxValue, -maxValue, -maxValue);
903 return;
904 }
905
906 rmin = R[0];
907 rmax = R[0];
908 for (size_t i = 1; i < localNum; ++ i) {
909 for (unsigned short d = 0; d < 3u; ++ d) {
910 if (rmin(d) > R[i](d)) rmin(d) = R[i](d);
911 else if (rmax(d) < R[i](d)) rmax(d) = R[i](d);
912 }
913 }
914}
915
916
917template <class T, unsigned Dim>
918std::pair<Vector_t, double> PartBunchBase<T, Dim>::getBoundingSphere() {
919 Vector_t rmin, rmax;
920 get_bounds(rmin, rmax);
921
922 std::pair<Vector_t, double> sphere;
923 sphere.first = 0.5 * (rmin + rmax);
924 sphere.second = std::sqrt(dot(rmax - sphere.first, rmax - sphere.first));
925
926 return sphere;
927}
928
929
930template <class T, unsigned Dim>
932 Vector_t rmin, rmax;
933 getLocalBounds(rmin, rmax);
934
935 std::pair<Vector_t, double> sphere;
936 sphere.first = 0.5 * (rmin + rmax);
937 sphere.second = std::sqrt(dot(rmax - sphere.first, rmax - sphere.first));
938
939 return sphere;
940}
941
942
943template <class T, unsigned Dim>
945 Inform msg("PartBunch ");
946
947 size_t i = getLocalNum();
948 create(1);
949
950 R[i] = particle.getR();
951 P[i] = particle.getP();
952
953 update();
954 msg << "Created one particle i= " << i << endl;
955}
956
957
958template <class T, unsigned Dim>
960 R[ii](0) = z[0];
961 P[ii](0) = z[1];
962 R[ii](1) = z[2];
963 P[ii](1) = z[3];
964 R[ii](2) = z[4];
965 P[ii](2) = z[5];
966}
967
968
969template <class T, unsigned Dim>
971 R[ii] = particle.getR();
972 P[ii] = particle.getP();
973}
974
975
976template <class T, unsigned Dim>
978 OpalParticle particle(ID[ii],
979 Vector_t(R[ii](0), R[ii](1), 0), P[ii],
980 R[ii](2), Q[ii], M[ii]);
981 return particle;
982}
983
984
985template <class T, unsigned Dim>
987 double& axmax, double& aymax) {
988 axmax = aymax = 0.0;
989 OpalParticle particle;
990
991 for (unsigned int ii = 0; ii < getLocalNum(); ii++) {
992
993 particle = getParticle(ii);
994 FVector<double, 6> vec({particle.getX(), particle.getPx(),
995 particle.getY(), particle.getPy(),
996 particle.getZ(), particle.getPz()});
997 FVector<double, 6> result;
998 result = D * vec;
999 // double xnor =
1000 // D(0, 0) * part.getX() + D(0, 1) * part.getPx() + D(0, 2) * part.getY() +
1001 // D(0, 3) * part.getPy() + D(0, 4) * part.getL() + D(0, 5) * part.getPLon();
1002 // double pxnor =
1003 // D(1, 0) * part.getX() + D(1, 1) * part.getPx() + D(1, 2) * part.getY() +
1004 // D(1, 3) * part.getPy() + D(1, 4) * part.getL() + D(1, 5) * part.getPLon();
1005 // double ynor =
1006 // D(2, 0) * part.getX() + D(2, 1) * part.getPx() + D(2, 2) * part.getY() +
1007 // D(2, 3) * part.getPy() + D(2, 4) * part.getL() + D(2, 5) * part.getPLon();
1008 // double pynor =
1009 // D(3, 0) * part.getX() + D(3, 1) * part.getPx() + D(3, 2) * part.getY() +
1010 // D(3, 3) * part.getPy() + D(3, 4) * part.getL() + D(3, 5) * part.getPLon();
1011
1012 axmax = std::max(axmax, (std::pow(result[0], 2) + std::pow(result[1], 2)));
1013 aymax = std::max(aymax, (std::pow(result[2], 2) + std::pow(result[3], 2)));
1014 }
1015}
1016
1017
1018template <class T, unsigned Dim>
1020 dt_m = dt;
1021}
1022
1023
1024template <class T, unsigned Dim>
1026 return dt_m;
1027}
1028
1029
1030template <class T, unsigned Dim>
1032 t_m = t;
1033}
1034
1035
1036template <class T, unsigned Dim>
1038 t_m += dt_m;
1039}
1040
1041
1042template <class T, unsigned Dim>
1044 return t_m;
1045}
1046
1047
1048template <class T, unsigned Dim>
1050 return spos_m;
1051}
1052
1053
1054template <class T, unsigned Dim>
1056 spos_m = s;
1057}
1058
1059
1060template <class T, unsigned Dim>
1062 return momentsComputer_m.getMeanGamma();
1063}
1064
1065
1066template <class T, unsigned Dim>
1068 return momentsComputer_m.getMeanKineticEnergy();
1069}
1070
1071
1072template <class T, unsigned Dim>
1074 return momentsComputer_m.getTemperature();
1075}
1076
1077template <class T, unsigned Dim>
1079 return momentsComputer_m.getDebyeLength();
1080}
1081
1082template <class T, unsigned Dim>
1084 return momentsComputer_m.getPlasmaParameter();
1085}
1086
1087template <class T, unsigned Dim>
1089 return rmsDensity_m;
1090}
1091
1092template <class T, unsigned Dim>
1094 return rmin_m;
1095}
1096
1097
1098template <class T, unsigned Dim>
1100 return rmax_m;
1101}
1102
1103
1104template <class T, unsigned Dim>
1106 return momentsComputer_m.getMeanPosition();
1107}
1108
1109
1110template <class T, unsigned Dim>
1112 return momentsComputer_m.getStandardDeviationPosition();
1113}
1114
1115
1116template <class T, unsigned Dim>
1118 return momentsComputer_m.getStandardDeviationRP();
1119}
1120
1121
1122template <class T, unsigned Dim>
1124 return momentsComputer_m.getMeanPosition();
1125}
1126
1127
1128template <class T, unsigned Dim>
1130 return momentsComputer_m.getStandardDeviationMomentum();
1131}
1132
1133
1134template <class T, unsigned Dim>
1136 return momentsComputer_m.getMeanMomentum();
1137}
1138
1139
1140template <class T, unsigned Dim>
1142 if (dist_m)// && dist_m->getType() != DistrTypeT::FROMFILE)
1143 return dist_m->get_pmean();
1144
1145 double gamma = 0.1 / getM() + 1; // set default 0.1 eV
1146 return Vector_t(0, 0, std::sqrt(std::pow(gamma, 2) - 1));
1147}
1148
1149
1150template <class T, unsigned Dim>
1152 return momentsComputer_m.getGeometricEmittance();
1153}
1154
1155
1156template <class T, unsigned Dim>
1158 return momentsComputer_m.getNormalizedEmittance();
1159}
1160
1161
1162template <class T, unsigned Dim>
1164 return momentsComputer_m.getHalo();
1165}
1166
1167template <class T, unsigned Dim>
1169 return momentsComputer_m.get68Percentile();
1170}
1171
1172template <class T, unsigned Dim>
1174 return momentsComputer_m.get95Percentile();
1175}
1176
1177template <class T, unsigned Dim>
1179 return momentsComputer_m.get99Percentile();
1180}
1181
1182template <class T, unsigned Dim>
1184 return momentsComputer_m.get99_99Percentile();
1185}
1186
1187template <class T, unsigned Dim>
1189 return momentsComputer_m.getNormalizedEmittance68Percentile();
1190}
1191
1192template <class T, unsigned Dim>
1194 return momentsComputer_m.getNormalizedEmittance95Percentile();
1195}
1196
1197template <class T, unsigned Dim>
1199 return momentsComputer_m.getNormalizedEmittance99Percentile();
1200}
1201
1202template <class T, unsigned Dim>
1204 return momentsComputer_m.getNormalizedEmittance99_99Percentile();
1205}
1206
1207template <class T, unsigned Dim>
1209 return momentsComputer_m.getDx();
1210}
1211
1212
1213template <class T, unsigned Dim>
1215 return momentsComputer_m.getDy();
1216}
1217
1218
1219template <class T, unsigned Dim>
1221 return momentsComputer_m.getDDx();
1222}
1223
1224
1225template <class T, unsigned Dim>
1227 return momentsComputer_m.getDDy();
1228}
1229
1230
1231template <class T, unsigned Dim>
1233 return hr_m;
1234}
1235
1236
1237template <class T, unsigned Dim>
1239 dh_m = dh;
1240}
1241
1242
1243template <class T, unsigned Dim>
1245
1246 for (int i = 0; i < Ippl::getNodes(); i++)
1247 globalPartPerNode_m[i] = 0;
1248
1249 std::size_t localnum = getLocalNum();
1250 gather(&localnum, &globalPartPerNode_m[0], 1);
1251}
1252
1253
1254template <class T, unsigned Dim>
1256 return globalPartPerNode_m[p];
1257}
1258
1259
1260template <class T, unsigned Dim>
1262 bounds(this->P, min, max);
1263}
1264
1265
1266template <class T, unsigned Dim>
1268
1269 IpplTimings::startTimer(statParamTimer_m);
1270 get_bounds(rmin_m, rmax_m);
1271 momentsComputer_m.compute(*this);
1272 IpplTimings::stopTimer(statParamTimer_m);
1273}
1274
1275template <class T, unsigned Dim>
1277 return couplingConstant_m;
1278}
1279
1280
1281template <class T, unsigned Dim>
1283 couplingConstant_m = c;
1284}
1285
1286
1287template <class T, unsigned Dim>
1289 qi_m = q;
1290 if (getTotalNum() != 0)
1291 Q = qi_m;
1292 else
1293 WARNMSG("Could not set total charge in PartBunch::setCharge based on getTotalNum" << endl);
1294}
1295
1296
1297template <class T, unsigned Dim>
1299 qi_m = q;
1300}
1301
1302
1303template <class T, unsigned Dim>
1305 massPerParticle_m = mass;
1306 if (getTotalNum() != 0)
1307 M = mass;
1308}
1309
1310template <class T, unsigned Dim>
1312 massPerParticle_m = mass;
1313}
1314
1315
1316template <class T, unsigned Dim>
1318 return sum(Q);
1319}
1320
1321
1322template <class T, unsigned Dim>
1324 return qi_m;
1325}
1326
1327template <class T, unsigned Dim>
1329 return massPerParticle_m;
1330}
1331
1332template <class T, unsigned Dim>
1334 fs_m = fs;
1335 fs_m->initSolver(this);
1336
1341 if (!OpalData::getInstance()->hasBunchAllocated()) {
1342 this->initialize(fs_m->getFieldLayout());
1343// this->setMesh(fs_m->getMesh());
1344// this->setFieldLayout(fs_m->getFieldLayout());
1345 }
1346
1347}
1348
1349
1350template <class T, unsigned Dim>
1352 if (fs_m)
1353 return fs_m->hasValidSolver();
1354 else
1355 return false;
1356}
1357
1358
1360template <class T, unsigned Dim>
1362 if (fs_m) {
1363 return fs_m->getFieldSolverType();
1364 } else {
1365 return FieldSolverType::NONE;
1366 }
1367}
1368
1369
1370template <class T, unsigned Dim>
1372 stepsPerTurn_m = n;
1373}
1374
1375
1376template <class T, unsigned Dim>
1378 return stepsPerTurn_m;
1379}
1380
1381
1382template <class T, unsigned Dim>
1384 globalTrackStep_m = n;
1385}
1386
1387
1388template <class T, unsigned Dim>
1390 return globalTrackStep_m;
1391}
1392
1393
1394template <class T, unsigned Dim>
1396 localTrackStep_m = n;
1397}
1398
1399
1400template <class T, unsigned Dim>
1402 globalTrackStep_m++; localTrackStep_m++;
1403}
1404
1405
1406template <class T, unsigned Dim>
1408 return localTrackStep_m;
1409}
1410
1411
1412template <class T, unsigned Dim>
1414 numBunch_m = n;
1415 bunchTotalNum_m.resize(n);
1416 bunchLocalNum_m.resize(n);
1417}
1418
1419
1420template <class T, unsigned Dim>
1422 return numBunch_m;
1423}
1424
1425
1426template <class T, unsigned Dim>
1427void PartBunchBase<T, Dim>::setTotalNumPerBunch(size_t totalnum, short n) {
1428 PAssert_LT(n, (short)bunchTotalNum_m.size());
1429 bunchTotalNum_m[n] = totalnum;
1430}
1431
1432
1433template <class T, unsigned Dim>
1435 PAssert_LT(n, (short)bunchTotalNum_m.size());
1436 return bunchTotalNum_m[n];
1437}
1438
1439
1440template <class T, unsigned Dim>
1441void PartBunchBase<T, Dim>::setLocalNumPerBunch(size_t localnum, short n) {
1442 PAssert_LT(n, (short)bunchLocalNum_m.size());
1443 bunchLocalNum_m[n] = localnum;
1444}
1445
1446
1447template <class T, unsigned Dim>
1449 PAssert_LT(n, (short)bunchLocalNum_m.size());
1450 return bunchLocalNum_m[n];
1451}
1452
1453
1454template <class T, unsigned Dim>
1456 bunchTotalNum_m.clear();
1457 bunchTotalNum_m.resize(numBunch_m);
1458 bunchLocalNum_m.clear();
1459 bunchLocalNum_m.resize(numBunch_m);
1460
1461 for (size_t i = 0; i < this->getLocalNum(); ++i) {
1462 PAssert_LT(this->bunchNum[i], numBunch_m);
1463 ++bunchLocalNum_m[this->bunchNum[i]];
1464 }
1465
1466 allreduce(bunchLocalNum_m.data(), bunchTotalNum_m.data(),
1467 bunchLocalNum_m.size(), std::plus<size_t>());
1468
1469 size_t totalnum = std::accumulate(bunchTotalNum_m.begin(),
1470 bunchTotalNum_m.end(), 0);
1471
1472 if ( totalnum != this->getTotalNum() )
1473 throw OpalException("PartBunchBase::countTotalNumPerBunch()",
1474 "Sum of total number of particles per bunch (" +
1475 std::to_string(totalnum) + ") != total number of particles (" +
1476 std::to_string(this->getTotalNum()) + ")");
1477}
1478
1479
1480template <class T, unsigned Dim>
1482 globalMeanR_m = globalMeanR;
1483}
1484
1485
1486template <class T, unsigned Dim>
1488 return globalMeanR_m;
1489}
1490
1491
1492template <class T, unsigned Dim>
1494
1495 globalToLocalQuaternion_m = globalToLocalQuaternion;
1496}
1497
1498
1499template <class T, unsigned Dim>
1501 return globalToLocalQuaternion_m;
1502}
1503
1504
1505template <class T, unsigned Dim>
1507 SteptoLastInj_m = n;
1508}
1509
1510
1511template <class T, unsigned Dim>
1513 return SteptoLastInj_m;
1514}
1515
1516
1517template <class T, unsigned Dim>
1519
1520 const int emittedBins = pbin_m->getLastemittedBin();
1521 double phi[emittedBins];
1522 double px[emittedBins];
1523 double py[emittedBins];
1524 double meanPhi = 0.0;
1525
1526 for (int ii = 0; ii < emittedBins; ii++) {
1527 phi[ii] = 0.0;
1528 px[ii] = 0.0;
1529 py[ii] = 0.0;
1530 }
1531
1532 for (unsigned int ii = 0; ii < getLocalNum(); ii++) {
1533 px[Bin[ii]] += P[ii](0);
1534 py[Bin[ii]] += P[ii](1);
1535 }
1536
1537 reduce(px, px + emittedBins, px, OpAddAssign());
1538 reduce(py, py + emittedBins, py, OpAddAssign());
1539 for (int ii = 0; ii < emittedBins; ii++) {
1540 phi[ii] = calculateAngle(px[ii], py[ii]);
1541 meanPhi += phi[ii];
1542 INFOMSG("Bin " << ii << " mean phi = " << phi[ii] * Units::rad2deg - 90.0 << "[degree]" << endl);
1543 }
1544
1545 meanPhi /= emittedBins;
1546
1547 INFOMSG("mean phi of all particles " << meanPhi * Units::rad2deg - 90.0 << "[degree]" << endl);
1548
1549 return meanPhi;
1550}
1551
1552// this function reset the BinID for each particles according to its current beta*gamma
1553// it is for multi-turn extraction cyclotron with small energy gain
1554// the bin number can be different with the bunch number
1555
1556template <class T, unsigned Dim>
1558
1559
1560 INFOMSG("Before reset Bin: " << endl);
1561 calcGammas_cycl();
1562 int maxbin = pbin_m->getNBins();
1563 size_t partInBin[maxbin];
1564 for (int ii = 0; ii < maxbin; ii++) partInBin[ii] = 0;
1565
1566 double pMin0 = 1.0e9;
1567 double pMin = 0.0;
1568 double maxbinIndex = 0;
1569
1570 for (unsigned long int n = 0; n < getLocalNum(); n++) {
1571 double temp_betagamma = std::sqrt(std::pow(P[n](0), 2) + std::pow(P[n](1), 2));
1572 if (pMin0 > temp_betagamma)
1573 pMin0 = temp_betagamma;
1574 }
1575 reduce(pMin0, pMin, OpMinAssign());
1576 INFOMSG("minimal beta*gamma = " << pMin << endl);
1577
1578 double asinh0 = std::asinh(pMin);
1579 for (unsigned long int n = 0; n < getLocalNum(); n++) {
1580
1581 double temp_betagamma = std::sqrt(std::pow(P[n](0), 2) + std::pow(P[n](1), 2));
1582 int itsBinID = std::floor((std::asinh(temp_betagamma) - asinh0) / eta + 1.0E-6);
1583 Bin[n] = itsBinID;
1584 if (maxbinIndex < itsBinID) {
1585 maxbinIndex = itsBinID;
1586 }
1587
1588 if (itsBinID >= maxbin) {
1589 ERRORMSG("The bin number limit is " << maxbin << ", please increase the energy interval and try again" << endl);
1590 return false;
1591 } else
1592 partInBin[itsBinID]++;
1593
1594 }
1595
1596 // partInBin only count particle on the local node.
1597 pbin_m->resetPartInBin_cyc(partInBin, maxbinIndex);
1598
1599 // after reset Particle Bin ID, update mass gamma of each bin again
1600 INFOMSG("After reset Bin: " << endl);
1601 calcGammas_cycl();
1602
1603 return true;
1604}
1605
1606
1607template <class T, unsigned Dim>
1609 int maxbin = pbin_m->getNBins();
1610 std::size_t partInBin[maxbin];
1611 for (int i = 0; i < maxbin; ++i) {
1612 partInBin[i] = 0;
1613 }
1614
1615 for (std::size_t i = 0; i < getLocalNum(); ++i) {
1616 partInBin[Bin[i]]++;
1617 }
1618
1619 // partInBin only count particle on the local node.
1620 pbin_m->resetPartInBin_cyc(partInBin, numBunch_m - 1);
1621
1622 // after reset Particle Bin ID, update mass gamma of each bin again
1623 calcGammas_cycl();
1624
1625 return true;
1626}
1627
1628
1629template <class T, unsigned Dim>
1631 return reference->getQ();
1632}
1633
1634
1635template <class T, unsigned Dim>
1637 return reference->getM();
1638}
1639
1640
1641template <class T, unsigned Dim>
1643 return reference->getP();
1644}
1645
1646
1647template <class T, unsigned Dim>
1649 return reference->getE();
1650}
1651
1652
1653template <class T, unsigned Dim>
1655 return refPOrigin_m;
1656}
1657
1658template <class T, unsigned Dim>
1660 refPOrigin_m = origin;
1661}
1662
1663
1664template <class T, unsigned Dim>
1666 return refPType_m;
1667}
1668
1669template <class T, unsigned Dim>
1670void PartBunchBase<T, Dim>::setPType(const std::string& type) {
1672}
1673
1674
1675template <class T, unsigned Dim>
1677 return dist_m->getType();
1678}
1679
1680
1681template <class T, unsigned Dim>
1683 const_cast<PartData *>(reference)->setQ(q);
1684}
1685
1686
1687template <class T, unsigned Dim>
1689 const_cast<PartData *>(reference)->setM(m);
1690}
1691
1692
1693template <class T, unsigned Dim>
1695 return momentsComputer_m.getStdKineticEnergy();
1696}
1697
1698
1699template <class T, unsigned Dim>
1701 return reference->getBeta();
1702}
1703
1704
1705template <class T, unsigned Dim>
1707 return reference->getGamma();
1708}
1709
1710
1711template <class T, unsigned Dim>
1713 return 0;
1714}
1715
1716
1717template <class T, unsigned Dim>
1719 return 0;
1720}
1721
1722
1723template <class T, unsigned Dim>
1725 // do nothing here
1726};
1727
1728
1729template <class T, unsigned Dim>
1731 return reference;
1732}
1733
1734
1735template <class T, unsigned Dim>
1737 return dist_m->getEmissionDeltaT();
1738}
1739
1740
1741template <class T, unsigned Dim>
1743 binemitted_m[binNumber]++;
1744}
1745
1746
1747template <class T, unsigned Dim>
1749 momentsComputer_m.computeMeanKineticEnergy(*this);
1750}
1751
1752template <class T, unsigned Dim>
1754
1755 if (getTotalNum() != 0) { // to suppress Nans
1756 Inform::FmtFlags_t ff = os.flags();
1757
1758 double pathLength = get_sPos();
1759
1760 os << std::scientific;
1761 os << level1 << "\n";
1762 os << "* ************** B U N C H ********************************************************* \n";
1763 os << "* NP = " << getTotalNum() << "\n";
1764 os << "* Qtot = " << std::setw(17) << Util::getChargeString(std::abs(sum(Q))) << " "
1765 << "Qi = " << std::setw(17) << Util::getChargeString(std::abs(qi_m)) << "\n";
1766 os << "* Ekin = " << std::setw(17) << Util::getEnergyString(get_meanKineticEnergy()) << " "
1767 << "dEkin = " << std::setw(17) << Util::getEnergyString(getdE()) << "\n";
1768 os << "* rmax = " << Util::getLengthString(rmax_m, 5) << "\n";
1769 os << "* rmin = " << Util::getLengthString(rmin_m, 5) << "\n";
1770 if (getTotalNum() >= 2) { // to suppress Nans
1771 os << "* rms beam size = " << Util::getLengthString(get_rrms(), 5) << "\n";
1772 os << "* rms momenta = " << std::setw(12) << std::setprecision(5) << get_prms() << " [beta gamma]\n";
1773 os << "* mean position = " << Util::getLengthString(get_rmean(), 5) << "\n";
1774 os << "* mean momenta = " << std::setw(12) << std::setprecision(5) << get_pmean() << " [beta gamma]\n";
1775 os << "* rms emittance = " << std::setw(12) << std::setprecision(5) << get_emit() << " (not normalized)\n";
1776 os << "* rms correlation = " << std::setw(12) << std::setprecision(5) << get_rprms() << "\n";
1777 }
1778 os << "* hr = " << Util::getLengthString(get_hr(), 5) << "\n";
1779 os << "* dh = " << std::setw(13) << std::setprecision(5) << dh_m * 100 << " [%]\n";
1780 os << "* t = " << std::setw(17) << Util::getTimeString(getT()) << " "
1781 << "dT = " << std::setw(17) << Util::getTimeString(getdT()) << "\n";
1782 os << "* spos = " << std::setw(17) << Util::getLengthString(pathLength) << "\n";
1783 os << "* ********************************************************************************** " << endl;
1784 os.flags(ff);
1785 }
1786 return os;
1787}
1788
1789// angle range [0~2PI) degree
1790template <class T, unsigned Dim>
1791double PartBunchBase<T, Dim>::calculateAngle(double x, double y) {
1792 double thetaXY = atan2(y, x);
1793
1794 return thetaXY >= 0 ? thetaXY : thetaXY + Physics::two_pi;
1795}
1796
1797
1798template <class T, unsigned Dim>
1800 return p.print(os);
1801}
1802
1803
1804/*
1805 * Virtual member functions
1806 */
1807
1808template <class T, unsigned Dim>
1810 throw OpalException("PartBunchBase<T, Dim>::runTests() ", "No test supported.");
1811}
1812
1813
1814template <class T, unsigned Dim>
1816
1817}
1818
1819template <class T, unsigned Dim>
1820void PartBunchBase<T, Dim>::swap(unsigned int i, unsigned int j) {
1821 if (i >= getLocalNum() || j >= getLocalNum() || i == j) return;
1822
1823 std::swap(R[i], R[j]);
1824 std::swap(P[i], P[j]);
1825 std::swap(Q[i], Q[j]);
1826 std::swap(M[i], M[j]);
1827 std::swap(Phi[i], Phi[j]);
1828 std::swap(Ef[i], Ef[j]);
1829 std::swap(Eftmp[i], Eftmp[j]);
1830 std::swap(Bf[i], Bf[j]);
1831 std::swap(Bin[i], Bin[j]);
1832 std::swap(dt[i], dt[j]);
1833 std::swap(PType[i], PType[j]);
1834 std::swap(POrigin[i], POrigin[j]);
1835 std::swap(TriID[i], TriID[j]);
1836 std::swap(cavityGapCrossed[i], cavityGapCrossed[j]);
1837 std::swap(bunchNum[i], bunchNum[j]);
1838}
1839
1840
1841template <class T, unsigned Dim>
1843 throw OpalException("PartBunchBase<T, Dim>::setBCAllPeriodic() ", "Not supported BC.");
1844}
1845
1846
1847template <class T, unsigned Dim>
1849 throw OpalException("PartBunchBase<T, Dim>::setBCAllOpen() ", "Not supported BC.");
1850}
1851
1852
1853template <class T, unsigned Dim>
1855 throw OpalException("PartBunchBase<T, Dim>::setBCForDCBeam() ", "Not supported BC.");
1856}
1857
1858
1859template <class T, unsigned Dim>
1860void PartBunchBase<T, Dim>::updateFields(const Vector_t& /*hr*/, const Vector_t& /*origin*/) {
1861}
1862
1863
1864template <class T, unsigned Dim>
1866
1867 pb->addAttribute(P);
1868 pb->addAttribute(Q);
1869 pb->addAttribute(M);
1870 pb->addAttribute(Phi);
1871 pb->addAttribute(Ef);
1872 pb->addAttribute(Eftmp);
1873 pb->addAttribute(Bf);
1874 pb->addAttribute(Bin);
1875 pb->addAttribute(dt);
1876 pb->addAttribute(PType);
1877 pb->addAttribute(POrigin);
1878 pb->addAttribute(TriID);
1879 pb->addAttribute(cavityGapCrossed);
1880 pb->addAttribute(bunchNum);
1881
1882 boundpTimer_m = IpplTimings::getTimer("Boundingbox");
1883 boundpBoundsTimer_m = IpplTimings::getTimer("Boundingbox-bounds");
1884 boundpUpdateTimer_m = IpplTimings::getTimer("Boundingbox-update");
1885 statParamTimer_m = IpplTimings::getTimer("Compute Statistics");
1886 selfFieldTimer_m = IpplTimings::getTimer("SelfField total");
1887
1888 histoTimer_m = IpplTimings::getTimer("Histogram");
1889
1890 distrCreate_m = IpplTimings::getTimer("Create Distr");
1891 distrReload_m = IpplTimings::getTimer("Load Distr");
1892
1893 globalPartPerNode_m = std::unique_ptr<size_t[]>(new size_t[Ippl::getNodes()]);
1894
1895 pmsg_m.release();
1896}
1897
1898
1899template <class T, unsigned Dim>
1901 return pbase_m->getTotalNum();
1902}
1903
1904template <class T, unsigned Dim>
1906 return pbase_m->getLocalNum();
1907}
1908
1909
1910template <class T, unsigned Dim>
1912 return pbase_m->getDestroyNum();
1913}
1914
1915template <class T, unsigned Dim>
1917 return pbase_m->getGhostNum();
1918}
1919
1920template <class T, unsigned Dim>
1922 pbase_m->setTotalNum(n);
1923}
1924
1925template <class T, unsigned Dim>
1927 pbase_m->setLocalNum(n);
1928}
1929
1930template <class T, unsigned Dim>
1932 return pbase_m->getLayout();
1933}
1934
1935template <class T, unsigned Dim>
1937 return pbase_m->getLayout();
1938}
1939
1940template <class T, unsigned Dim>
1942 return pbase_m->getUpdateFlag(f);
1943}
1944
1945template <class T, unsigned Dim>
1947 pbase_m->setUpdateFlag(f, val);
1948}
1949
1950template <class T, unsigned Dim>
1952 return pbase_m->singleInitNode();
1953}
1954
1955template <class T, unsigned Dim>
1957 pbase_m->resetID();
1958}
1959
1960template <class T, unsigned Dim>
1962 try {
1963 pbase_m->update();
1964 } catch (const IpplException& ex) {
1965 throw OpalException(ex.where(), ex.what());
1966 }
1967}
1968
1969template <class T, unsigned Dim>
1971 try {
1972 pbase_m->update(canSwap);
1973 } catch (const IpplException& ex) {
1974 throw OpalException(ex.where(), ex.what());
1975 }
1976}
1977
1978template <class T, unsigned Dim>
1980 pbase_m->createWithID(id);
1981}
1982
1983template <class T, unsigned Dim>
1985 pbase_m->create(M);
1986}
1987
1988template <class T, unsigned Dim>
1990 pbase_m->globalCreate(np);
1991}
1992
1993template <class T, unsigned Dim>
1994void PartBunchBase<T, Dim>::destroy(size_t M, size_t I, bool doNow) {
1995 pbase_m->destroy(M, I, doNow);
1996}
1997
1998template <class T, unsigned Dim>
1999void PartBunchBase<T, Dim>::performDestroy(bool updateLocalNum) {
2000 pbase_m->performDestroy(updateLocalNum);
2001}
2002
2003template <class T, unsigned Dim>
2004void PartBunchBase<T, Dim>::ghostDestroy(size_t M, size_t I) {
2005 pbase_m->ghostDestroy(M, I);
2006}
2007
2008template <class T, unsigned Dim>
2010 periodLength_m = Physics::c / f;
2011}
2012
2013template <class T, unsigned Dim>
2015 //const double N = static_cast<double>(this->getTotalNum());
2016
2017 Vektor<double, 2*Dim> rpmean;
2018 for (unsigned int i = 0; i < Dim; i++) {
2019 rpmean(2*i)= get_rmean()(i);
2020 rpmean((2*i)+1)= get_pmean()(i);
2021 }
2022
2024 for (unsigned int i = 0; i < 2 * Dim; i++) {
2025 for (unsigned int j = 0; j <= i; j++) {
2026 sigmaMatrix[i][j] = momentsComputer_m.getMoments6x6()[i][j] - rpmean(i) * rpmean(j);
2027 sigmaMatrix[j][i] = sigmaMatrix[i][j];
2028 }
2029 }
2030 return sigmaMatrix;
2031}
2032
2033#endif
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition: Vector3D.cpp:118
Inform & operator<<(Inform &os, PartBunchBase< T, Dim > &p)
Inform * gmsg
Definition: Main.cpp:61
ParticleOrigin
ParticleType
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
DistributionType
Definition: Distribution.h:50
const unsigned Dim
FieldSolverType
Definition: FieldSolver.h:38
void allreduce(const T *input, T *output, int count, Op op)
Definition: GlobalComm.hpp:510
bool reduce(Communicate &, InputIterator, InputIterator, OutputIterator, const ReduceOp &, bool *IncludeVal=0)
Definition: GlobalComm.hpp:55
void gather(const T *input, T *output, int count, int root=0)
Definition: GlobalComm.hpp:449
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:84
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:76
PETE_TBTree< OpNE, Index::PETE_Expr_t, PETE_Scalar< double > > ne(const Index &idx, double x)
Definition: IndexInlines.h:357
T::PETE_Expr_t::PETE_Return_t sum(const PETE_Expr< T > &expr)
Definition: PETE.h:1111
PETE_TUTree< FnFloor, typename T::PETE_Expr_t > floor(const PETE_Expr< T > &l)
Definition: PETE.h:733
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
PETE_TTTree< OpWhere, typename Cond_t::PETE_Expr_t, typename True_t::PETE_Expr_t, PETE_Scalar< Vektor< T, Dim > > > where(const PETE_Expr< Cond_t > &c, const PETE_Expr< True_t > &t, const Vektor< T, Dim > &f)
void bounds(const PETE_Expr< T1 > &expr, Vektor< T2, D > &minval, Vektor< T2, D > &maxval)
PETE_TBTree< FnArcTan2, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > atan2(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
Inform & level2(Inform &inf)
Definition: Inform.cpp:46
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
Inform & level1(Inform &inf)
Definition: Inform.cpp:45
#define INFORM_ALL_NODES
Definition: Inform.h:39
#define PAssert_LT(a, b)
Definition: PAssert.h:106
#define ERRORMSG(msg)
Definition: IpplInfo.h:350
#define INFOMSG(msg)
Definition: IpplInfo.h:348
#define WARNMSG(msg)
Definition: IpplInfo.h:349
Definition: Air.h:27
constexpr double two_pi
The value of.
Definition: Physics.h:33
constexpr double e
The value of.
Definition: Physics.h:39
constexpr double c
The velocity of light in m/s.
Definition: Physics.h:45
constexpr double rad2deg
Definition: Units.h:146
double remotePartDel
Definition: Options.cpp:61
std::string getChargeString(double charge, unsigned int precision=3)
Definition: Util.h:169
std::string getEnergyString(double energyInMeV, unsigned int precision=3)
Definition: Util.h:146
std::string getTimeString(double time, unsigned int precision=3)
Definition: Util.h:73
std::string getLengthString(double spos, unsigned int precision=3)
Definition: Util.h:96
bool eq(double x, double y)
boost::function< boost::tuple< double, bool >(arguments_t)> type
Definition: function.hpp:21
FRONT * fs
Definition: hypervolume.cpp:59
ParticleLayout< T, Dim > & getLayout()
double get_Dx() const
double getP() const
void setEnergyBins(int numberOfEnergyBins)
double get_meanKineticEnergy() const
void setDistribution(Distribution *d, std::vector< Distribution * > addedDistributions, size_t &np)
virtual void resetInterpolationCache(bool clearCache=false)
void setPType(const std::string &type)
const PartData * getReference() const
ParticleOrigin getPOrigin() const
void setMass(double mass)
void setCharge(double q)
int getSteptoLastInj() const
Vector_t get_99Percentile() const
void boundp_destroyCycl()
void get_bounds(Vector_t &rmin, Vector_t &rmax) const
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)
double getMassPerParticle() const
double getQ() const
Access to reference data.
double getCouplingConstant() const
Vector_t get_normalizedEps_99Percentile() const
double getChargePerParticle() const
get the macro particle charge
virtual void set_meshEnlargement(double dh)
void resetM(double m)
virtual double getBeta(int i)
virtual double getPx0(int i)
size_t getLocalNum() const
FMatrix< double, 2 *Dim, 2 *Dim > getSigmaMatrix() const
void set_sPos(double s)
void setLocalTrackStep(long long n)
step in a TRACK command
void setLocalBinCount(size_t num, int bin)
double get_debyeLength() const
bool getUpdateFlag(UpdateFlags_t f) const
void setParticle(FVector< double, 6 > z, int ii)
size_t emitParticles(double eZ)
Emit particles in the given bin i.e. copy the particles from the bin structure into the particle cont...
void maximumAmplitudes(const FMatrix< double, 6, 6 > &D, double &axmax, double &aymax)
Return maximum amplitudes.
double get_plasmaParameter() const
void setMassZeroPart(double mass)
size_t getTotalNum() const
bool weHaveEnergyBins()
double get_DDy() const
virtual void updateFields(const Vector_t &hr, const Vector_t &origin)
Vector_t get_95Percentile() const
bool resetPartBinBunch()
virtual void setZ(int i, double zcoo)
double calcMeanPhi()
calculate average angle of longitudinal direction of bins
Quaternion_t getGlobalToLocalQuaternion()
size_t boundp_destroyT()
void setBeamFrequency(double v)
Vector_t get_normalizedEps_68Percentile() const
double get_gamma() const
void switchToUnitlessPositions(bool use_dt_per_particle=false)
size_t calcNumPartsOutside(Vector_t x)
returns the number of particles outside of a box defined by x
double getTEmission()
double getdT() const
Inform & print(Inform &os)
FieldSolverType getFieldSolverType() const
Return the fieldsolver type if we have a fieldsolver.
double getEmissionDeltaT()
void setLocalNumPerBunch(size_t numpart, short n)
size_t getLocalNumPerBunch(short n) const
void setGlobalToLocalQuaternion(Quaternion_t globalToLocalQuaternion)
Vector_t get_rrms() const
bool getIfBeamEmitting()
bool weHaveBins() const
double get_rmsDensity() const
virtual double getPy(int i)
double getBinGamma(int bin)
Get gamma of one bin.
double getInitialBeta() const
int getLastEmittedEnergyBin()
void calcBeamParameters()
void getLocalBounds(Vector_t &rmin, Vector_t &rmax) const
void setSteptoLastInj(int n)
virtual double getX0(int i)
double getInitialGamma() const
virtual void setBCAllPeriodic()
virtual void runTests()
void setChargeZeroPart(double q)
virtual double getY0(int i)
ParticleType getPType() const
Vector_t get_origin() const
Vector_t get_prms() const
double getdE() const
void createWithID(unsigned id)
PartBunchBase(AbstractParticle< T, Dim > *pb, const PartData *ref)
double getCharge() const
get the total charge per simulation particle
virtual double getPy0(int i)
double get_temperature() const
size_t getTotalNumPerBunch(short n) const
virtual double getPx(int i)
Vector_t get_pmean_Distribution() const
size_t getNumberOfEmissionSteps()
void calcLineDensity(unsigned int nBins, std::vector< double > &lineDensity, std::pair< double, double > &meshInfo)
calculates the 1d line density (not normalized) and append it to a file.
Vector_t get_68Percentile() const
void setup(AbstractParticle< T, Dim > *pb)
virtual void setBCAllOpen()
void setTotalNum(size_t n)
long long getLocalTrackStep() const
void setGlobalMeanR(Vector_t globalMeanR)
void setCouplingConstant(double c)
short getNumBunch() const
double get_DDx() const
virtual void do_binaryRepart()
Vector_t get_norm_emit() const
void calcGammas()
Compute the gammas of all bins.
int getStepsPerTurn() const
void setdT(double dt)
double get_Dy() const
Vector_t get_rprms() const
void setPOrigin(ParticleOrigin)
Vector_t get_maxExtent() const
Vector_t get_normalizedEps_95Percentile() const
void gatherLoadBalanceStatistics()
void countTotalNumPerBunch()
DistributionType getDistType() const
void get_PBounds(Vector_t &min, Vector_t &max) const
void calcGammas_cycl()
virtual void setBinCharge(int bin, double q)
Set the charge of one bin to the value of q and all other to zero.
bool isGridFixed() const
Vector_t get_halo() const
void performDestroy(bool updateLocalNum=false)
Vector_t getGlobalMeanR()
void ghostDestroy(size_t M, size_t I)
int getNumberOfEnergyBins()
void setGlobalTrackStep(long long n)
step in multiple TRACK commands
std::pair< Vector_t, double > getBoundingSphere()
Vector_t get_centroid() const
Vector_t get_99_99Percentile() const
void push_back(OpalParticle const &p)
virtual double getX(int i)
virtual double getPz(int i)
void setLocalNum(size_t n)
Vector_t get_pmean() const
void setTotalNumPerBunch(size_t numpart, short n)
virtual void setBCForDCBeam()
bool hasBinning() const
void destroy(size_t M, size_t I, bool doNow=false)
void globalCreate(size_t np)
Vector_t get_normalizedEps_99_99Percentile() const
OpalParticle getParticle(int ii)
virtual void swap(unsigned int i, unsigned int j)
virtual void actT()
void setPBins(PartBins *pbin)
virtual void boundp()
void create(size_t M)
size_t getDestroyNum() const
virtual double getGamma(int i)
void resetQ(double q)
virtual void setSolver(FieldSolver *fs)
long long getGlobalTrackStep() const
void setT(double t)
size_t getGhostNum() const
void setTEmission(double t)
size_t getLoadBalance(int p) const
std::pair< Vector_t, double > getLocalBoundingSphere()
virtual Vector_t get_hr() const
Vector_t get_emit() const
double calculateAngle(double x, double y)
angle range [0~2PI) degree
void calcDebyeLength()
Compute the (global) Debye length for the beam.
double get_sPos() const
void iterateEmittedBin(int binNumber)
bool singleInitNode() const
double getM() const
void setUpdateFlag(UpdateFlags_t f, bool val)
virtual double getY(int i)
double getT() const
double getE() const
void switchOffUnitlessPositions(bool use_dt_per_particle=false)
void setStepsPerTurn(int n)
virtual double getZ(int i)
Vector_t get_rmean() const
static OpalData * getInstance()
Definition: OpalData.cpp:196
double getPy() const
Get vertical momentum (no dimension).
Definition: OpalParticle.h:213
const Vector_t & getR() const
Get position in m.
Definition: OpalParticle.h:225
const Vector_t & getP() const
Get momentum.
Definition: OpalParticle.h:231
double getPz() const
Get relative momentum error (no dimension).
Definition: OpalParticle.h:219
double getY() const
Get vertical displacement in m.
Definition: OpalParticle.h:195
double getZ() const
Get longitudinal displacement c*t in m.
Definition: OpalParticle.h:201
double getPx() const
Get horizontal momentum (no dimension).
Definition: OpalParticle.h:207
double getX() const
Get horizontal position in m.
Definition: OpalParticle.h:189
Particle reference data.
Definition: PartData.h:35
An abstract sequence of beam line components.
Definition: Beamline.h:34
A templated representation for vectors.
Definition: FVector.h:38
static ParticleType getParticleType(const std::string &str)
void createOpalCycl(PartBunchBase< double, 3 > *beam, size_t numberOfParticles, double current, const Beamline &bl)
void createOpalT(PartBunchBase< double, 3 > *beam, std::vector< Distribution * > addedDistributions, size_t &numberOfParticles)
The base class for all OPAL exceptions.
Definition: OpalException.h:28
virtual void addAttribute(ParticleAttribBase &pa)=0
void setCacheDimension(int d, T length)
Definition: Inform.h:42
std::ios_base::fmtflags FmtFlags_t
Definition: Inform.h:99
FmtFlags_t flags() const
Definition: Inform.h:106
virtual const char * what() const
Definition: IpplException.h:15
virtual const std::string & where() const
Definition: IpplException.h:19
static int getNodes()
Definition: IpplInfo.cpp:670
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
Definition: Vec.h:22
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6