Version: SMASH-3.1
action.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2024
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #include "smash/action.h"
11 
12 #include <assert.h>
13 
14 #include <algorithm>
15 #include <sstream>
16 
17 #include "smash/angles.h"
18 #include "smash/constants.h"
19 #include "smash/logging.h"
20 #include "smash/pauliblocking.h"
22 #include "smash/quantumnumbers.h"
23 
24 namespace smash {
26 Action::~Action() = default;
27 static constexpr int LPauliBlocking = LogArea::PauliBlocking::id;
28 
29 bool Action::is_valid(const Particles &particles) const {
30  return std::all_of(
32  [&particles](const ParticleData &p) { return particles.is_valid(p); });
33 }
34 
35 bool Action::is_pauli_blocked(const std::vector<Particles> &ensembles,
36  const PauliBlocker &p_bl) const {
37  // Wall-crossing actions should never be blocked: currently
38  // if the action is blocked, a particle continues to propagate in a straight
39  // line. This would simply bring it out of the box.
41  return false;
42  }
43  for (const auto &p : outgoing_particles_) {
44  if (p.is_baryon()) {
45  const auto f =
46  p_bl.phasespace_dens(p.position().threevec(), p.momentum().threevec(),
47  ensembles, p.pdgcode(), incoming_particles_);
48  if (f > random::uniform(0., 1.)) {
49  logg[LPauliBlocking].debug("Action ", *this,
50  " is pauli-blocked with f = ", f);
51  return true;
52  }
53  }
54  }
55  return false;
56 }
57 
58 const ParticleList &Action::incoming_particles() const {
59  return incoming_particles_;
60 }
61 
62 void Action::update_incoming(const Particles &particles) {
63  for (auto &p : incoming_particles_) {
64  p = particles.lookup(p);
65  }
66 }
67 
69  // Estimate for the interaction point in the calculational frame
70  ThreeVector interaction_point = ThreeVector(0., 0., 0.);
71  std::vector<ThreeVector> propagated_positions;
72  for (const auto &part : incoming_particles_) {
73  ThreeVector propagated_position =
74  part.position().threevec() +
75  part.velocity() * (time_of_execution_ - part.position().x0());
76  propagated_positions.push_back(propagated_position);
77  interaction_point += propagated_position;
78  }
79  interaction_point /= incoming_particles_.size();
80  /*
81  * In case of periodic boundaries interaction point is not necessarily
82  * (x1 + x2)/2. Consider only one dimension, e.g. x, the rest are analogous.
83  * Instead of x, there can be x + k * L, where k is any integer and L
84  * is period.Interaction point is either. Therefore, interaction point is
85  * (x1 + k * L + x2 + m * L) / 2 = (x1 + x2) / 2 + n * L / 2. We need
86  * this interaction point to be with [0, L], so n can be {-1, 0, 1}.
87  * Which n to choose? Our guiding principle is that n should be such that
88  * interaction point is closest to interacting particles.
89  */
90  if (box_length_ > 0 && stochastic_position_idx_ < 0) {
91  assert(incoming_particles_.size() == 2);
92  const ThreeVector r = propagated_positions[0] - propagated_positions[1];
93  for (int i = 0; i < 3; i++) {
94  const double d = std::abs(r[i]);
95  if (d > 0.5 * box_length_) {
96  if (interaction_point[i] >= 0.5 * box_length_) {
97  interaction_point[i] -= 0.5 * box_length_;
98  } else {
99  interaction_point[i] += 0.5 * box_length_;
100  }
101  }
102  }
103  }
104  /* In case of scatterings via the stochastic criterion, use postion of random
105  * incoming particle to prevent density hotspots in grid cell centers. */
106  if (stochastic_position_idx_ >= 0) {
108  }
109  return FourVector(time_of_execution_, interaction_point);
110 }
111 
112 std::pair<FourVector, FourVector> Action::get_potential_at_interaction_point()
113  const {
115  FourVector UB = FourVector();
116  FourVector UI3 = FourVector();
117  /* Check:
118  * Lattice is turned on. */
119  if (UB_lat_pointer != nullptr) {
120  UB_lat_pointer->value_at(r, UB);
121  }
122  if (UI3_lat_pointer != nullptr) {
123  UI3_lat_pointer->value_at(r, UI3);
124  }
125  return std::make_pair(UB, UI3);
126 }
127 
128 double Action::perform(Particles *particles, uint32_t id_process) {
129  assert(id_process != 0);
130  double energy_violation = 0.;
132  // store the history info
134  p.set_history(p.get_history().collisions_per_particle + 1, id_process,
136  }
137  }
138 
139  /* For elastic collisions and box wall crossings it is not necessary to remove
140  * particles from the list and insert new ones, it is enough to update their
141  * properties. */
145 
146  logg[LAction].debug("Particle map now has ", particles->size(), " elements.");
147 
148  /* Check the conservation laws if the modifications of the total kinetic
149  * energy of the outgoing particles by the mean field potentials are not
150  * taken into account. */
151  if (UB_lat_pointer == nullptr && UI3_lat_pointer == nullptr) {
152  energy_violation = check_conservation(id_process);
153  }
154  return energy_violation;
155 }
156 
158  const auto potentials = get_potential_at_interaction_point();
159  /* scale_B returns the difference of the total force scales of the skyrme
160  * potential between the initial and final states. */
161  double scale_B = 0.0;
162  /* scale_I3 returns the difference of the total force scales of the symmetry
163  * potential between the initial and final states. */
164  double scale_I3 = 0.0;
165  for (const auto &p_in : incoming_particles_) {
166  // Get the force scale of the incoming particle.
167  const auto scale =
168  ((pot_pointer != nullptr) ? pot_pointer->force_scale(p_in.type())
169  : std::make_pair(0.0, 0));
170  scale_B += scale.first;
171  scale_I3 += scale.second * p_in.type().isospin3_rel();
172  }
173  for (const auto &p_out : outgoing_particles_) {
174  // Get the force scale of the outgoing particle.
175  const auto scale = ((pot_pointer != nullptr)
177  : std::make_pair(0.0, 0));
178  scale_B -= scale.first;
179  scale_I3 -= scale.second * type_of_pout(p_out).isospin3_rel();
180  }
181  /* Rescale to get the potential difference between the
182  * initial and final state, and thus get the total momentum
183  * of the outgoing particles*/
184  return total_momentum() + potentials.first * scale_B +
185  potentials.second * scale_I3;
186 }
187 
189  /* Find incoming particle with largest formation time i.e. the last formed
190  * incoming particle. If all particles form at the same time, take the one
191  * with the lowest cross section scaling factor */
192  ParticleList::iterator last_formed_in_part;
193  bool all_incoming_same_formation_time =
195  [&](const ParticleData &data_comp) {
196  return std::abs(incoming_particles_[0].formation_time() -
197  data_comp.formation_time()) < really_small;
198  });
199  if (all_incoming_same_formation_time) {
200  last_formed_in_part =
201  std::min_element(incoming_particles_.begin(), incoming_particles_.end(),
202  [](const ParticleData &a, const ParticleData &b) {
203  return a.initial_xsec_scaling_factor() <
204  b.initial_xsec_scaling_factor();
205  });
206  } else {
207  last_formed_in_part =
208  std::max_element(incoming_particles_.begin(), incoming_particles_.end(),
209  [](const ParticleData &a, const ParticleData &b) {
210  return a.formation_time() < b.formation_time();
211  });
212  }
213 
214  const double form_time_begin = last_formed_in_part->begin_formation_time();
215  const double sc = last_formed_in_part->initial_xsec_scaling_factor();
216 
217  if (last_formed_in_part->formation_time() > time_of_execution_) {
218  for (ParticleData &new_particle : outgoing_particles_) {
219  if (new_particle.initial_xsec_scaling_factor() < 1.0) {
220  /* The new cross section scaling factor will be the product of the
221  * cross section scaling factor of the ingoing particles and of the
222  * outgoing ones (since the outgoing ones are also string fragments
223  * and thus take time to form). */
224  double sc_out = new_particle.initial_xsec_scaling_factor();
225  new_particle.set_cross_section_scaling_factor(sc * sc_out);
226  if (last_formed_in_part->formation_time() >
227  new_particle.formation_time()) {
228  /* If the unformed incoming particles' formation time is larger than
229  * the current outgoing particle's formation time, then the latter
230  * is overwritten by the former*/
231  new_particle.set_slow_formation_times(
232  time_of_execution_, last_formed_in_part->formation_time());
233  }
234  } else {
235  // not a string product
236  new_particle.set_slow_formation_times(
237  form_time_begin, last_formed_in_part->formation_time());
238  new_particle.set_cross_section_scaling_factor(sc);
239  }
240  }
241  } else {
242  for (ParticleData &new_particle : outgoing_particles_) {
243  if (new_particle.initial_xsec_scaling_factor() == 1.0) {
244  new_particle.set_formation_time(time_of_execution_);
245  }
246  }
247  }
248 }
249 
250 std::pair<double, double> Action::sample_masses(
251  const double kinetic_energy_cm) const {
252  const ParticleType &t_a = outgoing_particles_[0].type();
253  const ParticleType &t_b = outgoing_particles_[1].type();
254  // start with pole masses
255  std::pair<double, double> masses = {t_a.mass(), t_b.mass()};
256 
257  if (kinetic_energy_cm < t_a.min_mass_kinematic() + t_b.min_mass_kinematic()) {
258  const std::string reaction = incoming_particles_[0].type().name() +
259  incoming_particles_[1].type().name() + "→" +
260  t_a.name() + t_b.name();
262  reaction + ": not enough energy, " + std::to_string(kinetic_energy_cm) +
263  " < " + std::to_string(t_a.min_mass_kinematic()) + " + " +
264  std::to_string(t_b.min_mass_kinematic()));
265  }
266 
267  /* If one of the particles is a resonance, sample its mass. */
268  if (!t_a.is_stable() && t_b.is_stable()) {
269  masses.first = t_a.sample_resonance_mass(t_b.mass(), kinetic_energy_cm);
270  } else if (!t_b.is_stable() && t_a.is_stable()) {
271  masses.second = t_b.sample_resonance_mass(t_a.mass(), kinetic_energy_cm);
272  } else if (!t_a.is_stable() && !t_b.is_stable()) {
273  // two resonances in final state
274  masses = t_a.sample_resonance_masses(t_b, kinetic_energy_cm);
275  }
276  return masses;
277 }
278 
279 void Action::sample_angles(std::pair<double, double> masses,
280  const double kinetic_energy_cm) {
283 
284  const double pcm = pCM(kinetic_energy_cm, masses.first, masses.second);
285  if (!(pcm > 0.0)) {
286  logg[LAction].warn("Particle: ", p_a->pdgcode(), " radial momentum: ", pcm);
287  logg[LAction].warn("Ektot: ", kinetic_energy_cm, " m_a: ", masses.first,
288  " m_b: ", masses.second);
289  }
290  /* Here we assume an isotropic angular distribution. */
291  Angles phitheta;
292  phitheta.distribute_isotropically();
293 
294  p_a->set_4momentum(masses.first, phitheta.threevec() * pcm);
295  p_b->set_4momentum(masses.second, -phitheta.threevec() * pcm);
296  /* Debug message is printed before boost, so that p_a and p_b are
297  * the momenta in the center of mass frame and thus opposite to
298  * each other.*/
299  logg[LAction].debug("p_a: ", *p_a, "\np_b: ", *p_b);
300 }
301 
303  /* This function only operates on 2-particle final states. */
304  assert(outgoing_particles_.size() == 2);
306  const double cm_kin_energy = p_tot.abs();
307  // first sample the masses
308  const std::pair<double, double> masses = sample_masses(cm_kin_energy);
309  // after the masses are fixed (and thus also pcm), sample the angles
310  sample_angles(masses, cm_kin_energy);
311 }
312 
314  double sqrts, const std::vector<double> &m,
315  std::vector<FourVector> &sampled_momenta) {
332  const size_t n = m.size();
333  assert(n > 1);
334  sampled_momenta.resize(n);
335 
336  // Arrange a convenient vector of m1, m1 + m2, m1 + m2 + m3, ...
337  std::vector<double> msum(n);
338  std::partial_sum(m.begin(), m.end(), msum.begin());
339  const double msum_all = msum[n - 1];
340  int rejection_counter = -1;
341  if (sqrts <= msum_all) {
342  logg[LAction].error()
343  << "An interaction requiring " << sqrts
344  << "GeV was attempted below the minimum energy threshold" << msum_all
345  << " GeV, but was ignored.\nThis is a known internal error which does "
346  "not significantly affect physical results, and will be fixed in a "
347  "near-future release.";
348  throw StochasticBelowEnergyThreshold("Ignoring this action.");
349  }
350 
351  double w, r01;
352  std::vector<double> Minv(n);
353 
354  double weight_sqr_max = 1;
355  const double Ekin_share = (sqrts - msum_all) / (n - 1);
356  for (size_t i = 1; i < n; i++) {
357  // This maximum estimate idea is due Scott Pratt: maximum should be
358  // roughly at equal kinetic energies
359  weight_sqr_max *= pCM_sqr(i * Ekin_share + msum[i],
360  (i - 1) * Ekin_share + msum[i - 1], m[i]);
361  }
362  // Maximum estimate is rough and can be wrong. We multiply it by additional
363  // factor to be on the safer side.
364  const double safety_factor = 1.1 + (n - 2) * 0.2;
365  weight_sqr_max *= (safety_factor * safety_factor);
366  bool first_warning = true;
367 
368  do {
369  // Generate invariant masses of 1, 12, 123, 1243, etc.
370  // Minv = {m1, M12, M123, ..., M123n-1, sqrts}
371  Minv[0] = 0.0;
372  Minv[n - 1] = sqrts - msum_all;
373  for (size_t i = 1; i < n - 1; i++) {
374  Minv[i] = random::uniform(0.0, sqrts - msum_all);
375  }
376  std::sort(Minv.begin(), Minv.end());
377  for (size_t i = 0; i < n; i++) {
378  Minv[i] += msum[i];
379  }
380 
381  double weight_sqr = 1;
382  for (size_t i = 1; i < n; i++) {
383  weight_sqr *= pCM_sqr(Minv[i], Minv[i - 1], m[i]);
384  }
385 
386  rejection_counter++;
387  r01 = random::canonical();
388  w = weight_sqr / weight_sqr_max;
389  if (w > 1.0) {
390  logg[LAction].warn()
391  << "sample_manybody_phasespace_impl: alarm, weight > 1, w^2 = " << w
392  << ". Increase safety factor." << std::endl;
393  }
394  if (rejection_counter > 20 && first_warning) {
395  logg[LAction].warn() << "sample_manybody_phasespace_impl: "
396  << "likely hanging, way too many rejections,"
397  << " n = " << n << ", sqrts = " << sqrts
398  << ", msum = " << msum_all;
399  first_warning = false;
400  }
401  } while (w < r01 * r01);
402 
403  // Boost particles to the right frame
404  std::vector<ThreeVector> beta(n);
405  for (size_t i = n - 1; i > 0; i--) {
406  const double pcm = pCM(Minv[i], Minv[i - 1], m[i]);
407  Angles phitheta;
408  phitheta.distribute_isotropically();
409  const ThreeVector isotropic_unitvector = phitheta.threevec();
410  sampled_momenta[i] = FourVector(std::sqrt(m[i] * m[i] + pcm * pcm),
411  pcm * isotropic_unitvector);
412  if (i >= 2) {
413  beta[i - 2] = pcm * isotropic_unitvector /
414  std::sqrt(pcm * pcm + Minv[i - 1] * Minv[i - 1]);
415  }
416  if (i == 1) {
417  sampled_momenta[0] = FourVector(std::sqrt(m[0] * m[0] + pcm * pcm),
418  -pcm * isotropic_unitvector);
419  }
420  }
421 
422  for (size_t i = 0; i < n - 2; i++) {
423  // After each boost except the last one the sum of 3-momenta should be 0
424  FourVector ptot = FourVector(0.0, 0.0, 0.0, 0.0);
425  for (size_t j = 0; j <= i + 1; j++) {
426  ptot += sampled_momenta[j];
427  }
428  logg[LAction].debug() << "Total momentum of 0.." << i + 1 << " = "
429  << ptot.threevec() << " and should be (0, 0, 0). "
430  << std::endl;
431 
432  // Boost the first i+1 particles to the next CM frame
433  for (size_t j = 0; j <= i + 1; j++) {
434  sampled_momenta[j] = sampled_momenta[j].lorentz_boost(beta[i]);
435  }
436  }
437 
438  FourVector ptot_all = FourVector(0.0, 0.0, 0.0, 0.0);
439  for (size_t j = 0; j < n; j++) {
440  ptot_all += sampled_momenta[j];
441  }
442  logg[LAction].debug() << "Total 4-momentum = " << ptot_all << ", should be ("
443  << sqrts << ", 0, 0, 0)" << std::endl;
444 }
445 
447  const size_t n = outgoing_particles_.size();
448  if (n < 3) {
449  throw std::invalid_argument(
450  "sample_manybody_phasespace: number of outgoing particles should be 3 "
451  "or more");
452  }
453  bool all_stable = true;
454  for (size_t i = 0; i < n; i++) {
455  all_stable = all_stable && outgoing_particles_[i].type().is_stable();
456  }
457  if (!all_stable) {
458  throw std::invalid_argument(
459  "sample_manybody_phasespace: Found resonance in to be sampled outgoing "
460  "particles, but assumes stable particles.");
461  }
462 
463  std::vector<double> m(n);
464  for (size_t i = 0; i < n; i++) {
465  m[i] = outgoing_particles_[i].type().mass();
466  }
467  std::vector<FourVector> p(n);
468 
470  for (size_t i = 0; i < n; i++) {
471  outgoing_particles_[i].set_4momentum(p[i]);
472  }
473 }
474 
475 double Action::check_conservation(const uint32_t id_process) const {
478  double energy_violation = 0.;
479  if (before != after) {
480  std::stringstream particle_names;
481  for (const auto &p : incoming_particles_) {
482  particle_names << p.type().name();
483  }
484  particle_names << " vs. ";
485  for (const auto &p : outgoing_particles_) {
486  particle_names << p.type().name();
487  }
488  particle_names << "\n";
489  std::string err_msg = before.report_deviations(after);
490  /* Pythia does not conserve energy and momentum at high energy, so we just
491  * print the warning and continue. */
494  logg[LAction].warn() << "Conservation law violations due to Pythia\n"
495  << particle_names.str() << err_msg;
496  energy_violation = after.momentum()[0] - before.momentum()[0];
497  return energy_violation;
498  }
499  /* We allow decay of particles stable under the strong interaction to decay
500  * at the end, so just warn about such a "weak" process violating
501  * conservation laws */
503  incoming_particles_[0].type().is_stable()) {
504  logg[LAction].warn()
505  << "Conservation law violations of strong interaction in weak or "
506  "e.m. decay\n"
507  << particle_names.str() << err_msg;
508  return energy_violation;
509  }
510  /* If particles are added or removed, it is not surprising that conservation
511  * laws are potentially violated. Do not warn the user but print some
512  * information for debug */
514  logg[LAction].debug()
515  << "Conservation law violation, but we want it (Freeforall Action).\n"
516  << particle_names.str() << err_msg;
517  return energy_violation;
518  }
519  logg[LAction].error() << "Conservation law violations detected\n"
520  << particle_names.str() << err_msg;
521  if (id_process == ID_PROCESS_PHOTON) {
522  throw std::runtime_error("Conservation laws violated in photon process");
523  } else {
524  throw std::runtime_error("Conservation laws violated in process " +
525  std::to_string(id_process));
526  }
527  }
528  return energy_violation;
529 }
530 
531 std::ostream &operator<<(std::ostream &out, const ActionList &actions) {
532  out << "ActionList {\n";
533  for (const auto &a : actions) {
534  out << "- " << a << '\n';
535  }
536  return out << '}';
537 }
538 
539 } // namespace smash
Thrown for example when ScatterAction is called to perform with a wrong number of final-state particl...
Definition: action.h:330
Exception for a temporary bugfix for when multiparticle interactions do not have the necessary energy...
Definition: action.h:340
void sample_2body_phasespace()
Sample the full 2-body phase-space (masses, momenta, angles) in the center-of-mass frame for the fina...
Definition: action.cc:302
FourVector total_momentum_of_outgoing_particles() const
Calculate the total kinetic momentum of the outgoing particles.
Definition: action.cc:157
void assign_formation_time_to_outgoing_particles()
Assign the formation time to the outgoing particles.
Definition: action.cc:188
virtual ~Action()
Virtual Destructor.
int stochastic_position_idx_
This stores a randomly-chosen index to an incoming particle.
Definition: action.h:386
std::pair< FourVector, FourVector > get_potential_at_interaction_point() const
Get the skyrme and asymmetry potential at the interaction point.
Definition: action.cc:112
virtual void sample_angles(std::pair< double, double > masses, double kinetic_energy_cm)
Sample final-state momenta in general X->2 processes (here: using an isotropical angular distribution...
Definition: action.cc:279
ParticleList outgoing_particles_
Initially this stores only the PDG codes of final-state particles.
Definition: action.h:363
const ParticleType & type_of_pout(const ParticleData &p_out) const
Get the type of a given particle.
Definition: action.h:509
FourVector total_momentum() const
Sum of 4-momenta of incoming particles.
Definition: action.h:389
virtual void sample_manybody_phasespace()
Sample the full n-body phase-space (masses, momenta, angles) in the center-of-mass frame for the fina...
Definition: action.cc:446
const double time_of_execution_
Time at which the action is supposed to be performed (absolute time in the lab frame in fm).
Definition: action.h:369
virtual double perform(Particles *particles, uint32_t id_process)
Actually perform the action, e.g.
Definition: action.cc:128
void update_incoming(const Particles &particles)
Update the incoming particles that are stored in this action to the state they have in the global par...
Definition: action.cc:62
virtual double check_conservation(const uint32_t id_process) const
Check various conservation laws.
Definition: action.cc:475
const ParticleList & incoming_particles() const
Get the list of particles that go into the action.
Definition: action.cc:58
double sqrt_s() const
Determine the total energy in the center-of-mass frame [GeV].
Definition: action.h:271
double box_length_
Box length: needed to determine coordinates of collision correctly in case of collision through the w...
Definition: action.h:379
ParticleList incoming_particles_
List with data of incoming particles.
Definition: action.h:355
FourVector get_interaction_point() const
Get the interaction point.
Definition: action.cc:68
virtual std::pair< double, double > sample_masses(double kinetic_energy_cm) const
Sample final-state masses in general X->2 processes (thus also fixing the absolute c....
Definition: action.cc:250
ProcessType process_type_
type of process
Definition: action.h:372
bool is_valid(const Particles &particles) const
Check whether the action still applies.
Definition: action.cc:29
static void sample_manybody_phasespace_impl(double sqrts, const std::vector< double > &m, std::vector< FourVector > &sampled_momenta)
Implementation of the full n-body phase-space sampling (masses, momenta, angles) in the center-of-mas...
Definition: action.cc:313
bool is_pauli_blocked(const std::vector< Particles > &ensembles, const PauliBlocker &p_bl) const
Check if the action is Pauli-blocked.
Definition: action.cc:35
Angles provides a common interface for generating directions: i.e., two angles that should be interpr...
Definition: angles.h:59
ThreeVector threevec() const
Definition: angles.h:288
void distribute_isotropically()
Populate the object with a new direction.
Definition: angles.h:199
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
Definition: fourvector.h:33
double abs() const
calculate the lorentz invariant absolute value
Definition: fourvector.h:464
ThreeVector threevec() const
Definition: fourvector.h:329
ParticleData contains the dynamic information of a certain particle.
Definition: particledata.h:58
PdgCode pdgcode() const
Get the pdgcode of the particle.
Definition: particledata.h:87
void set_4momentum(const FourVector &momentum_vector)
Set the particle's 4-momentum directly.
Definition: particledata.h:164
Particle type contains the static properties of a particle species.
Definition: particletype.h:98
double sample_resonance_mass(const double mass_stable, const double cms_energy, int L=0) const
Resonance mass sampling for 2-particle final state with one resonance (type given by 'this') and one ...
double min_mass_kinematic() const
The minimum mass of the resonance that is kinematically allowed.
const std::string & name() const
Definition: particletype.h:142
bool is_stable() const
Definition: particletype.h:246
double isospin3_rel() const
Definition: particletype.h:180
double mass() const
Definition: particletype.h:145
std::pair< double, double > sample_resonance_masses(const ParticleType &t2, const double cms_energy, int L=0) const
Resonance mass sampling for 2-particle final state with two resonances.
The Particles class abstracts the storage and manipulation of particles.
Definition: particles.h:33
size_t size() const
Definition: particles.h:87
void update(const ParticleList &old_state, ParticleList &new_state, bool do_replace)
Updates the Particles object, replacing the particles in old_state with the particles in new_state.
Definition: particles.h:200
const ParticleData & lookup(const ParticleData &old_state) const
Returns the particle that is currently stored in this object given an old copy of that particle.
Definition: particles.h:222
A class that stores parameters needed for Pauli blocking, tabulates necessary integrals and computes ...
Definition: pauliblocking.h:38
double phasespace_dens(const ThreeVector &r, const ThreeVector &p, const std::vector< Particles > &ensembles, const PdgCode pdg, const ParticleList &disregard) const
Calculate phase-space density of a particle species at the point (r,p).
static std::pair< double, int > force_scale(const ParticleType &data)
Evaluates the scaling factor of the forces acting on the particles.
Definition: potentials.cc:156
A container for storing conserved values.
FourVector momentum() const
std::string report_deviations(const std::vector< Particles > &ensembles) const
Checks if the current particle list has still the same values and reports about differences.
The ThreeVector class represents a physical three-vector with the components .
Definition: threevector.h:31
Collection of useful constants that are known at compile time.
std::ostream & operator<<(std::ostream &out, const ActionPtr &action)
Convenience: dereferences the ActionPtr to Action.
Definition: action.h:547
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
constexpr int p
Proton.
constexpr int n
Neutron.
T beta(T a, T b)
Draws a random number from a beta-distribution, where probability density of is .
Definition: random.h:329
T uniform(T min, T max)
Definition: random.h:88
T canonical()
Definition: random.h:113
Definition: action.h:24
static constexpr int LPauliBlocking
Definition: action.cc:27
T pCM(const T sqrts, const T mass_a, const T mass_b) noexcept
Definition: kinematics.h:79
T pCM_sqr(const T sqrts, const T mass_a, const T mass_b) noexcept
Definition: kinematics.h:91
constexpr std::uint32_t ID_PROCESS_PHOTON
Process ID for any photon process.
Definition: constants.h:118
static constexpr int LAction
Definition: action.h:25
@ Freeforall
See here for a short description.
@ Decay
See here for a short description.
@ Wall
See here for a short description.
@ Elastic
See here for a short description.
@ StringHard
See here for a short description.
bool all_of(Container &&c, UnaryPredicate &&p)
Convenience wrapper for std::all_of that operates on a complete container.
Definition: algorithms.h:80
Potentials * pot_pointer
Pointer to a Potential class.
RectangularLattice< FourVector > * UB_lat_pointer
Pointer to the skyrme potential on the lattice.
bool is_string_soft_process(ProcessType p)
Check if a given process type is a soft string excitation.
RectangularLattice< FourVector > * UI3_lat_pointer
Pointer to the symmmetry potential on the lattice.