Version: SMASH-3.1
particledata.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2023
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #include "smash/particledata.h"
11 
12 #include <iomanip>
13 #include <iostream>
14 #include <optional>
15 #include <vector>
16 
17 #include "smash/constants.h"
18 #include "smash/iomanipulators.h"
19 #include "smash/logging.h"
20 #include "smash/numerics.h"
21 
22 namespace smash {
23 
25  const double m_pole = pole_mass();
26  if (m_pole < really_small) {
27  // prevent numerical problems with massless or very light particles
28  return m_pole;
29  } else {
30  return momentum().abs();
31  }
32 }
33 
34 void ParticleData::set_history(int ncoll, uint32_t pid, ProcessType pt,
35  double time_last_coll,
36  const ParticleList &plist) {
37  if (pt != ProcessType::Wall) {
39  history_.time_last_collision = time_last_coll;
40  }
41  history_.id_process = pid;
43  switch (pt) {
44  case ProcessType::Decay:
45  case ProcessType::Wall:
46  // only store one parent
47  history_.p1 = plist[0].pdgcode();
48  history_.p2 = 0x0;
49  break;
53  // Parent particles are not updated by the elastic scatterings,
54  // hypersurface crossings or failed string processes
55  break;
68  // store two parent particles
69  history_.p1 = plist[0].pdgcode();
70  history_.p2 = plist[1].pdgcode();
71  break;
78  case ProcessType::None:
79  // nullify parents
80  history_.p1 = 0x0;
81  history_.p2 = 0x0;
82  break;
83  }
84 }
85 
86 double ParticleData::xsec_scaling_factor(double delta_time) const {
87  double time_of_interest = position_.x0() + delta_time;
88  // cross section scaling factor at the time_of_interest
89  double scaling_factor;
90 
91  if (formation_power_ <= 0.) {
92  // use a step function to form particles
93  if (time_of_interest < formation_time_) {
94  // particles will not be fully formed at time of interest
95  scaling_factor = initial_xsec_scaling_factor_;
96  } else {
97  // particles are fully formed at time of interest
98  scaling_factor = 1.;
99  }
100  } else {
101  // use smooth function to scale cross section (unless particles are already
102  // fully formed at desired time or will start to form later)
103  if (formation_time_ <= time_of_interest) {
104  // particles are fully formed when colliding
105  scaling_factor = 1.;
106  } else if (begin_formation_time_ >= time_of_interest) {
107  // particles will start formimg later
108  scaling_factor = initial_xsec_scaling_factor_;
109  } else {
110  // particles are in the process of formation at the given time
111  scaling_factor =
114  std::pow((time_of_interest - begin_formation_time_) /
117  }
118  }
119  return scaling_factor;
120 }
121 
122 std::ostream &operator<<(std::ostream &out, const ParticleData &p) {
123  out.fill(' ');
124  return out << p.type().name() << " (" << std::setw(5) << p.type().pdgcode()
125  << ")" << std::right << "{id:" << field<6> << p.id()
126  << ", process:" << field<4> << p.id_process()
127  << ", pos [fm]:" << p.position() << ", mom [GeV]:" << p.momentum()
128  << ", formation time [fm]:" << p.formation_time()
129  << ", cross section scaling factor:" << p.xsec_scaling_factor()
130  << "}";
131 }
132 
133 std::ostream &operator<<(std::ostream &out, const ParticleList &particle_list) {
134  auto column = out.tellp();
135  out << '[';
136  for (const auto &p : particle_list) {
137  if (out.tellp() - column >= 201) {
138  out << '\n';
139  column = out.tellp();
140  out << ' ';
141  }
142  out << std::setw(5) << std::setprecision(3) << p.momentum().abs3()
143  << p.type().name();
144  }
145  return out << ']';
146 }
147 
148 std::ostream &operator<<(std::ostream &out,
149  const PrintParticleListDetailed &particle_list) {
150  bool first = true;
151  out << '[';
152  for (const auto &p : particle_list.list) {
153  if (first) {
154  first = false;
155  } else {
156  out << "\n ";
157  }
158  out << p;
159  }
160  return out << ']';
161 }
162 
163 double ParticleData::formation_power_ = 0.0;
164 
166  PdgCode pdgcode, double mass, const FourVector &four_position,
167  const FourVector &four_momentum, int log_area, bool &mass_warning,
168  bool &on_shell_warning) {
169  // Check input position and momentum for nan values
170  if (is_any_nan(four_position) || is_any_nan(four_momentum)) {
171  logg[log_area].fatal() << "Input particle has at least one nan value in "
172  "position and/or momentum four vector.";
173  throw std::invalid_argument(
174  "Invalid input (nan) for particle position or momentum.");
175  }
176 
177  // Some preliminary tool to avoid duplication later
178  static const auto emph = einhard::Yellow_t_::ANSI();
179  static const auto restore_default = einhard::NoColor_t_::ANSI();
180  auto prepare_needed_warnings = [&mass_warning, &on_shell_warning, &mass,
181  &four_momentum](const ParticleData &p) {
182  std::array<std::optional<std::string>, 2> warnings{};
183  if (mass_warning) {
184  warnings[0] = "Provided mass of stable particle " + p.type().name() +
185  " = " + std::to_string(mass) +
186  " [GeV] is inconsistent with value = " +
187  std::to_string(p.pole_mass()) + " [GeV] from " +
188  "particles file.\nForcing E = sqrt(p^2 + m^2)" +
189  ", where m is the mass contained in the particles file." +
190  "\nFurther warnings about discrepancies between the " +
191  "input mass and the mass contained in the particles file" +
192  " will be suppressed.\n" + emph + "Please make sure" +
193  " that changing input particle properties is an " +
194  "acceptable behavior." + restore_default;
195  }
196  if (on_shell_warning) {
197  std::stringstream ss{};
198  ss << four_momentum;
199  warnings[1] =
200  "Provided 4-momentum " + ss.str() + " [GeV] and mass " +
201  std::to_string(mass) + " [GeV] do not satisfy E^2 - p^2 = m^2.\n" +
202  "This may originate from the lack of numerical" +
203  " precision in the input. Setting E to sqrt(p^2 + " +
204  "m^2).\nFurther warnings about E != sqrt(p^2 + m^2) will" +
205  " be suppressed.\n" + emph + "Please make sure that setting " +
206  "particles back on the mass shell is an acceptable behavior." +
207  restore_default;
208  }
209  return warnings;
210  };
211  auto warn_if_needed = [&log_area](bool &flag,
212  const std::optional<std::string> &message) {
213  if (flag) {
214  logg[log_area].warn(message.value());
215  flag = false;
216  }
217  };
218  auto is_particle_stable_and_with_invalid_mass =
219  [&mass](const ParticleData &p) {
220  return p.type().is_stable() &&
221  std::abs(mass - p.pole_mass()) > really_small;
222  };
223  auto is_particle_off_its_mass_shell = [&mass](const ParticleData &p) {
224  return std::abs(p.momentum().sqr() - mass * mass) > really_small;
225  };
226 
227  // Actual implementation
228  ParticleData smash_particle{ParticleType::find(pdgcode)};
229  const auto warnings = prepare_needed_warnings(smash_particle);
230  if (is_particle_stable_and_with_invalid_mass(smash_particle)) {
231  warn_if_needed(mass_warning, warnings[0]);
232  smash_particle.set_4momentum(smash_particle.pole_mass(),
233  four_momentum.threevec());
234  } else {
235  smash_particle.set_4momentum(four_momentum);
236  if (is_particle_off_its_mass_shell(smash_particle)) {
237  warn_if_needed(on_shell_warning, warnings[1]);
238  smash_particle.set_4momentum(mass, four_momentum.threevec());
239  }
240  }
241 
242  // Set spatial coordinates, they will later be backpropagated if needed
243  smash_particle.set_4position(four_position);
244  smash_particle.set_formation_time(four_position.x0());
245  smash_particle.set_cross_section_scaling_factor(1.0);
246 
247  return smash_particle;
248 }
249 
251  const ParticleData &p2,
252  double time) {
253  if (p1.pdgcode() != p2.pdgcode()) {
254  return false;
255  } else {
256  if (p1.momentum() != p2.momentum()) {
257  return false;
258  }
259  auto get_propagated_position = [&time](const ParticleData &p) {
260  const double t = p.position().x0();
261  const FourVector u(1.0, p.velocity());
262  return p.position() + u * (time - t);
263  };
264  return get_propagated_position(p1) == get_propagated_position(p2);
265  }
266 }
267 
268 } // namespace smash
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
double x0() const
Definition: fourvector.h:313
ParticleData contains the dynamic information of a certain particle.
Definition: particledata.h:58
double formation_time_
Formation time at which the particle is fully formed given as an absolute value in the computational ...
Definition: particledata.h:459
PdgCode pdgcode() const
Get the pdgcode of the particle.
Definition: particledata.h:87
double begin_formation_time_
time when the cross section scaling factor starts to increase to 1
Definition: particledata.h:461
double xsec_scaling_factor(double delta_time=0.) const
Return the cross section scaling factor at a given time.
Definition: particledata.cc:86
void set_history(int ncoll, uint32_t pid, ProcessType pt, double time_of_or, const ParticleList &plist)
Store history information.
Definition: particledata.cc:34
static double formation_power_
Power with which the cross section scaling factor grows in time.
Definition: particledata.h:389
const FourVector & momentum() const
Get the particle's 4-momentum.
Definition: particledata.h:158
double initial_xsec_scaling_factor_
Initial cross section scaling factor.
Definition: particledata.h:466
double effective_mass() const
Get the particle's effective mass.
Definition: particledata.cc:24
FourVector position_
position in space: x0, x1, x2, x3 as t, x, y, z
Definition: particledata.h:455
double pole_mass() const
Get the particle's pole mass ("on-shell").
Definition: particledata.h:115
HistoryData history_
history information
Definition: particledata.h:468
static const ParticleType & find(PdgCode pdgcode)
Returns the ParticleType object for the given pdgcode.
Definition: particletype.cc:99
PdgCode stores a Particle Data Group Particle Numbering Scheme particle type number.
Definition: pdgcode.h:111
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.
Definition: action.h:24
ProcessType
ProcessTypes are used to identify the type of the process.
Definition: processbranch.h:39
@ FailedString
See here for a short description.
@ TwoToOne
See here for a short description.
@ MultiParticleThreeToTwo
See here for a short description.
@ StringSoftDoubleDiffractive
See here for a short description.
@ Bremsstrahlung
See here for a short description.
@ Thermalization
See here for a short description.
@ Freeforall
See here for a short description.
@ Decay
See here for a short description.
@ TwoToFive
See here for a short description.
@ None
See here for a short description.
@ StringSoftSingleDiffractiveXB
See here for a short description.
@ TwoToTwo
See here for a short description.
@ Wall
See here for a short description.
@ Elastic
See here for a short description.
@ TwoToFour
See here for a short description.
@ StringSoftAnnihilation
See here for a short description.
@ MultiParticleThreeMesonsToOne
See here for a short description.
@ StringSoftNonDiffractive
See here for a short description.
@ MultiParticleFourToTwo
See here for a short description.
@ StringSoftSingleDiffractiveAX
See here for a short description.
@ StringHard
See here for a short description.
@ HyperSurfaceCrossing
See here for a short description.
@ TwoToThree
See here for a short description.
@ MultiParticleFiveToTwo
See here for a short description.
bool are_particles_identical_at_given_time(const ParticleData &p1, const ParticleData &p2, double time)
Utility function to compare two ParticleData instances with respect to their PDG code,...
bool is_any_nan(const T &collection)
This function iterates through the elements of a collection and checks if any of them is NaN using th...
Definition: numerics.h:82
ParticleData create_valid_smash_particle_matching_provided_quantities(PdgCode pdgcode, double mass, const FourVector &four_position, const FourVector &four_momentum, int log_area, bool &mass_warning, bool &on_shell_warning)
This function creates a SMASH particle validating the provided information.
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37
Generic numerical functions.
double time_last_collision
Time of the last action (excluding walls), time of kinetic freeze_out for HBT analysis this time shou...
Definition: particledata.h:43
int32_t id_process
id of the last action
Definition: particledata.h:34
PdgCode p2
PdgCode of the second parent particles.
Definition: particledata.h:47
PdgCode p1
PdgCode of the first parent particles.
Definition: particledata.h:45
int32_t collisions_per_particle
Collision counter per particle, zero only for initially present particles.
Definition: particledata.h:32
ProcessType process_type
type of the last action
Definition: particledata.h:36
const ParticleList & list
Particle list.
Definition: particledata.h:493