OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
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 
21 #include <cmath>
22 #include <numeric>
23 
25 
27 #include "Algorithms/PartBins.h"
28 #include "Algorithms/PartBinsCyc.h"
29 #include "Algorithms/PartData.h"
30 #include "Physics/Physics.h"
31 #include "Structure/FieldSolver.h"
34 #include "Utilities/Options.h"
36 #include "Utilities/Util.h"
37 
38 extern Inform* gmsg;
39 
40 template <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  moments_m(),
52  dt_m(0.0),
53  t_m(0.0),
54  spos_m(0.0),
55  globalMeanR_m(Vector_t(0.0, 0.0, 0.0)),
56  globalToLocalQuaternion_m(Quaternion_t(1.0, 0.0, 0.0, 0.0)),
57  rmax_m(0.0),
58  rmin_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 }
85 
86 /*
87  * Bunch common member functions
88  */
89 
90 template <class T, unsigned Dim>
92  if (dist_m != NULL) {
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 
104 template <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 }
113 
114 
115 template <class T, unsigned Dim>
117  return dist_m->getNumberOfEmissionSteps();
118 }
119 
120 
121 template <class T, unsigned Dim>
123  return dist_m->getNumberOfEnergyBins();
124 }
125 
126 
127 template <class T, unsigned Dim>
129 
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;
140  }
141 }
142 
143 
144 template <class T, unsigned Dim>
145 void 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 }
151 
152 
153 template <class T, unsigned Dim>
155 
156  if (dist_m != NULL)
157  return dist_m->getNumberOfEnergyBins() > 0;
158  else
159  return false;
160 }
161 
162 
163 template <class T, unsigned Dim>
164 void PartBunchBase<T, Dim>::switchToUnitlessPositions(bool use_dt_per_particle) {
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;
182 
183  if (hasToReset) R.resetDirtyFlag();
184 }
185 
186 //FIXME: unify methods, use convention that all particles have own dt
187 template <class T, unsigned Dim>
189 
190  if (unit_state_ == units)
191  throw SwitcherError("PartBunch::switchOffUnitlessPositions",
192  "Cannot apply units twice to PartBunch");
193 
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];
201 
202  R[i] *= Vector_t(Physics::c * dt);
203  }
204 
205  unit_state_ = units;
206 
207  if (hasToReset) R.resetDirtyFlag();
208 }
209 
210 
211 template <class T, unsigned Dim>
213  // do nothing here
214 }
215 
216 
217 template <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 
231 
232 template <class T, unsigned Dim>
234  return fixed_grid;
235 }
236 
237 
238 template <class T, unsigned Dim>
240  return (pbin_m != nullptr);
241 }
242 
243 
244 template <class T, unsigned Dim>
246  tEmission_m = t;
247 }
248 
249 
250 template <class T, unsigned Dim>
252  return tEmission_m;
253 }
254 
255 
256 template <class T, unsigned Dim>
258  if (dist_m != NULL)
259  return dist_m->getIfDistEmitting();
260  else
261  return false;
262 }
263 
264 
265 template <class T, unsigned Dim>
267  if (pbin_m != NULL)
268  return pbin_m->weHaveBins();
269  else
270  return false;
271 }
272 
273 
274 template <class T, unsigned Dim>
276  pbin_m = pbin;
277  *gmsg << *pbin_m << endl;
278  setEnergyBins(pbin_m->getNBins());
279 }
280 
281 
282 template <class T, unsigned Dim>
284  pbin_m = pbin;
285  setEnergyBins(pbin_m->getNBins());
286 }
287 
288 
289 template <class T, unsigned Dim>
291  return dist_m->emitParticles(this, eZ);
292 }
293 
294 
295 template <class T, unsigned Dim>
297  size_t numParticles = getLocalNum();
298  reduce(numParticles, numParticles, OpAddAssign());
299  setTotalNum(numParticles);
300 }
301 
302 
303 template <class T, unsigned Dim>
305  this->Bin = 0;
306  pbin_m->resetBins();
307  // delete pbin_m; we did not allocate it!
308  pbin_m = NULL;
309 }
310 
311 
312 template <class T, unsigned Dim>
314  if (pbin_m != NULL)
315  return pbin_m->getLastemittedBin();
316  else
317  return 0;
318 }
319 
320 
321 template <class T, unsigned Dim>
322 void PartBunchBase<T, Dim>::setLocalBinCount(size_t num, int bin) {
323  if (pbin_m != NULL) {
324  pbin_m->setPartNum(bin, num);
325  }
326 }
327 
328 
329 template <class T, unsigned Dim>
331 
332  const int emittedBins = dist_m->getNumberOfEnergyBins();
333 
334  size_t s = 0;
335 
336  for (int i = 0; i < emittedBins; i++)
337  bingamma_m[i] = 0.0;
338 
339  for (unsigned int n = 0; n < getLocalNum(); n++)
340  bingamma_m[this->Bin[n]] += std::sqrt(1.0 + dot(this->P[n], this->P[n]));
341 
342  std::unique_ptr<size_t[]> particlesInBin(new size_t[emittedBins]);
343  reduce(bingamma_m.get(), bingamma_m.get() + emittedBins, bingamma_m.get(), OpAddAssign());
344  reduce(binemitted_m.get(), binemitted_m.get() + emittedBins, particlesInBin.get(), OpAddAssign());
345  for (int i = 0; i < emittedBins; i++) {
346  size_t &pInBin = particlesInBin[i];
347  if (pInBin != 0) {
348  bingamma_m[i] /= pInBin;
349  INFOMSG(level2 << "Bin " << std::setw(3) << i
350  << " gamma = " << std::setw(8) << std::scientific
351  << std::setprecision(5) << bingamma_m[i]
352  << "; NpInBin= " << std::setw(8)
353  << std::setfill(' ') << pInBin << endl);
354  } else {
355  bingamma_m[i] = 1.0;
356  INFOMSG(level2 << "Bin " << std::setw(3) << i << " has no particles " << endl);
357  }
358  s += pInBin;
359  }
360  particlesInBin.reset();
361 
362 
363  if (s != getTotalNum() && !OpalData::getInstance()->hasGlobalGeometry())
364  ERRORMSG("sum(Bins)= " << s << " != sum(R)= " << getTotalNum() << endl;);
365 
366  if (emittedBins >= 2) {
367  for (int i = 1; i < emittedBins; i++) {
368  if (binemitted_m[i - 1] != 0 && binemitted_m[i] != 0)
369  INFOMSG(level2 << "d(gamma)= " << 100.0 * std::abs(bingamma_m[i - 1] - bingamma_m[i]) / bingamma_m[i] << " [%] "
370  << "between bin " << i - 1 << " and " << i << endl);
371  }
372  }
373 }
374 
375 
376 template <class T, unsigned Dim>
378 
379  const int emittedBins = pbin_m->getLastemittedBin();
380 
381  for (int i = 0; i < emittedBins; i++)
382  bingamma_m[i] = 0.0;
383  for (unsigned int n = 0; n < getLocalNum(); n++) {
384  if ( this->Bin[n] > -1 ) {
385  bingamma_m[this->Bin[n]] += std::sqrt(1.0 + dot(this->P[n], this->P[n]));
386  }
387  }
388 
389  allreduce(*bingamma_m.get(), emittedBins, std::plus<double>());
390 
391  for (int i = 0; i < emittedBins; i++) {
392  if (pbin_m->getTotalNumPerBin(i) > 0) {
393  bingamma_m[i] /= pbin_m->getTotalNumPerBin(i);
394  } else {
395  bingamma_m[i] = 0.0;
396  }
397  INFOMSG("Bin " << i << " : particle number = " << pbin_m->getTotalNumPerBin(i)
398  << " gamma = " << bingamma_m[i] << endl);
399  }
400 
401 }
402 
403 
404 template <class T, unsigned Dim>
406  return bingamma_m[bin];
407 }
408 
409 
410 template <class T, unsigned Dim>
411 void PartBunchBase<T, Dim>::setBinCharge(int bin, double q) {
412  this->Q = where(eq(this->Bin, bin), q, 0.0);
413 }
414 
415 
416 template <class T, unsigned Dim>
418  this->Q = where(eq(this->Bin, bin), this->qi_m, 0.0);
419 }
420 
421 
422 template <class T, unsigned Dim>
424 
425  std::size_t localnum = 0;
426  const Vector_t meanR = get_rmean();
427 
428  for (unsigned long k = 0; k < getLocalNum(); ++ k)
429  if (std::abs(R[k](0) - meanR(0)) > x(0) ||
430  std::abs(R[k](1) - meanR(1)) > x(1) ||
431  std::abs(R[k](2) - meanR(2)) > x(2)) {
432 
433  ++localnum;
434  }
435 
436  gather(&localnum, &globalPartPerNode_m[0], 1);
437 
438  size_t npOutside = std::accumulate(globalPartPerNode_m.get(),
439  globalPartPerNode_m.get() + Ippl::getNodes(), 0,
440  std::plus<size_t>());
441 
442  return npOutside;
443 }
444 
445 
455 template <class T, unsigned Dim>
457  std::vector<double>& lineDensity,
458  std::pair<double, double>& meshInfo) {
459  Vector_t rmin, rmax;
460  get_bounds(rmin, rmax);
461 
462  if (nBins < 2) {
463  Vektor<int, 3>/*NDIndex<3>*/ grid;
464  this->updateDomainLength(grid);
465  nBins = grid[2];
466  }
467 
468  double length = rmax(2) - rmin(2);
469  double zmin = rmin(2) - dh_m * length, zmax = rmax(2) + dh_m * length;
470  double hz = (zmax - zmin) / (nBins - 2);
471  double perMeter = 1.0 / hz;//(zmax - zmin);
472  zmin -= hz;
473 
474  lineDensity.resize(nBins, 0.0);
475  std::fill(lineDensity.begin(), lineDensity.end(), 0.0);
476 
477  const unsigned int lN = getLocalNum();
478  for (unsigned int i = 0; i < lN; ++ i) {
479  const double z = R[i](2) - 0.5 * hz;
480  unsigned int idx = (z - zmin) / hz;
481  double tau = (z - zmin) / hz - idx;
482 
483  lineDensity[idx] += Q[i] * (1.0 - tau) * perMeter;
484  lineDensity[idx + 1] += Q[i] * tau * perMeter;
485  }
486 
487  reduce(&(lineDensity[0]), &(lineDensity[0]) + nBins, &(lineDensity[0]), OpAddAssign());
488 
489  meshInfo.first = zmin;
490  meshInfo.second = hz;
491 }
492 
493 
494 template <class T, unsigned Dim>
496  /*
497  Assume rmin_m < 0.0
498  */
499 
500  IpplTimings::startTimer(boundpTimer_m);
501  //if (!R.isDirty() && stateOfLastBoundP_ == unit_state_) return;
502  if ( !(R.isDirty() || ID.isDirty() ) && stateOfLastBoundP_ == unit_state_) return; //-DW
503 
504  stateOfLastBoundP_ = unit_state_;
505 
506  if (!isGridFixed()) {
507  const int dimIdx = (dcBeam_m? 2: 3);
508 
515  this->updateDomainLength(nr_m);
516  IpplTimings::startTimer(boundpBoundsTimer_m);
517  get_bounds(rmin_m, rmax_m);
518  IpplTimings::stopTimer(boundpBoundsTimer_m);
519  Vector_t len = rmax_m - rmin_m;
520 
521  double volume = 1.0;
522  for (int i = 0; i < dimIdx; i++) {
523  double length = std::abs(rmax_m[i] - rmin_m[i]);
524  if (length < 1e-10) {
525  rmax_m[i] += 1e-10;
526  rmin_m[i] -= 1e-10;
527  } else {
528  rmax_m[i] += dh_m * length;
529  rmin_m[i] -= dh_m * length;
530  }
531  hr_m[i] = (rmax_m[i] - rmin_m[i]) / (nr_m[i] - 1);
532  }
533  if (dcBeam_m) {
534  rmax_m[2] = rmin_m[2] + periodLength_m;
535  hr_m[2] = periodLength_m / (nr_m[2] - 1);
536  }
537  for (int i = 0; i < dimIdx; ++ i) {
538  volume *= std::abs(rmax_m[i] - rmin_m[i]);
539  }
540 
541  if (getIfBeamEmitting() && dist_m != NULL) {
542  // keep particles per cell ratio high, don't spread a hand full particles across the whole grid
543  double percent = std::max(1.0 / (nr_m[2] - 1), dist_m->getPercentageEmitted());
544  double length = std::abs(rmax_m[2] - rmin_m[2]) / (1.0 + 2 * dh_m);
545  if (percent < 1.0 && percent > 0.0) {
546  rmax_m[2] -= dh_m * length;
547  rmin_m[2] = rmax_m[2] - length / percent;
548 
549  length /= percent;
550 
551  rmax_m[2] += dh_m * length;
552  rmin_m[2] -= dh_m * length;
553 
554  hr_m[2] = (rmax_m[2] - rmin_m[2]) / (nr_m[2] - 1);
555  }
556  }
557 
558  if (volume < 1e-21 && getTotalNum() > 1 && std::abs(sum(Q)) > 0.0) {
559  WARNMSG(level1 << "!!! Extremely high particle density detected !!!" << endl);
560  }
561  //INFOMSG("It is a full boundp hz= " << hr_m << " rmax= " << rmax_m << " rmin= " << rmin_m << endl);
562 
563  if (hr_m[0] * hr_m[1] * hr_m[2] <= 0) {
564  throw GeneralClassicException("boundp() ", "h<0, can not build a mesh");
565  }
566 
567  Vector_t origin = rmin_m - Vector_t(hr_m[0] / 2.0, hr_m[1] / 2.0, hr_m[2] / 2.0);
568  this->updateFields(hr_m, origin);
569  }
570  IpplTimings::startTimer(boundpUpdateTimer_m);
571  update();
572  IpplTimings::stopTimer(boundpUpdateTimer_m);
573  R.resetDirtyFlag();
574 
575  IpplTimings::stopTimer(boundpTimer_m);
576 }
577 
578 
579 template <class T, unsigned Dim>
581 
582  Vector_t len;
583  const int dimIdx = 3;
584  IpplTimings::startTimer(boundpTimer_m);
585 
586  std::unique_ptr<size_t[]> countLost;
587  if (weHaveBins()) {
588  const int tempN = pbin_m->getLastemittedBin();
589  countLost = std::unique_ptr<size_t[]>(new size_t[tempN]);
590  for (int ii = 0; ii < tempN; ii++) countLost[ii] = 0;
591  }
592 
593  this->updateDomainLength(nr_m);
594 
595  IpplTimings::startTimer(boundpBoundsTimer_m);
596  get_bounds(rmin_m, rmax_m);
597  IpplTimings::stopTimer(boundpBoundsTimer_m);
598 
599  len = rmax_m - rmin_m;
600 
601  calcBeamParameters();
602 
603  int checkfactor = Options::remotePartDel;
604  if (checkfactor != 0) {
605  //INFOMSG("checkfactor= " << checkfactor << endl);
606  // check the bunch if its full size is larger than checkfactor times of its rms size
607  Vector_t rmean = momentsComputer_m.getMeanPosition();
608  Vector_t rrms = momentsComputer_m.getStandardDeviationPosition();
609  if(checkfactor < 0) {
610  checkfactor *= -1;
611  if (len[0] > checkfactor * rrms[0] ||
612  len[1] > checkfactor * rrms[1] ||
613  len[2] > checkfactor * rrms[2])
614  {
615  for(unsigned int ii = 0; ii < this->getLocalNum(); ii++) {
616  /* delete the particle if the distance to the beam center
617  * is larger than 8 times of beam's rms size
618  */
619  if (std::abs(R[ii](0) - rmean(0)) > checkfactor * rrms[0] ||
620  std::abs(R[ii](1) - rmean(1)) > checkfactor * rrms[1] ||
621  std::abs(R[ii](2) - rmean(2)) > checkfactor * rrms[2])
622  {
623  // put particle onto deletion list
624  destroy(1, ii);
625  //update bin parameter
626  if (weHaveBins())
627  countLost[Bin[ii]] += 1 ;
628  /* INFOMSG("REMOTE PARTICLE DELETION: ID = " << ID[ii] << ", R = " << R[ii]
629  * << ", beam rms = " << rrms_m << endl;);
630  */
631  }
632  }
633  }
634  }
635  else {
636  if (len[0] > checkfactor * rrms[0] ||
637  len[2] > checkfactor * rrms[2])
638  {
639  for(unsigned int ii = 0; ii < this->getLocalNum(); ii++) {
640  /* delete the particle if the distance to the beam center
641  * is larger than 8 times of beam's rms size
642  */
643  if (std::abs(R[ii](0) - rmean(0)) > checkfactor * rrms[0] ||
644  std::abs(R[ii](2) - rmean(2)) > checkfactor * rrms[2])
645  {
646  // put particle onto deletion list
647  destroy(1, ii);
648  //update bin parameter
649  if (weHaveBins())
650  countLost[Bin[ii]] += 1 ;
651  /* INFOMSG("REMOTE PARTICLE DELETION: ID = " << ID[ii] << ", R = " << R[ii]
652  * << ", beam rms = " << rrms_m << endl;);
653  */
654  }
655  }
656  }
657  }
658  }
659 
660  for (int i = 0; i < dimIdx; i++) {
661  double length = std::abs(rmax_m[i] - rmin_m[i]);
662  rmax_m[i] += dh_m * length;
663  rmin_m[i] -= dh_m * length;
664  hr_m[i] = (rmax_m[i] - rmin_m[i]) / (nr_m[i] - 1);
665  }
666 
667  // rescale mesh
668  this->updateFields(hr_m, rmin_m);
669 
670  if (weHaveBins()) {
671  pbin_m->updatePartInBin_cyc(countLost.get());
672  }
673 
674  /* we also need to update the number of particles per bunch
675  * expensive since does an allreduce!
676  */
677  countTotalNumPerBunch();
678 
679  IpplTimings::startTimer(boundpUpdateTimer_m);
680  update();
681  IpplTimings::stopTimer(boundpUpdateTimer_m);
682 
683  IpplTimings::stopTimer(boundpTimer_m);
684 }
685 
686 
687 template <class T, unsigned Dim>
689 
690  this->updateDomainLength(nr_m);
691 
692  std::vector<size_t> tmpbinemitted;
693 
694  boundp();
695 
696  size_t ne = 0;
697  const size_t localNum = getLocalNum();
698 
699  double rzmean = momentsComputer_m.getMeanPosition()(2);
700  double rzrms = momentsComputer_m.getStandardDeviationPosition()(2);
701  const bool haveEnergyBins = weHaveEnergyBins();
702  if (haveEnergyBins) {
703  tmpbinemitted.resize(getNumberOfEnergyBins(), 0.0);
704  }
705  for (unsigned int i = 0; i < localNum; i++) {
706  if (Bin[i] < 0 || (Options::remotePartDel > 0 && std::abs(R[i](2) - rzmean) < Options::remotePartDel * rzrms)) {
707  ne++;
708  destroy(1, i);
709  } else if (haveEnergyBins) {
710  tmpbinemitted[Bin[i]]++;
711  }
712  }
713 
714  boundp();
715 
716  calcBeamParameters();
717  gatherLoadBalanceStatistics();
718 
719  if (haveEnergyBins) {
720  const int lastBin = dist_m->getLastEmittedEnergyBin();
721  for (int i = 0; i < lastBin; i++) {
722  binemitted_m[i] = tmpbinemitted[i];
723  }
724  }
725  reduce(ne, ne, OpAddAssign());
726  return ne;
727 }
728 
729 
730 template <class T, unsigned Dim>
732 
733  std::unique_ptr<size_t[]> tmpbinemitted;
734 
735  const size_t localNum = getLocalNum();
736  const size_t totalNum = getTotalNum();
737  size_t ne = 0;
738 
739  if (weHaveEnergyBins()) {
740  tmpbinemitted = std::unique_ptr<size_t[]>(new size_t[getNumberOfEnergyBins()]);
741  for (int i = 0; i < getNumberOfEnergyBins(); i++) {
742  tmpbinemitted[i] = 0;
743  }
744  for (unsigned int i = 0; i < localNum; i++) {
745  if (Bin[i] < 0) {
746  destroy(1, i);
747  ++ ne;
748  } else
749  tmpbinemitted[Bin[i]]++;
750  }
751  } else {
752  Inform dmsg("destroy: ", INFORM_ALL_NODES);
753  for (size_t i = 0; i < localNum; i++) {
754  if ((Bin[i] < 0)) {
755  ne++;
756  destroy(1, i);
757  }
758  }
759  }
760 
761  if (ne > 0) {
762  performDestroy(true);
763  }
764 
765  calcBeamParameters();
766  gatherLoadBalanceStatistics();
767 
768  if (weHaveEnergyBins()) {
769  const int lastBin = dist_m->getLastEmittedEnergyBin();
770  for (int i = 0; i < lastBin; i++) {
771  binemitted_m[i] = tmpbinemitted[i];
772  }
773  }
774  size_t newTotalNum = getLocalNum();
775  reduce(newTotalNum, newTotalNum, OpAddAssign());
776 
777  setTotalNum(newTotalNum);
778 
779  return totalNum - newTotalNum;
780 }
781 
782 
783 template <class T, unsigned Dim>
784 double PartBunchBase<T, Dim>::getPx(int /*i*/) {
785  return 0.0;
786 }
787 
788 template <class T, unsigned Dim>
790  return 0.0;
791 }
792 
793 template <class T, unsigned Dim>
795  return 0.0;
796 }
797 
798 template <class T, unsigned Dim>
800  return 0.0;
801 }
802 
803 template <class T, unsigned Dim>
805  return 0;
806 }
807 
808 //ff
809 template <class T, unsigned Dim>
811  return this->R[i](0);
812 }
813 
814 //ff
815 template <class T, unsigned Dim>
817  return this->R[i](1);
818 }
819 
820 //ff
821 template <class T, unsigned Dim>
823  return this->R[i](2);
824 }
825 
826 //ff
827 template <class T, unsigned Dim>
828 double PartBunchBase<T, Dim>::getX0(int /*i*/) {
829  return 0.0;
830 }
831 
832 //ff
833 template <class T, unsigned Dim>
834 double PartBunchBase<T, Dim>::getY0(int /*i*/) {
835  return 0.0;
836 }
837 
838 
839 template <class T, unsigned Dim>
840 void PartBunchBase<T, Dim>::setZ(int /*i*/, double /*zcoo*/) {
841 };
842 
843 
844 template <class T, unsigned Dim>
846 
847  this->getLocalBounds(rmin, rmax);
848 
849  double min[2*Dim];
850 
851  for (unsigned int i = 0; i < Dim; ++i) {
852  min[2*i] = rmin[i];
853  min[2*i + 1] = -rmax[i];
854  }
855 
856  allreduce(min, 2*Dim, std::less<double>());
857 
858  for (unsigned int i = 0; i < Dim; ++i) {
859  rmin[i] = min[2*i];
860  rmax[i] = -min[2*i + 1];
861  }
862 }
863 
864 
865 template <class T, unsigned Dim>
867  const size_t localNum = getLocalNum();
868  if (localNum == 0) {
869  double maxValue = 1e8;
870  rmin = Vector_t(maxValue, maxValue, maxValue);
871  rmax = Vector_t(-maxValue, -maxValue, -maxValue);
872  return;
873  }
874 
875  rmin = R[0];
876  rmax = R[0];
877  for (size_t i = 1; i < localNum; ++ i) {
878  for (unsigned short d = 0; d < 3u; ++ d) {
879  if (rmin(d) > R[i](d)) rmin(d) = R[i](d);
880  else if (rmax(d) < R[i](d)) rmax(d) = R[i](d);
881  }
882  }
883 }
884 
885 
886 template <class T, unsigned Dim>
887 std::pair<Vector_t, double> PartBunchBase<T, Dim>::getBoundingSphere() {
888  Vector_t rmin, rmax;
889  get_bounds(rmin, rmax);
890 
891  std::pair<Vector_t, double> sphere;
892  sphere.first = 0.5 * (rmin + rmax);
893  sphere.second = std::sqrt(dot(rmax - sphere.first, rmax - sphere.first));
894 
895  return sphere;
896 }
897 
898 
899 template <class T, unsigned Dim>
900 std::pair<Vector_t, double> PartBunchBase<T, Dim>::getLocalBoundingSphere() {
901  Vector_t rmin, rmax;
902  getLocalBounds(rmin, rmax);
903 
904  std::pair<Vector_t, double> sphere;
905  sphere.first = 0.5 * (rmin + rmax);
906  sphere.second = std::sqrt(dot(rmax - sphere.first, rmax - sphere.first));
907 
908  return sphere;
909 }
910 
911 
912 template <class T, unsigned Dim>
914  Inform msg("PartBunch ");
915 
916  size_t i = getLocalNum();
917  create(1);
918 
919  R[i] = particle.getR();
920  P[i] = particle.getP();
921 
922  update();
923  msg << "Created one particle i= " << i << endl;
924 }
925 
926 
927 template <class T, unsigned Dim>
929  R[ii](0) = z[0];
930  P[ii](0) = z[1];
931  R[ii](1) = z[2];
932  P[ii](1) = z[3];
933  R[ii](2) = z[4];
934  P[ii](2) = z[5];
935 }
936 
937 
938 template <class T, unsigned Dim>
939 void PartBunchBase<T, Dim>::setParticle(OpalParticle const& particle, int ii) {
940  R[ii] = particle.getR();
941  P[ii] = particle.getP();
942 }
943 
944 
945 template <class T, unsigned Dim>
947  OpalParticle particle(ID[ii],
948  Vector_t(R[ii](0), R[ii](1), 0), P[ii],
949  R[ii](2), Q[ii], M[ii]);
950  return particle;
951 }
952 
953 
954 template <class T, unsigned Dim>
956  double& axmax, double& aymax) {
957  axmax = aymax = 0.0;
958  OpalParticle particle;
959 
960  for (unsigned int ii = 0; ii < getLocalNum(); ii++) {
961 
962  particle = getParticle(ii);
963  FVector<double, 6> vec({particle.getX(), particle.getPx(),
964  particle.getY(), particle.getPy(),
965  particle.getZ(), particle.getPz()});
966  FVector<double, 6> result;
967  result = D * vec;
968  // double xnor =
969  // D(0, 0) * part.getX() + D(0, 1) * part.getPx() + D(0, 2) * part.getY() +
970  // D(0, 3) * part.getPy() + D(0, 4) * part.getL() + D(0, 5) * part.getPLon();
971  // double pxnor =
972  // D(1, 0) * part.getX() + D(1, 1) * part.getPx() + D(1, 2) * part.getY() +
973  // D(1, 3) * part.getPy() + D(1, 4) * part.getL() + D(1, 5) * part.getPLon();
974  // double ynor =
975  // D(2, 0) * part.getX() + D(2, 1) * part.getPx() + D(2, 2) * part.getY() +
976  // D(2, 3) * part.getPy() + D(2, 4) * part.getL() + D(2, 5) * part.getPLon();
977  // double pynor =
978  // D(3, 0) * part.getX() + D(3, 1) * part.getPx() + D(3, 2) * part.getY() +
979  // D(3, 3) * part.getPy() + D(3, 4) * part.getL() + D(3, 5) * part.getPLon();
980 
981  axmax = std::max(axmax, (std::pow(result[0], 2) + std::pow(result[1], 2)));
982  aymax = std::max(aymax, (std::pow(result[2], 2) + std::pow(result[3], 2)));
983  }
984 }
985 
986 
987 template <class T, unsigned Dim>
989  dt_m = dt;
990 }
991 
992 
993 template <class T, unsigned Dim>
995  return dt_m;
996 }
997 
998 
999 template <class T, unsigned Dim>
1001  t_m = t;
1002 }
1003 
1004 
1005 template <class T, unsigned Dim>
1007  t_m += dt_m;
1008 }
1009 
1010 
1011 template <class T, unsigned Dim>
1013  return t_m;
1014 }
1015 
1016 
1017 template <class T, unsigned Dim>
1019  return spos_m;
1020 }
1021 
1022 
1023 template <class T, unsigned Dim>
1025  spos_m = s;
1026 }
1027 
1028 
1029 template <class T, unsigned Dim>
1031  return momentsComputer_m.getMeanGamma();
1032 }
1033 
1034 
1035 template <class T, unsigned Dim>
1037  return momentsComputer_m.getMeanKineticEnergy();
1038 }
1039 
1040 
1041 template <class T, unsigned Dim>
1043  return rmin_m;
1044 }
1045 
1046 
1047 template <class T, unsigned Dim>
1049  return rmax_m;
1050 }
1051 
1052 
1053 template <class T, unsigned Dim>
1055  return momentsComputer_m.getMeanPosition();
1056 }
1057 
1058 
1059 template <class T, unsigned Dim>
1061  return momentsComputer_m.getStandardDeviationPosition();
1062 }
1063 
1064 
1065 template <class T, unsigned Dim>
1067  return momentsComputer_m.getStandardDeviationRP();
1068 }
1069 
1070 
1071 template <class T, unsigned Dim>
1073  return momentsComputer_m.getMeanPosition();
1074 }
1075 
1076 
1077 template <class T, unsigned Dim>
1079  return momentsComputer_m.getStandardDeviationMomentum();
1080 }
1081 
1082 
1083 template <class T, unsigned Dim>
1085  return momentsComputer_m.getMeanMomentum();
1086 }
1087 
1088 
1089 template <class T, unsigned Dim>
1091  if (dist_m)// && dist_m->getType() != DistrTypeT::FROMFILE)
1092  return dist_m->get_pmean();
1093 
1094  double gamma = 0.1 / getM() + 1; // set default 0.1 eV
1095  return Vector_t(0, 0, std::sqrt(std::pow(gamma, 2) - 1));
1096 }
1097 
1098 
1099 template <class T, unsigned Dim>
1101  return momentsComputer_m.getGeometricEmittance();
1102 }
1103 
1104 
1105 template <class T, unsigned Dim>
1107  return momentsComputer_m.getNormalizedEmittance();
1108 }
1109 
1110 
1111 template <class T, unsigned Dim>
1113  return momentsComputer_m.getHalo();
1114 }
1115 
1116 
1117 template <class T, unsigned Dim>
1119  return momentsComputer_m.getDx();
1120 }
1121 
1122 
1123 template <class T, unsigned Dim>
1125  return momentsComputer_m.getDy();
1126 }
1127 
1128 
1129 template <class T, unsigned Dim>
1131  return momentsComputer_m.getDDx();
1132 }
1133 
1134 
1135 template <class T, unsigned Dim>
1137  return momentsComputer_m.getDDy();
1138 }
1139 
1140 
1141 template <class T, unsigned Dim>
1143  return hr_m;
1144 }
1145 
1146 
1147 template <class T, unsigned Dim>
1149  dh_m = dh;
1150 }
1151 
1152 
1153 template <class T, unsigned Dim>
1155 
1156  for (int i = 0; i < Ippl::getNodes(); i++)
1157  globalPartPerNode_m[i] = 0;
1158 
1159  std::size_t localnum = getLocalNum();
1160  gather(&localnum, &globalPartPerNode_m[0], 1);
1161 }
1162 
1163 
1164 template <class T, unsigned Dim>
1166  return globalPartPerNode_m[p];
1167 }
1168 
1169 
1170 template <class T, unsigned Dim>
1172  bounds(this->P, min, max);
1173 }
1174 
1175 
1176 template <class T, unsigned Dim>
1178 
1179  IpplTimings::startTimer(statParamTimer_m);
1180  get_bounds(rmin_m, rmax_m);
1181  momentsComputer_m.compute(*this);
1182  IpplTimings::stopTimer(statParamTimer_m);
1183 }
1184 
1185 template <class T, unsigned Dim>
1187  return couplingConstant_m;
1188 }
1189 
1190 
1191 template <class T, unsigned Dim>
1193  couplingConstant_m = c;
1194 }
1195 
1196 
1197 template <class T, unsigned Dim>
1199  qi_m = q;
1200  if (getTotalNum() != 0)
1201  Q = qi_m;
1202  else
1203  WARNMSG("Could not set total charge in PartBunch::setCharge based on getTotalNum" << endl);
1204 }
1205 
1206 
1207 template <class T, unsigned Dim>
1209  qi_m = q;
1210 }
1211 
1212 
1213 template <class T, unsigned Dim>
1215  massPerParticle_m = mass;
1216  if (getTotalNum() != 0)
1217  M = mass;
1218 }
1219 
1220 template <class T, unsigned Dim>
1222  massPerParticle_m = mass;
1223 }
1224 
1225 
1226 template <class T, unsigned Dim>
1228  return sum(Q);
1229 }
1230 
1231 
1232 template <class T, unsigned Dim>
1234  return qi_m;
1235 }
1236 
1237 template <class T, unsigned Dim>
1239  return massPerParticle_m;
1240 }
1241 
1242 template <class T, unsigned Dim>
1244  fs_m = fs;
1245  fs_m->initSolver(this);
1246 
1251  if (!OpalData::getInstance()->hasBunchAllocated()) {
1252  this->initialize(fs_m->getFieldLayout());
1253 // this->setMesh(fs_m->getMesh());
1254 // this->setFieldLayout(fs_m->getFieldLayout());
1255  }
1256 }
1257 
1258 
1259 template <class T, unsigned Dim>
1261  if (fs_m)
1262  return fs_m->hasValidSolver();
1263  else
1264  return false;
1265 }
1266 
1267 
1269 template <class T, unsigned Dim>
1271  if (fs_m)
1272  return fs_m->getFieldSolverType();
1273  else
1274  return "";
1275 }
1276 
1277 
1278 template <class T, unsigned Dim>
1280  stepsPerTurn_m = n;
1281 }
1282 
1283 
1284 template <class T, unsigned Dim>
1286  return stepsPerTurn_m;
1287 }
1288 
1289 
1290 template <class T, unsigned Dim>
1292  globalTrackStep_m = n;
1293 }
1294 
1295 
1296 template <class T, unsigned Dim>
1298  return globalTrackStep_m;
1299 }
1300 
1301 
1302 template <class T, unsigned Dim>
1304  localTrackStep_m = n;
1305 }
1306 
1307 
1308 template <class T, unsigned Dim>
1310  globalTrackStep_m++; localTrackStep_m++;
1311 }
1312 
1313 
1314 template <class T, unsigned Dim>
1316  return localTrackStep_m;
1317 }
1318 
1319 
1320 template <class T, unsigned Dim>
1322  numBunch_m = n;
1323  bunchTotalNum_m.resize(n);
1324  bunchLocalNum_m.resize(n);
1325 }
1326 
1327 
1328 template <class T, unsigned Dim>
1330  return numBunch_m;
1331 }
1332 
1333 
1334 template <class T, unsigned Dim>
1335 void PartBunchBase<T, Dim>::setTotalNumPerBunch(size_t totalnum, short n) {
1336  PAssert_LT(n, (short)bunchTotalNum_m.size());
1337  bunchTotalNum_m[n] = totalnum;
1338 }
1339 
1340 
1341 template <class T, unsigned Dim>
1343  PAssert_LT(n, (short)bunchTotalNum_m.size());
1344  return bunchTotalNum_m[n];
1345 }
1346 
1347 
1348 template <class T, unsigned Dim>
1349 void PartBunchBase<T, Dim>::setLocalNumPerBunch(size_t localnum, short n) {
1350  PAssert_LT(n, (short)bunchLocalNum_m.size());
1351  bunchLocalNum_m[n] = localnum;
1352 }
1353 
1354 
1355 template <class T, unsigned Dim>
1357  PAssert_LT(n, (short)bunchLocalNum_m.size());
1358  return bunchLocalNum_m[n];
1359 }
1360 
1361 
1362 template <class T, unsigned Dim>
1364  bunchTotalNum_m.clear();
1365  bunchTotalNum_m.resize(numBunch_m);
1366  bunchLocalNum_m.clear();
1367  bunchLocalNum_m.resize(numBunch_m);
1368 
1369  for (size_t i = 0; i < this->getLocalNum(); ++i) {
1370  PAssert_LT(this->bunchNum[i], numBunch_m);
1371  ++bunchLocalNum_m[this->bunchNum[i]];
1372  }
1373 
1374  allreduce(bunchLocalNum_m.data(), bunchTotalNum_m.data(),
1375  bunchLocalNum_m.size(), std::plus<size_t>());
1376 
1377  size_t totalnum = std::accumulate(bunchTotalNum_m.begin(),
1378  bunchTotalNum_m.end(), 0);
1379 
1380  if ( totalnum != this->getTotalNum() )
1381  throw OpalException("PartBunchBase::countTotalNumPerBunch()",
1382  "Sum of total number of particles per bunch (" +
1383  std::to_string(totalnum) + ") != total number of particles (" +
1384  std::to_string(this->getTotalNum()) + ")");
1385 }
1386 
1387 
1388 template <class T, unsigned Dim>
1390  globalMeanR_m = globalMeanR;
1391 }
1392 
1393 
1394 template <class T, unsigned Dim>
1396  return globalMeanR_m;
1397 }
1398 
1399 
1400 template <class T, unsigned Dim>
1402 
1403  globalToLocalQuaternion_m = globalToLocalQuaternion;
1404 }
1405 
1406 
1407 template <class T, unsigned Dim>
1409  return globalToLocalQuaternion_m;
1410 }
1411 
1412 
1413 template <class T, unsigned Dim>
1415  SteptoLastInj_m = n;
1416 }
1417 
1418 
1419 template <class T, unsigned Dim>
1421  return SteptoLastInj_m;
1422 }
1423 
1424 
1425 template <class T, unsigned Dim>
1427 
1428  const int emittedBins = pbin_m->getLastemittedBin();
1429  double phi[emittedBins];
1430  double px[emittedBins];
1431  double py[emittedBins];
1432  double meanPhi = 0.0;
1433 
1434  for (int ii = 0; ii < emittedBins; ii++) {
1435  phi[ii] = 0.0;
1436  px[ii] = 0.0;
1437  py[ii] = 0.0;
1438  }
1439 
1440  for (unsigned int ii = 0; ii < getLocalNum(); ii++) {
1441  px[Bin[ii]] += P[ii](0);
1442  py[Bin[ii]] += P[ii](1);
1443  }
1444 
1445  reduce(px, px + emittedBins, px, OpAddAssign());
1446  reduce(py, py + emittedBins, py, OpAddAssign());
1447  for (int ii = 0; ii < emittedBins; ii++) {
1448  phi[ii] = calculateAngle(px[ii], py[ii]);
1449  meanPhi += phi[ii];
1450  INFOMSG("Bin " << ii << " mean phi = " << phi[ii] * 180.0 / Physics::pi - 90.0 << "[degree]" << endl);
1451  }
1452 
1453  meanPhi /= emittedBins;
1454 
1455  INFOMSG("mean phi of all particles " << meanPhi * 180.0 / Physics::pi - 90.0 << "[degree]" << endl);
1456 
1457  return meanPhi;
1458 }
1459 
1460 // this function reset the BinID for each particles according to its current beta*gamma
1461 // it is for multi-turn extraction cyclotron with small energy gain
1462 // the bin number can be different with the bunch number
1463 
1464 template <class T, unsigned Dim>
1466 
1467 
1468  INFOMSG("Before reset Bin: " << endl);
1469  calcGammas_cycl();
1470  int maxbin = pbin_m->getNBins();
1471  size_t partInBin[maxbin];
1472  for (int ii = 0; ii < maxbin; ii++) partInBin[ii] = 0;
1473 
1474  double pMin0 = 1.0e9;
1475  double pMin = 0.0;
1476  double maxbinIndex = 0;
1477 
1478  for (unsigned long int n = 0; n < getLocalNum(); n++) {
1479  double temp_betagamma = std::sqrt(std::pow(P[n](0), 2) + std::pow(P[n](1), 2));
1480  if (pMin0 > temp_betagamma)
1481  pMin0 = temp_betagamma;
1482  }
1483  reduce(pMin0, pMin, OpMinAssign());
1484  INFOMSG("minimal beta*gamma = " << pMin << endl);
1485 
1486  double asinh0 = std::asinh(pMin);
1487  for (unsigned long int n = 0; n < getLocalNum(); n++) {
1488 
1489  double temp_betagamma = std::sqrt(std::pow(P[n](0), 2) + std::pow(P[n](1), 2));
1490  int itsBinID = std::floor((std::asinh(temp_betagamma) - asinh0) / eta + 1.0E-6);
1491  Bin[n] = itsBinID;
1492  if (maxbinIndex < itsBinID) {
1493  maxbinIndex = itsBinID;
1494  }
1495 
1496  if (itsBinID >= maxbin) {
1497  ERRORMSG("The bin number limit is " << maxbin << ", please increase the energy interval and try again" << endl);
1498  return false;
1499  } else
1500  partInBin[itsBinID]++;
1501 
1502  }
1503 
1504  // partInBin only count particle on the local node.
1505  pbin_m->resetPartInBin_cyc(partInBin, maxbinIndex);
1506 
1507  // after reset Particle Bin ID, update mass gamma of each bin again
1508  INFOMSG("After reset Bin: " << endl);
1509  calcGammas_cycl();
1510 
1511  return true;
1512 }
1513 
1514 
1515 template <class T, unsigned Dim>
1517  int maxbin = pbin_m->getNBins();
1518  std::size_t partInBin[maxbin];
1519  for (int i = 0; i < maxbin; ++i) {
1520  partInBin[i] = 0;
1521  }
1522 
1523  for (std::size_t i = 0; i < getLocalNum(); ++i) {
1524  partInBin[Bin[i]]++;
1525  }
1526 
1527  // partInBin only count particle on the local node.
1528  pbin_m->resetPartInBin_cyc(partInBin, numBunch_m - 1);
1529 
1530  // after reset Particle Bin ID, update mass gamma of each bin again
1531  calcGammas_cycl();
1532 
1533  return true;
1534 }
1535 
1536 
1537 template <class T, unsigned Dim>
1539  return reference->getQ();
1540 }
1541 
1542 
1543 template <class T, unsigned Dim>
1545  return reference->getM();
1546 }
1547 
1548 
1549 template <class T, unsigned Dim>
1551  return reference->getP();
1552 }
1553 
1554 
1555 template <class T, unsigned Dim>
1557  return reference->getE();
1558 }
1559 
1560 
1561 template <class T, unsigned Dim>
1563  return refPOrigin_m;
1564 }
1565 
1566 template <class T, unsigned Dim>
1568  refPOrigin_m = origin;
1569 }
1570 
1571 
1572 template <class T, unsigned Dim>
1574  return refPType_m;
1575 }
1576 
1577 template <class T, unsigned Dim>
1579 
1580  switch (refPType_m) {
1582  return "ELECTRON";
1583  case ParticleType::PROTON:
1584  return "PROTON";
1586  return "POSITRON";
1588  return "ANTIPROTON";
1589  case ParticleType::CARBON:
1590  return "CARBON";
1591  case ParticleType::HMINUS:
1592  return "HMINUS";
1593  case ParticleType::URANIUM:
1594  return "URANIUM";
1595  case ParticleType::MUON:
1596  return "MUON";
1598  return "DEUTERON";
1599  case ParticleType::XENON:
1600  return "XENON";
1601  case ParticleType::H2P:
1602  return "H2P";
1603  case ParticleType::ALPHA:
1604  return "ALPHA";
1606  return "HYDROGEN";
1607  case ParticleType::H3P:
1608  return "H3P";
1609  default:
1610  INFOMSG("Unknown type for OPAL particles" << endl);
1611  return "UNNAMED";
1612  }
1613 }
1614 
1615 template <class T, unsigned Dim>
1617 
1618  if (type == "ELECTRON") {
1619  refPType_m = ParticleType::ELECTRON;
1620  } else if (type == "PROTON") {
1621  refPType_m = ParticleType::PROTON;
1622  } else if (type == "POSITRON") {
1623  refPType_m = ParticleType::POSITRON;
1624  } else if (type == "ANTIPROTON") {
1625  refPType_m = ParticleType::ANTIPROTON;
1626  } else if (type == "CARBON") {
1627  refPType_m = ParticleType::CARBON;
1628  } else if (type == "HMINUS") {
1629  refPType_m = ParticleType::HMINUS;
1630  } else if (type == "URANIUM") {
1631  refPType_m = ParticleType::URANIUM;
1632  } else if (type == "MUON") {
1633  refPType_m = ParticleType::MUON;
1634  } else if (type == "DEUTERON") {
1635  refPType_m = ParticleType::DEUTERON;
1636  } else if (type == "XENON") {
1637  refPType_m = ParticleType::XENON;
1638  } else if (type == "H2P") {
1639  refPType_m = ParticleType::H2P;
1640  } else if (type == "ALPHA") {
1641  refPType_m = ParticleType::ALPHA;
1642  } else if (type == "HYDROGEN") {
1643  refPType_m = ParticleType::HYDROGEN;
1644  } else if (type == "H3P") {
1645  refPType_m = ParticleType::H3P;
1646  } else {
1647  INFOMSG("Unknown type for OPAL particles. Default ParticleType::UNNAMED is set" << endl);
1648  refPType_m = ParticleType::UNNAMED;
1649  }
1650 }
1651 
1652 
1653 template <class T, unsigned Dim>
1655  const_cast<PartData *>(reference)->setQ(q);
1656 }
1657 
1658 
1659 template <class T, unsigned Dim>
1661  const_cast<PartData *>(reference)->setM(m);
1662 }
1663 
1664 
1665 template <class T, unsigned Dim>
1667  return momentsComputer_m.getStdKineticEnergy();
1668 }
1669 
1670 
1671 template <class T, unsigned Dim>
1673  return reference->getBeta();
1674 }
1675 
1676 
1677 template <class T, unsigned Dim>
1679  return reference->getGamma();
1680 }
1681 
1682 
1683 template <class T, unsigned Dim>
1685  return 0;
1686 }
1687 
1688 
1689 template <class T, unsigned Dim>
1691  return 0;
1692 }
1693 
1694 
1695 template <class T, unsigned Dim>
1697  // do nothing here
1698 };
1699 
1700 
1701 template <class T, unsigned Dim>
1703  return reference;
1704 }
1705 
1706 
1707 template <class T, unsigned Dim>
1709  return dist_m->getEmissionDeltaT();
1710 }
1711 
1712 
1713 template <class T, unsigned Dim>
1715  binemitted_m[binNumber]++;
1716 }
1717 
1718 
1719 template <class T, unsigned Dim>
1721  momentsComputer_m.computeMeanKineticEnergy(*this);
1722 }
1723 
1724 template <class T, unsigned Dim>
1726 
1727  if (getTotalNum() != 0) { // to suppress Nans
1728  Inform::FmtFlags_t ff = os.flags();
1729 
1730  double pathLength = get_sPos();
1731 
1732  os << std::scientific;
1733  os << level1 << "\n";
1734  os << "* ************** B U N C H ********************************************************* \n";
1735  os << "* NP = " << getTotalNum() << "\n";
1736  os << "* Qtot = " << std::setw(17) << Util::getChargeString(std::abs(sum(Q))) << " "
1737  << "Qi = " << std::setw(17) << Util::getChargeString(std::abs(qi_m)) << "\n";
1738  os << "* Ekin = " << std::setw(17) << Util::getEnergyString(get_meanKineticEnergy()) << " "
1739  << "dEkin = " << std::setw(17) << Util::getEnergyString(getdE()) << "\n";
1740  os << "* rmax = " << Util::getLengthString(rmax_m, 5) << "\n";
1741  os << "* rmin = " << Util::getLengthString(rmin_m, 5) << "\n";
1742  if (getTotalNum() >= 2) { // to suppress Nans
1743  os << "* rms beam size = " << Util::getLengthString(get_rrms(), 5) << "\n";
1744  os << "* rms momenta = " << std::setw(12) << std::setprecision(5) << get_prms() << " [beta gamma]\n";
1745  os << "* mean position = " << Util::getLengthString(get_rmean(), 5) << "\n";
1746  os << "* mean momenta = " << std::setw(12) << std::setprecision(5) << get_pmean() << " [beta gamma]\n";
1747  os << "* rms emittance = " << std::setw(12) << std::setprecision(5) << get_emit() << " (not normalized)\n";
1748  os << "* rms correlation = " << std::setw(12) << std::setprecision(5) << get_rprms() << "\n";
1749  }
1750  os << "* hr = " << Util::getLengthString(get_hr(), 5) << "\n";
1751  os << "* dh = " << std::setw(13) << std::setprecision(5) << dh_m * 100 << " [%]\n";
1752  os << "* t = " << std::setw(17) << Util::getTimeString(getT()) << " "
1753  << "dT = " << std::setw(17) << Util::getTimeString(getdT()) << "\n";
1754  os << "* spos = " << std::setw(17) << Util::getLengthString(pathLength) << "\n";
1755  os << "* ********************************************************************************** " << endl;
1756  os.flags(ff);
1757  }
1758  return os;
1759 }
1760 
1761 // angle range [0~2PI) degree
1762 template <class T, unsigned Dim>
1763 double PartBunchBase<T, Dim>::calculateAngle(double x, double y) {
1764  double thetaXY = atan2(y, x);
1765 
1766  return thetaXY >= 0 ? thetaXY : thetaXY + Physics::two_pi;
1767 }
1768 
1769 
1770 template <class T, unsigned Dim>
1772  return p.print(os);
1773 }
1774 
1775 
1776 /*
1777  * Virtual member functions
1778  */
1779 
1780 template <class T, unsigned Dim>
1782  throw OpalException("PartBunchBase<T, Dim>::runTests() ", "No test supported.");
1783 }
1784 
1785 
1786 template <class T, unsigned Dim>
1788 
1789 }
1790 
1791 template <class T, unsigned Dim>
1792 void PartBunchBase<T, Dim>::swap(unsigned int i, unsigned int j) {
1793  if (i >= getLocalNum() || j >= getLocalNum() || i == j) return;
1794 
1795  std::swap(R[i], R[j]);
1796  std::swap(P[i], P[j]);
1797  std::swap(Q[i], Q[j]);
1798  std::swap(M[i], M[j]);
1799  std::swap(Phi[i], Phi[j]);
1800  std::swap(Ef[i], Ef[j]);
1801  std::swap(Eftmp[i], Eftmp[j]);
1802  std::swap(Bf[i], Bf[j]);
1803  std::swap(Bin[i], Bin[j]);
1804  std::swap(dt[i], dt[j]);
1805  std::swap(PType[i], PType[j]);
1806  std::swap(POrigin[i], POrigin[j]);
1807  std::swap(TriID[i], TriID[j]);
1808  std::swap(cavityGapCrossed[i], cavityGapCrossed[j]);
1809  std::swap(bunchNum[i], bunchNum[j]);
1810 }
1811 
1812 
1813 template <class T, unsigned Dim>
1815  throw OpalException("PartBunchBase<T, Dim>::setBCAllPeriodic() ", "Not supported BC.");
1816 }
1817 
1818 
1819 template <class T, unsigned Dim>
1821  throw OpalException("PartBunchBase<T, Dim>::setBCAllOpen() ", "Not supported BC.");
1822 }
1823 
1824 
1825 template <class T, unsigned Dim>
1827  throw OpalException("PartBunchBase<T, Dim>::setBCForDCBeam() ", "Not supported BC.");
1828 }
1829 
1830 
1831 template <class T, unsigned Dim>
1832 void PartBunchBase<T, Dim>::updateFields(const Vector_t& /*hr*/, const Vector_t& /*origin*/) {
1833 }
1834 
1835 
1836 template <class T, unsigned Dim>
1838 
1839  pb->addAttribute(P);
1840  pb->addAttribute(Q);
1841  pb->addAttribute(M);
1842  pb->addAttribute(Phi);
1843  pb->addAttribute(Ef);
1844  pb->addAttribute(Eftmp);
1845  pb->addAttribute(Bf);
1846  pb->addAttribute(Bin);
1847  pb->addAttribute(dt);
1848  pb->addAttribute(PType);
1849  pb->addAttribute(POrigin);
1850  pb->addAttribute(TriID);
1851  pb->addAttribute(cavityGapCrossed);
1852  pb->addAttribute(bunchNum);
1853 
1854  boundpTimer_m = IpplTimings::getTimer("Boundingbox");
1855  boundpBoundsTimer_m = IpplTimings::getTimer("Boundingbox-bounds");
1856  boundpUpdateTimer_m = IpplTimings::getTimer("Boundingbox-update");
1857  statParamTimer_m = IpplTimings::getTimer("Compute Statistics");
1858  selfFieldTimer_m = IpplTimings::getTimer("SelfField total");
1859 
1860  histoTimer_m = IpplTimings::getTimer("Histogram");
1861 
1862  distrCreate_m = IpplTimings::getTimer("Create Distr");
1863  distrReload_m = IpplTimings::getTimer("Load Distr");
1864 
1865  globalPartPerNode_m = std::unique_ptr<size_t[]>(new size_t[Ippl::getNodes()]);
1866 
1867  pmsg_m.release();
1868 }
1869 
1870 
1871 template <class T, unsigned Dim>
1873  return pbase_m->getTotalNum();
1874 }
1875 
1876 template <class T, unsigned Dim>
1878  return pbase_m->getLocalNum();
1879 }
1880 
1881 
1882 template <class T, unsigned Dim>
1884  return pbase_m->getDestroyNum();
1885 }
1886 
1887 template <class T, unsigned Dim>
1889  return pbase_m->getGhostNum();
1890 }
1891 
1892 template <class T, unsigned Dim>
1894  pbase_m->setTotalNum(n);
1895 }
1896 
1897 template <class T, unsigned Dim>
1899  pbase_m->setLocalNum(n);
1900 }
1901 
1902 template <class T, unsigned Dim>
1904  return pbase_m->getLayout();
1905 }
1906 
1907 template <class T, unsigned Dim>
1909  return pbase_m->getLayout();
1910 }
1911 
1912 template <class T, unsigned Dim>
1914  return pbase_m->getUpdateFlag(f);
1915 }
1916 
1917 template <class T, unsigned Dim>
1919  pbase_m->setUpdateFlag(f, val);
1920 }
1921 
1922 template <class T, unsigned Dim>
1924  return pbase_m->singleInitNode();
1925 }
1926 
1927 template <class T, unsigned Dim>
1929  pbase_m->resetID();
1930 }
1931 
1932 template <class T, unsigned Dim>
1934  try {
1935  pbase_m->update();
1936  } catch (const IpplException& ex) {
1937  throw OpalException(ex.where(), ex.what());
1938  }
1939 }
1940 
1941 template <class T, unsigned Dim>
1943  try {
1944  pbase_m->update(canSwap);
1945  } catch (const IpplException& ex) {
1946  throw OpalException(ex.where(), ex.what());
1947  }
1948 }
1949 
1950 template <class T, unsigned Dim>
1952  pbase_m->createWithID(id);
1953 }
1954 
1955 template <class T, unsigned Dim>
1957  pbase_m->create(M);
1958 }
1959 
1960 template <class T, unsigned Dim>
1962  pbase_m->globalCreate(np);
1963 }
1964 
1965 template <class T, unsigned Dim>
1966 void PartBunchBase<T, Dim>::destroy(size_t M, size_t I, bool doNow) {
1967  pbase_m->destroy(M, I, doNow);
1968 }
1969 
1970 template <class T, unsigned Dim>
1971 void PartBunchBase<T, Dim>::performDestroy(bool updateLocalNum) {
1972  pbase_m->performDestroy(updateLocalNum);
1973 }
1974 
1975 template <class T, unsigned Dim>
1976 void PartBunchBase<T, Dim>::ghostDestroy(size_t M, size_t I) {
1977  pbase_m->ghostDestroy(M, I);
1978 }
1979 
1980 template <class T, unsigned Dim>
1982  periodLength_m = Physics::c / f;
1983 }
1984 
1985 template <class T, unsigned Dim>
1987  //const double N = static_cast<double>(this->getTotalNum());
1988 
1989  Vektor<double, 2*Dim> rpmean;
1990  for (unsigned int i = 0; i < Dim; i++) {
1991  rpmean(2*i)= get_rmean()(i);
1992  rpmean((2*i)+1)= get_pmean()(i);
1993  }
1994 
1995  FMatrix<double, 2 * Dim, 2 * Dim> sigmaMatrix;// = moments_m / N;
1996  for (unsigned int i = 0; i < 2 * Dim; i++) {
1997  for (unsigned int j = 0; j <= i; j++) {
1998  sigmaMatrix[i][j] = moments_m(i, j) - rpmean(i) * rpmean(j);
1999  sigmaMatrix[j][i] = sigmaMatrix[i][j];
2000  }
2001  }
2002  return sigmaMatrix;
2003 }
2004 
2005 #endif
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
ParticleOrigin
Definition: PartBunchBase.h:46
ParticleType
Definition: PartBunchBase.h:50
Inform & operator<<(Inform &os, PartBunchBase< T, Dim > &p)
Inform * gmsg
Definition: Main.cpp:62
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition: Vector3D.cpp:118
const unsigned Dim
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
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
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)
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
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)
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
Inform & level1(Inform &inf)
Definition: Inform.cpp:45
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
Inform & level2(Inform &inf)
Definition: Inform.cpp:46
#define INFORM_ALL_NODES
Definition: Inform.h:39
#define ERRORMSG(msg)
Definition: IpplInfo.h:350
#define INFOMSG(msg)
Definition: IpplInfo.h:348
#define WARNMSG(msg)
Definition: IpplInfo.h:349
#define PAssert_LT(a, b)
Definition: PAssert.h:106
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:51
constexpr double pi
The value of.
Definition: Physics.h:30
double remotePartDel
Definition: Options.cpp:61
std::string getChargeString(double charge, unsigned int precision=3)
Definition: Util.h:151
std::string getEnergyString(double energyInMeV, unsigned int precision=3)
Definition: Util.h:128
std::string getTimeString(double time, unsigned int precision=3)
Definition: Util.h:55
std::string getLengthString(double spos, unsigned int precision=3)
Definition: Util.h:78
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)
const PartData * getReference() const
ParticleOrigin getPOrigin() const
void setMass(double mass)
void setCharge(double q)
int getSteptoLastInj() const
void boundp_destroyCycl()
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)
std::string getPTypeString()
double getMassPerParticle() const
double getQ() const
Access to reference data.
double getCouplingConstant() const
double getChargePerParticle() const
get the macro particle charge
virtual void set_meshEnlargement(double dh)
void resetM(double m)
virtual double getBeta(int i)
void getLocalBounds(Vector_t &rmin, Vector_t &rmax)
virtual double getPx0(int i)
size_t getLocalNum() const
void set_sPos(double s)
void setLocalTrackStep(long long n)
step in a TRACK command
void setLocalBinCount(size_t num, int bin)
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.
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)
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)
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)
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
virtual double getPy(int i)
double getBinGamma(int bin)
Get gamma of one bin.
double getInitialBeta() const
int getLastEmittedEnergyBin()
void calcBeamParameters()
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)
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.
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
void gatherLoadBalanceStatistics()
void countTotalNumPerBunch()
void get_bounds(Vector_t &rmin, Vector_t &rmax)
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
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)
FMatrix< double, 2 *Dim, 2 *Dim > getSigmaMatrix()
OpalParticle getParticle(int ii)
virtual void swap(unsigned int i, unsigned int j)
virtual void actT()
void setPType(std::string type)
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()
std::string getFieldSolverType() const
Return the fieldsolver type if we have a fieldsolver.
virtual Vector_t get_hr() const
Vector_t get_emit() const
double calculateAngle(double x, double y)
angle range [0~2PI) degree
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:195
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
A templated representation for vectors.
Definition: FVector.h:38
void createOpalT(PartBunchBase< double, 3 > *beam, std::vector< Distribution * > addedDistributions, size_t &numberOfParticles)
The FieldSolver definition.
Definition: FieldSolver.h:43
The base class for all OPAL exceptions.
Definition: OpalException.h:28
virtual void addAttribute(ParticleAttribBase &pa)=0
Definition: Inform.h:42
std::ios_base::fmtflags FmtFlags_t
Definition: Inform.h:99
FmtFlags_t flags() const
Definition: Inform.h:106
virtual const std::string & where() const
Definition: IpplException.h:19
virtual const char * what() const
Definition: IpplException.h:15
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