OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
ScatteringPhysics.cpp
Go to the documentation of this file.
1 //
2 // Class ScatteringPhysics
3 // Defines the physical processes of beam scattering
4 // and energy loss by heavy charged particles
5 //
6 // Copyright (c) 2009 - 2021, Bi, Yang, Stachel, Adelmann
7 // Paul Scherrer Institut, Villigen PSI, Switzerland
8 // All rights reserved.
9 //
10 // This file is part of OPAL.
11 //
12 // OPAL is free software: you can redistribute it and/or modify
13 // it under the terms of the GNU General Public License as published by
14 // the Free Software Foundation, either version 3 of the License, or
15 // (at your option) any later version.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
19 //
21 
25 #include "AbsBeamline/Degrader.h"
26 #include "AbsBeamline/Drift.h"
27 #include "AbsBeamline/SBend.h"
28 #include "AbsBeamline/RBend.h"
29 #include "AbsBeamline/Multipole.h"
30 #include "Physics/Physics.h"
31 #include "Physics/Material.h"
32 #include "Structure/LossDataSink.h"
33 #include "Utilities/Options.h"
35 #include "Utilities/Util.h"
36 #include "Utilities/Timer.h"
37 
38 #include "Utility/Inform.h"
39 
40 #include <gsl/gsl_randist.h>
41 
42 #include <algorithm>
43 #include <cmath>
44 #include <fstream>
45 #include <iostream>
46 
47 #include <sys/time.h>
48 
49 namespace {
50  struct DegraderInsideTester: public InsideTester {
51  explicit DegraderInsideTester(ElementBase* el) {
52  deg_m = static_cast<Degrader*>(el);
53  }
54  virtual
55  bool checkHit(const Vector_t& R) override {
56  return deg_m->isInMaterial(R(2));
57  }
58  private:
59  Degrader* deg_m;
60  };
61 
62  struct CollimatorInsideTester: public InsideTester {
63  explicit CollimatorInsideTester(ElementBase* el) {
64  col_m = static_cast<CCollimator*>(el);
65  }
66  virtual
67  bool checkHit(const Vector_t& R) override {
68  return col_m->checkPoint(R(0), R(1));
69  }
70  private:
71  CCollimator* col_m;
72  };
73 
74  struct FlexCollimatorInsideTester: public InsideTester {
75  explicit FlexCollimatorInsideTester(ElementBase* el) {
76  col_m = static_cast<FlexibleCollimator*>(el);
77  }
78  virtual
79  bool checkHit(const Vector_t& R) override {
80  return col_m->isStopped(R);
81  }
82  private:
83  FlexibleCollimator* col_m;
84  };
85 }
86 
88  ElementBase* element,
89  std::string& material,
90  bool enableRutherford,
91  double lowEnergyThr):
93  T_m(0.0),
94  dT_m(0.0),
95  mass_m(0.0),
96  charge_m(0.0),
97  material_m(material),
98  hitTester_m(nullptr),
99  Z_m(0),
100  A_m(0.0),
101  rho_m(0.0),
102  X0_m(0.0),
103  I_m(0.0),
104  A1_c(0.0),
105  A2_c(0.0),
106  A3_c(0.0),
107  A4_c(0.0),
108  A5_c(0.0),
109  B1_c(0.0),
110  B2_c(0.0),
111  B3_c(0.0),
112  B4_c(0.0),
113  B5_c(0.0),
114  bunchToMatStat_m(0),
115  stoppedPartStat_m(0),
116  rediffusedStat_m(0),
117  totalPartsInMat_m(0),
118  Eavg_m(0.0),
119  Emax_m(0.0),
120  Emin_m(0.0),
121  enableRutherford_m(enableRutherford),
122  lowEnergyThr_m(lowEnergyThr)
123 {
124 
125  gsl_rng_env_setup();
126  rGen_m = gsl_rng_alloc(gsl_rng_default);
127 
128  size_t mySeed = Options::seed;
129 
130  if (Options::seed == -1) {
131  struct timeval tv;
132  gettimeofday(&tv,0);
133  mySeed = tv.tv_sec + tv.tv_usec;
134  }
135 
136  gsl_rng_set(rGen_m, mySeed + Ippl::myNode());
137 
139 
141  switch (collshape_m) {
143  hitTester_m.reset(new DegraderInsideTester(element_ref_m));
144  break;
146  hitTester_m.reset(new CollimatorInsideTester(element_ref_m));
147  break;
149  hitTester_m.reset(new FlexCollimatorInsideTester(element_ref_m));
150  break;
151  default:
152  throw GeneralClassicException("ScatteringPhysics::ScatteringPhysics",
153  "Unsupported element type");
154  }
155 
156  lossDs_m = std::unique_ptr<LossDataSink>(new LossDataSink(getName(), !Options::asciidump));
157 
158  DegraderApplyTimer_m = IpplTimings::getTimer("DegraderApply");
159  DegraderLoopTimer_m = IpplTimings::getTimer("DegraderLoop");
160  DegraderDestroyTimer_m = IpplTimings::getTimer("DegraderDestroy");
161 }
162 
164  locParts_m.clear();
165  lossDs_m->save();
166  if (rGen_m)
167  gsl_rng_free(rGen_m);
168 }
169 
170 
172 // ------------------------------------------------------------------------
174 
176  Z_m = material->getAtomicNumber();
177  A_m = material->getAtomicMass();
178  rho_m = material->getMassDensity();
179  X0_m = material->getRadiationLength();
180  I_m = material->getMeanExcitationEnergy();
181  A1_c = material->getStoppingPowerFitCoefficients(Physics::Material::A1);
182  A2_c = material->getStoppingPowerFitCoefficients(Physics::Material::A2);
183  A3_c = material->getStoppingPowerFitCoefficients(Physics::Material::A3);
184  A4_c = material->getStoppingPowerFitCoefficients(Physics::Material::A4);
185  A5_c = material->getStoppingPowerFitCoefficients(Physics::Material::A5);
186  B1_c = material->getStoppingPowerFitCoefficients(Physics::Material::B1);
187  B2_c = material->getStoppingPowerFitCoefficients(Physics::Material::B2);
188  B3_c = material->getStoppingPowerFitCoefficients(Physics::Material::B3);
189  B4_c = material->getStoppingPowerFitCoefficients(Physics::Material::B4);
190  B5_c = material->getStoppingPowerFitCoefficients(Physics::Material::B5);
191 }
192 
194  const std::pair<Vector_t, double>& boundingSphere) {
196 
197  /*
198  Particles that have entered material are flagged as Bin[i] == -1.
199 
200  Flagged particles are copied to a local structure within Scattering Physics locParts_m.
201 
202  Particles in that structure will be pushed in the material and either come
203  back to the bunch or will be fully stopped in the material.
204  */
205 
206  ParticleType pType = bunch->getPType();
207  if (pType != ParticleType::PROTON &&
208  pType != ParticleType::DEUTERON &&
209  pType != ParticleType::HMINUS &&
210  pType != ParticleType::MUON &&
211  pType != ParticleType::H2P &&
212  pType != ParticleType::ALPHA) {
213 
215  "ScatteringPhysics::apply",
216  "Particle " + bunch->getPTypeString() +
217  " is not supported for scattering interactions!");
218  }
219 
220  Eavg_m = 0.0;
221  Emax_m = 0.0;
222  Emin_m = 0.0;
223 
224  bunchToMatStat_m = 0;
225  rediffusedStat_m = 0;
226  stoppedPartStat_m = 0;
227  totalPartsInMat_m = 0;
228 
229  dT_m = bunch->getdT();
230  T_m = bunch->getT();
231  mass_m = bunch->getM();
232  charge_m = bunch->getQ();
233 
234  bool onlyOneLoopOverParticles = ! (allParticleInMat_m);
235 
236  do {
238  push();
240 
241  // if we are not looping copy newly arrived particles
242  if (onlyOneLoopOverParticles) {
243  copyFromBunch(bunch, boundingSphere);
244  }
245  addBackToBunch(bunch);
246 
247  computeInteraction(bunch);
248 
249  push();
250  resetTimeStep();
251 
253 
254  T_m += dT_m; // update local time
255 
257 
258  if (allParticleInMat_m) {
259  onlyOneLoopOverParticles = (rediffusedStat_m > 0 || totalPartsInMat_m <= 0);
260  } else {
261  onlyOneLoopOverParticles = true;
262  }
263  } while (onlyOneLoopOverParticles == false);
264 
266 }
267 
269  /*
270  Do physics if
271  -- correct type of particle
272  -- particle not stopped (locParts_m[i].label != -1.0)
273 
274  Absorbed particle i: locParts_m[i].label = -1.0;
275  */
276  for (size_t i = 0; i < locParts_m.size(); ++i) {
277  if (locParts_m[i].label != -1) {
278  Vector_t &R = locParts_m[i].Rincol;
279  Vector_t &P = locParts_m[i].Pincol;
280  double &dt = locParts_m[i].DTincol;
281 
282  if (hitTester_m->checkHit(R)) {
283  bool pdead = computeEnergyLoss(bunch, P, dt);
284  if (!pdead) {
285  /*
286  Now scatter and transport particle in material.
287  The checkHit call just above will detect if the
288  particle is rediffused from the material into vacuum.
289  */
290 
291  computeCoulombScattering(R, P, dt);
292  } else {
293  // The particle is stopped in the material, set label to -1
294  locParts_m[i].label = -1.0;
296  lossDs_m->addParticle(OpalParticle(locParts_m[i].IDincol,
297  R, P, T_m,
298  locParts_m[i].Qincol, locParts_m[i].Mincol));
299  }
300  }
301  }
302  }
303 
304  // delete absorbed particles
306 }
307 
314 // -------------------------------------------------------------------------
316  Vector_t& P,
317  const double deltat,
318  bool includeFluctuations) const {
319 
320  ParticleType pType = bunch->getPType();
321  constexpr double m2cm = 1e2;
322  constexpr double eV2keV = 1e-3;
323  constexpr double GeV2keV = 1e6;
324  const double mass_keV = mass_m * eV2keV;
325  constexpr double massElectron_keV = Physics::m_e * GeV2keV;
326 
327  constexpr double K = 4.0 * Physics::pi * Physics::Avo * Physics::r_e * m2cm * Physics::r_e * m2cm * massElectron_keV;
328 
329  double gamma = Util::getGamma(P);
330  const double gammaSqr = std::pow(gamma, 2);
331  const double betaSqr = 1.0 - 1.0 / gammaSqr;
332  double beta = std::sqrt(betaSqr);
333  double Ekin = (gamma - 1) * mass_keV;
334  double dEdx = 0.0;
335  double epsilon = 0.0;
336 
337  const double deltas = deltat * beta * Physics::c;
338  const double deltasrho = deltas * m2cm * rho_m;
339 
340  const double massRatio = massElectron_keV / mass_keV;
341  double Tmax = (2.0 * massElectron_keV * betaSqr * gammaSqr /
342  (std::pow(gamma + massRatio, 2) - (gammaSqr - 1.0)));
343 
344  if (pType != ParticleType::ALPHA) {
345 
346  if (Ekin >= 600 && Ekin < 1e7) {
347  dEdx = (-K * std::pow(charge_m, 2) * Z_m / (A_m * betaSqr) *
348  (0.5 * std::log(2 * massElectron_keV * betaSqr * gammaSqr * Tmax / std::pow(I_m * eV2keV, 2)) - betaSqr));
349  } else if (pType == ParticleType::PROTON && Ekin < 600) {
350  constexpr double massProton_amu = Physics::m_p / Physics::amu;
351  const double Ts = Ekin / massProton_amu;
352  if (Ekin > 10) {
353  const double epsilon_low = A2_c * std::pow(Ts, 0.45);
354  const double epsilon_high = (A3_c / Ts) * std::log(1 + (A4_c / Ts) + (A5_c * Ts));
355  epsilon = (epsilon_low * epsilon_high) / (epsilon_low + epsilon_high);
356  } else if (Ekin > 1) {
357  epsilon = A1_c * std::pow(Ts, 0.5);
358  }
359  dEdx = -epsilon / (1e18 * (A_m / Physics::Avo));
360  } else {
361  INFOMSG(level4 << "Particle energy out of the valid range "
362  "for energy loss calculation." << endl);
363  }
364  } else {
365  if (Ekin > 10000 && Ekin < 1e6) {
366  dEdx = (-K * std::pow(charge_m, 2) * Z_m / (A_m * betaSqr) *
367  (0.5 * std::log(2 * massElectron_keV * betaSqr * gammaSqr * Tmax / std::pow(I_m * eV2keV, 2)) - betaSqr));
368  } else if (Ekin > 1 && Ekin <= 10000) {
369  const double T = Ekin * 1e-3; //MeV
370  const double epsilon_low = B1_c * std::pow(1000*T, B2_c);
371  const double epsilon_high = (B3_c / T) * std::log(1 + (B4_c / T) + (B5_c * T));
372  epsilon = (epsilon_low * epsilon_high) / (epsilon_low + epsilon_high);
373  dEdx = -epsilon / (1e18 * (A_m / Physics::Avo));
374  } else {
375  INFOMSG(level4 << "Particle energy out of the valid range "
376  "for energy loss calculation." << endl);
377  }
378  }
379 
380  Ekin += deltasrho * dEdx;
381 
382  if (includeFluctuations) {
383  double sigma_E = std::sqrt(K * massElectron_keV * rho_m * (Z_m / A_m) * deltas * m2cm);
384  Ekin += gsl_ran_gaussian(rGen_m, sigma_E);
385  }
386 
387  gamma = Ekin / mass_keV + 1.0;
388  beta = std::sqrt(1.0 - 1.0 / std::pow(gamma, 2));
389  P = gamma * beta * P / euclidean_norm(P);
390 
391  bool stopped = (Ekin < lowEnergyThr_m * 1e3 || dEdx > 0);
392  return stopped;
393 }
394 
395 
396 // Implement the rotation in 2 dimensions here
397 // For details see: J. Beringer et al. (Particle Data Group),
398 // "Passage of particles through matter", Phys. Rev. D 86, 010001 (2012)
399 // -------------------------------------------------------------------------
401  Vector_t& R,
402  double shift,
403  double thetacou) {
404  // Calculate the angle between the transverse and longitudinal component of the momentum
405  double Psixz = std::fmod(std::atan2(P(0), P(2)) + Physics::two_pi, Physics::two_pi);
406 
407  R(0) = R(0) + shift * std::cos(Psixz);
408  R(2) = R(2) - shift * std::sin(Psixz);
409 
410  // Apply the rotation about the random angle thetacou
411  double Px = P(0);
412  P(0) = Px * std::cos(thetacou) + P(2) * std::sin(thetacou);
413  P(2) = -Px * std::sin(thetacou) + P(2) * std::cos(thetacou);
414 }
415 
417 
418  double thetaru = 2.5 / std::sqrt(gsl_rng_uniform(rGen_m)) * 2.0 * theta0;
419  double phiru = Physics::two_pi * gsl_rng_uniform(rGen_m);
420 
421  double normPtrans = std::sqrt(P(0) * P(0) + P(1) * P(1));
422  double Theta = std::atan(normPtrans / std::abs(P(2)));
423  double CosT = std::cos(Theta);
424  double SinT = std::sin(Theta);
425 
426  Vector_t X(std::cos(phiru)*std::sin(thetaru),
427  std::sin(phiru)*std::sin(thetaru),
428  std::cos(thetaru));
429  X *= euclidean_norm(P);
430 
431  Vector_t W(-P(1), P(0), 0.0);
432  W = W / normPtrans;
433 
434  // Rodrigues' formula for a rotation about W by angle Theta
435  P = X * CosT + cross(W, X) * SinT + W * dot(W, X) * (1.0 - CosT);
436 }
437 
440 //--------------------------------------------------------------------------
442  Vector_t& P,
443  double dt) {
444 
445  constexpr double sqrtThreeInv = 0.57735026918962576451; // sqrt(1.0 / 3.0)
446  const double normP = euclidean_norm(P);
447  const double gammaSqr = std::pow(normP, 2) + 1.0;
448  const double beta = std::sqrt(1.0 - 1.0 / gammaSqr);
449  const double deltas = dt * beta * Physics::c;
450  const double theta0 = (13.6e6 / (beta * normP * mass_m) *
451  charge_m * std::sqrt(deltas / X0_m) *
452  (1.0 + 0.038 * std::log(deltas / X0_m)));
453 
454  double phi = Physics::two_pi * gsl_rng_uniform(rGen_m);
455  for (unsigned int i = 0; i < 2; ++ i) {
456  CoordinateSystemTrafo randomTrafo(R, Quaternion(cos(phi), 0, 0, sin(phi)));
457  P = randomTrafo.rotateTo(P);
458  R = Vector_t(0.0); // corresponds to randomTrafo.transformTo(R);
459 
460  double z1 = gsl_ran_gaussian(rGen_m, 1.0);
461  double z2 = gsl_ran_gaussian(rGen_m, 1.0);
462 
463  while(std::abs(z2) > 3.5) {
464  z1 = gsl_ran_gaussian(rGen_m, 1.0);
465  z2 = gsl_ran_gaussian(rGen_m, 1.0);
466  }
467 
468  double thetacou = z2 * theta0;
469  double shift = (z1 * sqrtThreeInv + z2) * deltas * theta0 * 0.5;
470  applyRotation(P, R, shift, thetacou);
471 
472  P = randomTrafo.rotateFrom(P);
473  R = randomTrafo.transformFrom(R);
474 
475  phi += 0.5 * Physics::pi;
476  }
477 
478  if (enableRutherford_m &&
479  gsl_rng_uniform(rGen_m) < 0.0047) {
480 
481  applyRandomRotation(P, theta0);
482  }
483 }
484 
486 
487  const size_t nL = locParts_m.size();
488  if (nL == 0) return;
489 
490  unsigned int numLocalParticles = bunch->getLocalNum();
491  const double elementLength = element_ref_m->getElementLength();
492 
493  for (size_t i = 0; i < nL; ++ i) {
494  Vector_t& R = locParts_m[i].Rincol;
495 
496  if (R[2] >= elementLength) {
497 
498  bunch->createWithID(locParts_m[i].IDincol);
499 
500  /*
501  Binincol is still <0, but now the particle is rediffused
502  from the material and hence this is not a "lost" particle anymore
503  */
504  bunch->Bin[numLocalParticles] = 1;
505  bunch->R[numLocalParticles] = R;
506  bunch->P[numLocalParticles] = locParts_m[i].Pincol;
507  bunch->Q[numLocalParticles] = locParts_m[i].Qincol;
508  bunch->M[numLocalParticles] = locParts_m[i].Mincol;
509  bunch->Bf[numLocalParticles] = 0.0;
510  bunch->Ef[numLocalParticles] = 0.0;
511  bunch->dt[numLocalParticles] = dT_m;
512 
513  /*
514  This particle is back to the bunch, by set
515  ting the label to -1.0
516  the particle will be deleted.
517  */
518  locParts_m[i].label = -1.0;
519 
520  ++ rediffusedStat_m;
521  ++ numLocalParticles;
522  }
523  }
524 
525  // delete particles that went to the bunch
527 }
528 
530  const std::pair<Vector_t, double>& boundingSphere)
531 {
532  const size_t nL = bunch->getLocalNum();
533  if (nL == 0) return;
534 
536  double zmax = boundingSphere.first(2) + boundingSphere.second;
537  double zmin = boundingSphere.first(2) - boundingSphere.second;
538  if (zmax < 0.0 || zmin > element_ref_m->getElementLength()) {
540  return;
541  }
542 
543  size_t ne = 0;
544  std::set<size_t> partsToDel;
545  for (size_t i = 0; i < nL; ++ i) {
546  if ((bunch->Bin[i] == -1 || bunch->Bin[i] == 1) &&
547  hitTester_m->checkHit(bunch->R[i]))
548  {
549  // adjust the time step for those particles that enter the material
550  // such that it corresponds to the time needed to reach the current
551  // location form the edge of the material. Only use this time step
552  // for the computation of the interaction with the material, not for
553  // the integration of the particles. This will ensure that the momenta
554  // of all particles are reduced by approximately the same amount in
555  // computeEnergyLoss.
556  double betaz = bunch->P[i](2) / Util::getGamma(bunch->P[i]);
557  double stepWidth = betaz * Physics::c * bunch->dt[i];
558  double tau = bunch->R[i](2) / stepWidth;
559 
560  PAssert_LE(tau, 1.0);
561  PAssert_GE(tau, 0.0);
562 
563  PART x;
564  x.localID = i;
565  x.DTincol = bunch->dt[i] * tau;
566  x.IDincol = bunch->ID[i];
567  x.Binincol = bunch->Bin[i];
568  x.Rincol = bunch->R[i];
569  x.Pincol = bunch->P[i];
570  x.Qincol = bunch->Q[i];
571  x.Mincol = bunch->M[i];
572  x.Bfincol = bunch->Bf[i];
573  x.Efincol = bunch->Ef[i];
574  x.label = 0; // alive in matter
575 
576  locParts_m.push_back(x);
577  ne++;
579 
580  partsToDel.insert(i);
581  }
582  }
583 
584  for (auto it = partsToDel.begin(); it != partsToDel.end(); ++ it) {
585  bunch->destroy(1, *it);
586  }
587 
588  if (ne > 0) {
589  bunch->performDestroy(true);
590  }
591 
593 }
594 
596  Inform::FmtFlags_t ff = msg.flags();
597 
598  if (totalPartsInMat_m > 0 ||
599  bunchToMatStat_m > 0 ||
600  rediffusedStat_m > 0 ||
601  stoppedPartStat_m > 0) {
602 
603  OPALTimer::Timer time;
604  msg << level2
605  << "--- ScatteringPhysics\n"
606  << "Name: " << name_m << " - "
607  << "Material: " << material_m << " - "
608  << "Element: " << element_ref_m->getName() << "\n"
609  << "Particle Statistics @ " << time.time() << "\n"
610  << std::setw(21) << "entered: " << Util::toStringWithThousandSep(bunchToMatStat_m) << "\n"
611  << std::setw(21) << "rediffused: " << Util::toStringWithThousandSep(rediffusedStat_m) << "\n"
612  << std::setw(21) << "stopped: " << Util::toStringWithThousandSep(stoppedPartStat_m) << "\n"
613  << std::setw(21) << "total in material: " << Util::toStringWithThousandSep(totalPartsInMat_m)
614  << endl;
615  }
616 
617  msg.flags(ff);
618 }
619 
621  return totalPartsInMat_m != 0;
622 }
623 
624 namespace {
625  bool myCompF(PART x, PART y) {
626  return x.label > y.label;
627  }
628 }
629 
631  /*
632  the particle to be deleted (label < 0) are all
633  at the end of the vector.
634  */
635  sort(locParts_m.begin(), locParts_m.end(), myCompF);
636 
637  // find start of particles to delete
639 
640  for (; inv != locParts_m.end(); ++inv) {
641  if ((*inv).label == -1)
642  break;
643  }
644  locParts_m.erase(inv, locParts_m.end());
645  locParts_m.resize(inv - locParts_m.begin());
646 
647  // update statistics
648  if (locParts_m.size() > 0) {
649  Eavg_m /= locParts_m.size();
650  Emin_m /= locParts_m.size();
651  Emax_m /= locParts_m.size();
652  }
653 }
654 
656  for (size_t i = 0; i < locParts_m.size(); ++i) {
657  Vector_t& R = locParts_m[i].Rincol;
658  Vector_t& P = locParts_m[i].Pincol;
659  double gamma = Util::getGamma(P);
660 
661  R += 0.5 * dT_m * Physics::c * P / gamma;
662  }
663 }
664 
665 // adjust the time step for those particles that will rediffuse to
666 // vacuum such that it corresponds to the time needed to reach the
667 // end of the material. Only use this time step for the computation
668 // of the interaction with the material, not for the integration of
669 // the particles. This will ensure that the momenta of all particles
670 // are reduced by approcimately the same amount in computeEnergyLoss.
672  const double elementLength = element_ref_m->getElementLength();
673 
674  for (size_t i = 0; i < locParts_m.size(); ++i) {
675  Vector_t& R = locParts_m[i].Rincol;
676  Vector_t& P = locParts_m[i].Pincol;
677  double& dt = locParts_m[i].DTincol;
678  double gamma = Util::getGamma(P);
679  Vector_t stepLength = dT_m * Physics::c * P / gamma;
680 
681  if (R(2) < elementLength &&
682  R(2) + stepLength(2) > elementLength) {
683  // particle is likely to leave material
684  double distance = elementLength - R(2);
685  double tau = distance / stepLength(2);
686 
687  PAssert_LE(tau, 1.0);
688  PAssert_GE(tau, 0.0);
689 
690  dt *= tau;
691  }
692  }
693 }
694 
696  for (size_t i = 0; i < locParts_m.size(); ++i) {
697  double& dt = locParts_m[i].DTincol;
698  dt = dT_m;
699  }
700 }
701 
702 
704 
705  unsigned int locPartsInMat;
706  locPartsInMat = locParts_m.size();
707 
708  constexpr unsigned short numItems = 4;
709  unsigned int partStatistics[numItems] = {locPartsInMat,
713 
714  allreduce(&(partStatistics[0]), numItems, std::plus<unsigned int>());
715 
716  totalPartsInMat_m = partStatistics[0];
717  bunchToMatStat_m = partStatistics[1];
718  rediffusedStat_m = partStatistics[2];
719  stoppedPartStat_m = partStatistics[3];
720 }
Tps< T > log(const Tps< T > &x)
Natural logarithm.
Definition: TpsMath.h:182
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Definition: TpsMath.h:76
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
T euclidean_norm(const Vector< T > &)
Euclidean norm.
Definition: Vector.h:243
ParticleType
Definition: PartBunchBase.h:50
Vector3D cross(const Vector3D &lhs, const Vector3D &rhs)
Vector cross product.
Definition: Vector3D.cpp:111
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition: Vector3D.cpp:118
#define X(arg)
Definition: fftpack.cpp:112
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
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
PETE_TBTree< FnFmod, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > fmod(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
PETE_TBTree< FnArcTan2, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > atan2(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
PETE_TUTree< FnArcTan, typename T::PETE_Expr_t > atan(const PETE_Expr< T > &l)
Definition: PETE.h:727
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
Inform & level2(Inform &inf)
Definition: Inform.cpp:46
Inform & level4(Inform &inf)
Definition: Inform.cpp:48
#define INFOMSG(msg)
Definition: IpplInfo.h:348
#define PAssert_LE(a, b)
Definition: PAssert.h:107
#define PAssert_GE(a, b)
Definition: PAssert.h:109
const std::string name
constexpr double amu
The atomic mass unit energy equivalent in GeV.
Definition: Physics.h:81
constexpr double two_pi
The value of.
Definition: Physics.h:33
constexpr double Avo
The Avogadro's number.
Definition: Physics.h:63
constexpr double m_p
The proton rest mass in GeV.
Definition: Physics.h:96
constexpr double m_e
The electron rest mass in GeV.
Definition: Physics.h:84
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
constexpr double r_e
The classical electron radius in m.
Definition: Physics.h:87
std::string::iterator iterator
Definition: MSLang.h:16
bool asciidump
Definition: Options.cpp:85
int seed
The current random seed.
Definition: Options.cpp:37
double getGamma(Vector_t p)
Definition: Util.h:27
std::string toStringWithThousandSep(T value, char sep='\'')
Definition: Util.h:209
ParticleAttrib< Vector_t > Ef
ParticlePos_t & R
ParticleAttrib< int > Bin
std::string getPTypeString()
double getQ() const
Access to reference data.
size_t getLocalNum() const
ParticleAttrib< double > M
ParticleAttrib< Vector_t > P
double getdT() const
ParticleAttrib< double > Q
ParticleType getPType() const
void createWithID(unsigned id)
ParticleAttrib< double > dt
void performDestroy(bool updateLocalNum=false)
void destroy(size_t M, size_t I, bool doNow=false)
ParticleAttrib< Vector_t > Bf
ParticleIndex_t & ID
double getM() const
double getT() const
virtual bool isInMaterial(double z)
Definition: Degrader.cpp:65
virtual const std::string & getName() const
Get element name.
virtual double getElementLength() const
Get design length.
Definition: ElementBase.h:432
@ FLEXIBLECOLLIMATOR
Definition: ElementBase.h:114
virtual ElementType getType() const =0
Get element type std::string.
bool isStopped(const Vector_t &R)
int checkPoint(const double &x, const double &y) const
Checks if coordinate is within element.
Vector_t rotateFrom(const Vector_t &r) const
Vector_t transformFrom(const Vector_t &r) const
Vector_t rotateTo(const Vector_t &r) const
static std::shared_ptr< Material > getMaterial(const std::string &name)
Definition: Material.cpp:53
bool allParticleInMat_m
if all particles are in matter stay inside the particle matter interaction
double Qincol
long IDincol
unsigned localID
double DTincol
double Mincol
int Binincol
Vector_t Rincol
Vector_t Pincol
Vector_t Bfincol
Vector_t Efincol
void addBackToBunch(PartBunchBase< double, 3 > *bunch)
virtual bool computeEnergyLoss(PartBunchBase< double, 3 > *bunch, Vector_t &P, const double deltat, bool includeFluctuations=true) const
void configureMaterialParameters()
The material of the collimator.
virtual bool stillActive()
ElementBase::ElementType collshape_m
void copyFromBunch(PartBunchBase< double, 3 > *bunch, const std::pair< Vector_t, double > &boundingSphere)
virtual void apply(PartBunchBase< double, 3 > *bunch, const std::pair< Vector_t, double > &boundingSphere)
unsigned int bunchToMatStat_m
IpplTimings::TimerRef DegraderLoopTimer_m
void applyRotation(Vector_t &P, Vector_t &R, double xplane, double thetacou)
ScatteringPhysics(const std::string &name, ElementBase *element, std::string &mat, bool enableRutherford, double lowEnergyThr)
void computeInteraction(PartBunchBase< double, 3 > *bunch)
unsigned int totalPartsInMat_m
void applyRandomRotation(Vector_t &P, double theta0)
void computeCoulombScattering(Vector_t &R, Vector_t &P, double dt)
std::unique_ptr< InsideTester > hitTester_m
virtual std::string getName()
std::vector< PART > locParts_m
unsigned int rediffusedStat_m
IpplTimings::TimerRef DegraderApplyTimer_m
unsigned int stoppedPartStat_m
IpplTimings::TimerRef DegraderDestroyTimer_m
virtual void print(Inform &os)
std::unique_ptr< LossDataSink > lossDs_m
std::string time() const
Return time.
Definition: Timer.cpp:42
Definition: Inform.h:42
std::ios_base::fmtflags FmtFlags_t
Definition: Inform.h:99
FmtFlags_t flags() const
Definition: Inform.h:106
static int myNode()
Definition: IpplInfo.cpp:691
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
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6