Version: SMASH-3.3
listmodus.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2015-2025
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #include "smash/listmodus.h"
11 
12 #include <array>
13 #include <cmath>
14 #include <cstdio>
15 #include <cstdlib>
16 #include <filesystem>
17 #include <fstream>
18 #include <list>
19 #include <map>
20 #include <sstream>
21 #include <utility>
22 #include <vector>
23 
24 #include "smash/algorithms.h"
25 #include "smash/boxmodus.h"
26 #include "smash/configuration.h"
27 #include "smash/constants.h"
29 #include "smash/fourvector.h"
30 #include "smash/inputfunctions.h"
31 #include "smash/logging.h"
32 #include "smash/particledata.h"
33 #include "smash/propagation.h"
34 #include "smash/threevector.h"
36 
37 namespace smash {
38 static constexpr int LList = LogArea::List::id;
39 
40 static bool is_list_of_particles_invalid(const Particles &, int);
41 
43  const ExperimentParameters &param)
44  : file_id_{std::nullopt}, event_id_{0} {
45  /*
46  * Make some logic on config to understand whether to extract parent or
47  * children keys. These have all the same keys but have a different section
48  * name (like for instance 'ListBox' instead of 'List'). At the moment there
49  * is only one child and this approach is fine enough, although ugly.
50  */
51  const bool is_list =
53  const bool is_list_box =
55  if (is_list == is_list_box) {
56  throw std::logic_error(
57  "Unexpected error in ListModus constructor. Either List or ListBox "
58  "sections must be present in configuration.");
59  }
61  file_directory_key = InputKeys::modi_list_fileDirectory,
62  filename_key = InputKeys::modi_list_filename;
64  Key<std::vector<std::string>> optional_quantities_key =
66  if (is_list_box) {
67  file_prefix_key = InputKeys::modi_listBox_filePrefix;
68  file_directory_key = InputKeys::modi_listBox_fileDirectory;
69  filename_key = InputKeys::modi_listBox_filename;
70  shift_id_key = InputKeys::modi_listBox_shiftId;
71  optional_quantities_key = InputKeys::modi_listBox_optionalQuantities;
72  }
73 
74  // Set the default values for the spin interaction type
76 
77  // Impose strict requirement on possible keys present in configuration file
78  const bool file_prefix_used = modus_config.has_value(file_prefix_key);
79  const bool filename_used = modus_config.has_value(filename_key);
80  if (file_prefix_used == filename_used) {
81  throw std::invalid_argument(
82  "Either 'Filename' or 'File_Prefix' key must be used in 'Modi' section "
83  "in configuration file. Please, adjust your configuration file.");
84  }
85  if (file_prefix_used) {
86  particle_list_filename_or_prefix_ = modus_config.take(file_prefix_key);
87  file_id_ = modus_config.take(shift_id_key);
88  } else {
89  particle_list_filename_or_prefix_ = modus_config.take(filename_key);
90  }
91  particle_list_file_directory_ = modus_config.take(file_directory_key);
92  if (param.n_ensembles > 1) {
93  throw std::runtime_error("ListModus only makes sense with one ensemble");
94  }
95  optional_fields_ = modus_config.take(optional_quantities_key);
98 }
99 
100 /* console output on startup of List specific parameters */
101 std::ostream &operator<<(std::ostream &out, const ListModus &m) {
102  out << "-- List Modus\nInput directory for external particle lists:\n"
103  << m.particle_list_file_directory_ << "\n";
104  return out;
105 }
106 
108  /* (1) If particles are already at the same time - don't touch them
109  AND start at the start_time_ from the config. */
110  double earliest_formation_time = DBL_MAX;
111  double formation_time_difference = 0.0;
112  double reference_formation_time = 0.0; // avoid compiler warning
113  bool first_particle = true;
114  for (const auto &particle : particles) {
115  const double t = particle.position().x0();
116  if (t < earliest_formation_time) {
117  earliest_formation_time = t;
118  }
119  if (first_particle) {
120  reference_formation_time = t;
121  first_particle = false;
122  } else {
123  formation_time_difference += std::abs(t - reference_formation_time);
124  }
125  }
126  /* (2) If particles are NOT at the same time -> anti-stream them to
127  the earliest time (Note: not to the start_time_ set by config) */
128  bool anti_streaming_needed = (formation_time_difference > really_small);
129  start_time_ = earliest_formation_time;
130  if (anti_streaming_needed) {
132  }
133 }
134 
136  Particles &particles, PdgCode pdgcode, double t, double x, double y,
137  double z, double mass, double E, double px, double py, double pz,
138  const std::vector<std::string> &optional_quantities) {
139  try {
140  ParticleData new_particle =
142  pdgcode, mass, {t, x, y, z}, {E, px, py, pz}, LList,
144  insert_optional_quantities_to_(new_particle, optional_quantities);
145  particles.insert(new_particle);
147  logg[LList].warn() << "SMASH does not recognize pdg code " << pdgcode
148  << " loaded from file. This particle will be ignored.\n";
149  }
150 }
151 
153  ParticleData &p,
154  const std::vector<std::string> &optional_quantities) const {
155  if (optional_quantities.empty()) {
156  return;
157  } else if (optional_quantities.size() != optional_fields_.size()) {
158  using namespace std::string_literals; // NOLINT(build/namespaces)
159  throw std::out_of_range("Unexpected size mismatch in "s + __func__ +
160  " between the list of optional quantities values "
161  "passed in and the class member optional_fields_");
162  }
163  HistoryData hist = p.get_history();
164  std::ostringstream error_message{"", std::ios_base::ate};
165 
166  for (size_t i = 0; i < optional_fields_.size(); ++i) {
167  size_t len{};
168  auto field = optional_fields_[i];
169  auto quantity = optional_quantities[i];
170  if (field == "ID") {
171  // ID information is not relevant
172  continue;
173  } else if (field == "charge") {
174  const PdgCode pdgcode = p.pdgcode();
175  const int charge = std::stoi(optional_quantities[i], &len);
176  // Charge consistency check
177  if (pdgcode.charge() != charge) {
178  error_message << "Charge of pdg = " << pdgcode << " != " << charge
179  << ".\n";
180  throw std::invalid_argument("Inconsistent input (charge).");
181  }
182  } else if (field == "ncoll") {
183  const int ncoll = std::stoi(optional_quantities[i], &len);
184  if (ncoll < 0) {
185  error_message << "ncoll < 0.\n";
186  }
187  hist.collisions_per_particle = ncoll;
188  } else if (field == "form_time") {
189  p.set_formation_time(std::stod(quantity, &len));
190  } else if (field == "xsecfac") {
191  const double xsecfac = std::stod(quantity, &len);
192  if (xsecfac < 0 || xsecfac > 1) {
193  error_message << "xsecfac < 0 or xsecfac > 1.\n";
194  }
195  p.set_cross_section_scaling_factor(xsecfac);
196  } else if (field == "proc_type") {
197  const int proc_type = std::stoi(quantity, &len);
198  if (!is_valid_process_type(proc_type)) {
199  error_message << "Invalid proc_type.\n";
200  }
201  hist.process_type = static_cast<ProcessType>(proc_type);
202  } else if (field == "time_last_coll") {
203  const double t_last_coll = std::stod(quantity, &len);
204  if (t_last_coll > p.position().x0()) {
205  error_message << "time_last_coll > particle time.\n";
206  }
207  hist.time_last_collision = t_last_coll;
208  } else if (field == "pdg_mother1") {
209  if (quantity != "0") {
210  if (!ParticleType::exists(PdgCode(quantity))) {
211  error_message << "pdg_mother1 cannot be " << quantity << ".\n";
212  }
213  hist.p1 = PdgCode(quantity);
214  len = quantity.size();
215  }
216  } else if (field == "pdg_mother2") {
217  if (quantity != "0") {
218  if (!ParticleType::exists(PdgCode(quantity))) {
219  error_message << "pdg_mother2 cannot be " << quantity << ".\n";
220  }
221  hist.p2 = PdgCode(quantity);
222  len = quantity.size();
223  }
224  } else if (field == "spin0") {
225  const double s0 = std::stod(quantity, &len);
226  p.set_spin_vector_component(0, s0);
227  } else if (field == "spinx") {
228  const double s1 = std::stod(quantity, &len);
229  p.set_spin_vector_component(1, s1);
230  } else if (field == "spiny") {
231  const double s2 = std::stod(quantity, &len);
232  p.set_spin_vector_component(2, s2);
233  } else if (field == "spinz") {
234  const double s3 = std::stod(quantity, &len);
235  p.set_spin_vector_component(3, s3);
236  } else if (field == "perturbative_weight") {
237  const double weight = std::stod(quantity, &len);
238  if (0 > weight || weight > 1) {
239  error_message << "Perturbative weight must be between 0 and 1.\n";
240  }
241  p.set_perturbative_weight(weight);
242  } else {
243  error_message << " Unknown quantities given in the configuration.\n";
244  }
245  /* This is to assist the user, in case of a mistype in the inputfile.
246  * We do not throw here because it may be intentional. */
247  if (len != quantity.size()) {
248  logg[LList].warn()
249  << field << "=" << quantity
250  << " not read exactly as written in the input particle list.\n";
251  }
252  }
253 
254  if (error_message.str().size() > 0) {
255  logg[LList].error()
256  << "The reading-in of optional quantities had the following problems:"
257  << std::endl
258  << error_message.str();
259  throw std::invalid_argument(
260  "Please fix the list of input particles and/or configuration.");
261  }
262  p.set_history(std::move(hist));
263 }
264 
265 /* initial_conditions - sets particle data for @particles */
267  const ExperimentParameters &) {
269  if (particles->size() > 0) {
271  } else {
272  start_time_ = 0.0;
273  }
274  event_id_++;
275 
276  return start_time_;
277 }
278 
280  std::string particle_list = next_event_();
281  const std::vector<Line> event_content = line_parser(particle_list);
282  if (event_content.empty()) {
283  if (verbose_) {
284  logg[LList].warn(
285  "Encountered empty event while reading input particle lists data, "
286  "which will result in empty events in the output file!");
287  }
288  return;
289  }
290  for (const Line &line : event_content) {
291  std::istringstream lineinput(line.text);
292  double t, x, y, z, mass, E, px, py, pz;
293  std::string pdg_string;
294  lineinput >> t >> x >> y >> z >> mass >> E >> px >> py >> pz >> pdg_string;
295  std::vector<std::string> optional_quantities(optional_fields_.size());
296  for (size_t i = 0; i < optional_fields_.size(); ++i) {
297  std::string opt{};
298  lineinput >> opt;
299  optional_quantities[i] = std::move(opt);
300  }
301  if (lineinput.fail()) {
302  throw LoadFailure(
303  build_error_string("While loading external particle lists data:\n"
304  "Failed to convert the input string to the "
305  "expected data types.",
306  line));
307  }
308  PdgCode pdgcode(pdg_string);
309  logg[LList].debug("Particle ", pdgcode, " (x,y,z)= (", x, ", ", y, ", ", z,
310  ")");
311 
312  try_create_particle(particles, pdgcode, t, x, y, z, mass, E, px, py, pz,
313  optional_quantities);
314  }
315 }
316 
317 std::filesystem::path ListModus::file_path_(std::optional<int> file_id) {
318  std::string fname = particle_list_filename_or_prefix_ +
319  ((file_id) ? std::to_string(*file_id) : "");
320 
321  const std::filesystem::path default_path =
322  std::filesystem::absolute(particle_list_file_directory_);
323 
324  const std::filesystem::path fpath = default_path / fname;
325 
326  logg[LList].debug() << "File: " << std::filesystem::absolute(fpath) << '\n';
327 
328  if (!std::filesystem::exists(fpath)) {
329  if (verbose_) {
330  logg[LList].fatal()
331  << fpath.filename().native() << " does not exist! \n\n"
332  << "Usage of smash with external particle lists:\n"
333  << " 1. Put the external particle lists in one or more files\n"
334  << " according to the user guide instructions.\n"
335  << " 2. Particles info: t x y z mass p0 px py pz pdg ID charge\n"
336  << " in units of: fm fm fm fm GeV GeV GeV GeV GeV none none e\n";
337  }
338  throw std::runtime_error("External particle list does not exist!");
339  }
340 
341  return fpath;
342 }
343 
344 std::string ListModus::next_event_() {
345  const std::filesystem::path fpath = file_path_(file_id_);
346  std::ifstream ifs{fpath};
347  ifs.seekg(last_read_position_);
348 
349  if (!file_has_events_(fpath, last_read_position_)) {
350  if (file_id_) {
351  // Get next file and call this function recursively
352  (*file_id_)++;
354  ifs.close();
355  return next_event_();
356  } else {
357  throw std::runtime_error(
358  "Attempt to read in next event in ListModus object but no further "
359  "data found in single provided file. Please, check your setup.");
360  }
361  }
362 
363  // read one event. events marked by line # event end i in case of Oscar
364  // output. Assume one event per file for all other output formats
365  std::string event_string{};
366  const std::string needle = " end ";
367  std::string line{};
368  while (getline(ifs, line)) {
369  if (line.find(needle) == std::string::npos) {
370  event_string += line + "\n";
371  } else {
372  break;
373  }
374  }
375 
376  if (!ifs.eof() && (ifs.fail() || ifs.bad())) {
377  if (verbose_) {
378  logg[LList].fatal() << "Error while reading "
379  << fpath.filename().native();
380  }
381  throw std::runtime_error("Error while reading external particle list");
382  }
383  // save position for next event read
384  last_read_position_ = ifs.tellg();
385  ifs.close();
386 
387  return event_string;
388 }
389 
390 bool ListModus::file_has_events_(std::filesystem::path filepath,
391  std::streampos last_position) {
392  std::ifstream ifs{filepath};
393  std::string line;
394 
395  // last event read read at end of file. we know this because errors are
396  // handled in next_event
397  if (last_position == -1) {
398  return false;
399  }
400  ifs.seekg(last_position);
401  // skip over comment lines, assume that a max. of four consecutive comment
402  // lines can occur
403  int skipped_lines = 0;
404  const int max_comment_lines = 4;
405  while (std::getline(ifs, line) && line[0] != '#' &&
406  skipped_lines++ < max_comment_lines) {
407  }
408 
409  if (ifs.eof()) {
410  return false;
411  }
412 
413  if (!ifs.good()) {
414  if (verbose_) {
415  logg[LList].fatal() << "Error while reading "
416  << filepath.filename().native();
417  }
418  throw std::runtime_error("Error while reading external particle list");
419  }
420 
421  ifs.close();
422  return true;
423 }
424 
425 /* In this method, which is called from the constructor only, we "abuse" of the
426  * class functionality to read in all events and validate them. In order not to
427  * modify the original object we work on an utility copy. Note that the copy
428  * constructor provided by the compiler is enough as the class has only STL or
429  * builtin members.
430  */
432  ListModus utility_copy{*this};
433  utility_copy.verbose_ = false;
434  utility_copy.warn_about_mass_discrepancy_ = false;
435  utility_copy.warn_about_off_shell_particles_ = false;
436  bool are_there_faulty_events = false;
437  while (true) {
438  try {
439  Particles particles{};
440  utility_copy.read_particles_from_next_event_(particles);
441  if (is_list_of_particles_invalid(particles, utility_copy.event_id_)) {
442  are_there_faulty_events = true;
443  }
444  utility_copy.event_id_++;
445  } catch (const std::exception &) {
446  break;
447  }
448  }
449  if (are_there_faulty_events) {
450  throw InvalidEvents(
451  "More than 2 particles with the same 4-position have been found in the "
452  "same event.\nPlease, check your particles list file.");
453  }
454 }
455 
457  // If spin interactions are enabled, require all four spin components.
459  std::array<bool, 4> has_spin{{false, false, false, false}};
460  for (const auto &field : optional_fields_) {
461  if (field == "spin0") {
462  has_spin[0] = true;
463  } else if (field == "spinx") {
464  has_spin[1] = true;
465  } else if (field == "spiny") {
466  has_spin[2] = true;
467  } else if (field == "spinz") {
468  has_spin[3] = true;
469  }
470  }
471  for (int c = 0; c < 4; ++c) {
472  if (!has_spin[c]) {
473  throw std::invalid_argument(
474  "When spin interactions are enabled, all four spin components "
475  "(spin0, spinx, spiny, spinz) must be provided in the config "
476  "file.");
477  }
478  }
479  }
480 }
481 
483  const ExperimentParameters &param)
484  : ListModus(), length_(modus_config.take(InputKeys::modi_listBox_length)) {
485  /*
486  * ATTENTION: In a child class initialization list nothing can be done before
487  * calling the base constructor. However, here we cannot hand over the
488  * configuration to the base class as there are child-specific keys to be
489  * taken before. This cannot be done after having moved the configuration and
490  * changing the constructor signature would be a big change as all modus
491  * classes should have the same constructor signature to allow Experiment to
492  * template on it. Therefore, we abuse C++ here by default-initializing the
493  * parent class, then taking the child-specific key(s) and then assigning a
494  * parent instance to the child using the parent assignment operator. In
495  * general this would be risky as it would open up the possibility to leave
496  * part of the children uninitialized, but here we should have under control
497  * what exactly happens at initialization time.
498  */
499  this->ListModus::operator=(ListModus(std::move(modus_config), param));
500 }
501 
503  const OutputsList &output_list) {
504  int wraps = 0;
505  for (ParticleData &data : *particles) {
506  FourVector position = data.position();
507  bool wall_hit = enforce_periodic_boundaries(position.begin() + 1,
508  position.end(), length_);
509  if (wall_hit) {
510  const ParticleData incoming_particle(data);
511  data.set_4position(position);
512  ++wraps;
513  ActionPtr action =
514  std::make_unique<WallcrossingAction>(incoming_particle, data);
515  for (const auto &output : output_list) {
516  if (!output->is_dilepton_output() && !output->is_photon_output()) {
517  output->at_interaction(*action, 0.);
518  }
519  }
520  }
521  }
522 
523  logg[LList].debug("Moved ", wraps, " particles back into the box.");
524  return wraps;
525 }
526 
527 /* This function is meant to throw if there are more than two particles at the
528  * same position. To be more user-friendly we first check all particles and then
529  * report about all faulty groups of particles with their position. Only
530  * afterwards the simulation is aborted. */
531 static bool is_list_of_particles_invalid(const Particles &particles,
532  int event) {
533  /* In order to make the desired check, particles are classified in an std::map
534  * using their position as a key. However, to do so, the operator< of the
535  * FourVector class is not suitable since in a std::map, by default, two keys
536  * a and b are considered equivalent if !(a<b) && !(b<a). Therefore we convert
537  * the 4-postion to a string and use this as key. Note that this should also
538  * work in the case in which the file contains apparently different positions,
539  * i.e. with differences in the decimals beyond double precision. At this
540  * point the file has been already read and the 4-positions are stored in
541  * double position. */
542  auto to_string = [](const FourVector &v) {
543  return "(" + std::to_string(v[0]) + ", " + std::to_string(v[1]) + ", " +
544  std::to_string(v[2]) + ", " + std::to_string(v[3]) + ")";
545  };
546  std::map<std::string, int> checker{};
547  for (const auto &p : particles) {
548  checker[to_string(p.position())]++;
549  }
550  bool error_found = false;
551  for (const auto &[key, value] : checker) {
552  if (value > 2) {
553  logg[LList].error() << "Event " << event << ": Found " << value
554  << " particles at same position " << key;
555  error_found = true;
556  }
557  }
558  return error_found;
559 }
560 } // namespace smash
Generic algorithms on containers and ranges.
Interface to the SMASH configuration files.
bool has_value(const Key< T > &key) const
Return whether there is a non-empty value behind the requested key (which is supposed not to refer to...
T take(const Key< T > &key)
The default interface for SMASH to read configuration values.
The FourVector class holds relevant values in Minkowski spacetime with (+, −, −, −) metric signature.
Definition: fourvector.h:33
iterator end()
Definition: fourvector.h:294
iterator begin()
Definition: fourvector.h:291
const double length_
Length of the cube's edge in fm.
Definition: listmodus.h:374
int impose_boundary_conditions(Particles *particles, const OutputsList &output_list={})
Enforces that all particles are inside the box at the beginning of an event.
Definition: listmodus.cc:502
ListBoxModus(Configuration modus_config, const ExperimentParameters &parameters)
Constructor (This is the same as for the ListModus)
Definition: listmodus.cc:482
ListModus: Provides a modus for running SMASH on an external particle list, for example as an afterbu...
Definition: listmodus.h:57
bool file_has_events_(std::filesystem::path filepath, std::streampos last_position)
Check if the given file has events left after the given position.
Definition: listmodus.cc:390
std::optional< int > file_id_
The id of the current file.
Definition: listmodus.h:259
bool is_list() const
Definition: listmodus.h:148
std::string particle_list_filename_or_prefix_
Prefix of the file(s) containing the particle list.
Definition: listmodus.h:256
void backpropagate_to_same_time_if_needed_(Particles &particles)
Judge whether times are the same for all the particles; don't do anti-freestreaming if all particles ...
Definition: listmodus.cc:107
void validate_optional_fields_() const
Validate the optional fields.
Definition: listmodus.cc:456
std::filesystem::path file_path_(std::optional< int > file_id)
Return the absolute path of the data file.
Definition: listmodus.cc:317
SpinInteractionType spin_interaction_type_
Auxiliary flag to indicate the type of spin interaction used.
Definition: listmodus.h:275
std::string particle_list_file_directory_
File directory of the particle list.
Definition: listmodus.h:250
void validate_list_of_particles_of_all_events_() const
Read and validate all events particles.
Definition: listmodus.cc:431
void read_particles_from_next_event_(Particles &particles)
Read the next event from file.
Definition: listmodus.cc:279
double start_time_
Starting time for the List; changed to the earliest formation time.
Definition: listmodus.h:152
ListModus()=default
Construct an empty list.
bool verbose_
Flag to suppress some error messages.
Definition: listmodus.h:283
void try_create_particle(Particles &particles, PdgCode pdgcode, double t, double x, double y, double z, double mass, double E, double px, double py, double pz, const std::vector< std::string > &optional_quantities={})
Tries to add a new particle to particles and performs consistency checks: (i) The PDG code is legal a...
Definition: listmodus.cc:135
std::streampos last_read_position_
Last read position in current file.
Definition: listmodus.h:267
bool warn_about_mass_discrepancy_
Auxiliary flag to warn about mass-discrepancies only once per instance.
Definition: listmodus.h:270
bool warn_about_off_shell_particles_
Auxiliary flag to warn about off-shell particles only once per instance.
Definition: listmodus.h:272
std::string next_event_()
Read the next event.
Definition: listmodus.cc:344
std::vector< std::string > optional_fields_
Fields with optional quantities to be read.
Definition: listmodus.h:262
void insert_optional_quantities_to_(ParticleData &p, const std::vector< std::string > &optional_quantities) const
Sets the optional fields given in the input list into a particle.
Definition: listmodus.cc:152
double initial_conditions(Particles *particles, const ExperimentParameters &parameters)
Generates initial state of the particles in the system according to a list.
Definition: listmodus.cc:266
int event_id_
The unique id of the current event.
Definition: listmodus.h:264
ParticleData contains the dynamic information of a certain particle.
Definition: particledata.h:59
static bool exists(PdgCode pdgcode)
The Particles class abstracts the storage and manipulation of particles.
Definition: particles.h:33
size_t size() const
Definition: particles.h:87
const ParticleData & insert(const ParticleData &p)
Inserts the particle into the list of particles.
Definition: particles.cc:50
PdgCode stores a Particle Data Group Particle Numbering Scheme particle type number.
Definition: pdgcode.h:108
int charge() const
The charge of the particle.
Definition: pdgcode.h:635
Collection of useful constants that are known at compile time.
@ Off
No spin interactions.
std::ostream & operator<<(std::ostream &out, const ActionPtr &action)
Convenience: dereferences the ActionPtr to Action.
Definition: action.h:555
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:40
std::basic_ostream< CharT, Traits > & field(std::basic_ostream< CharT, Traits > &s)
Stream modifier to align the next object to a specific width w.
constexpr int p
Proton.
Definition: action.h:24
bool is_valid_process_type(int v)
Definition: processbranch.h:92
ProcessType
ProcessTypes are used to identify the type of the process.
Definition: processbranch.h:39
static bool enforce_periodic_boundaries(Iterator begin, const Iterator &end, typename std::iterator_traits< Iterator >::value_type length)
Enforces periodic boundaries on the given collection of values.
Definition: algorithms.h:53
build_vector_< Line > line_parser(const std::string &input)
Helper function for parsing particles.txt and decaymodes.txt.
std::string to_string(ThermodynamicQuantity quantity)
Convert a ThermodynamicQuantity enum value to its corresponding string.
Definition: stringify.cc:26
static constexpr int LList
Definition: listmodus.cc:38
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:41
void backpropagate_straight_line(Particles *particles, double to_time)
Definition: propagation.cc:86
std::string build_error_string(std::string message, const Line &line)
Builds a meaningful error message.
static bool is_list_of_particles_invalid(const Particles &, int)
Definition: listmodus.cc:531
Helper structure for Experiment.
int n_ensembles
Number of parallel ensembles.
SpinInteractionType spin_interaction_type
Whether to include spin interactions.
A structure to hold information about the history of the particle, e.g.
Definition: particledata.h:31
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:44
PdgCode p2
PdgCode of the second parent particles.
Definition: particledata.h:48
PdgCode p1
PdgCode of the first parent particles.
Definition: particledata.h:46
int32_t collisions_per_particle
Collision counter per particle, zero only for initially present particles.
Definition: particledata.h:33
ProcessType process_type
type of the last action
Definition: particledata.h:37
A container to keep track of all ever existed input keys.
Definition: input_keys.h:1116
static const Key< std::vector< std::string > > modi_listBox_optionalQuantities
See user guide description for more information.
Definition: input_keys.h:4878
static const Key< std::string > modi_list_fileDirectory
See user guide description for more information.
Definition: input_keys.h:4687
static const Key< std::string > modi_listBox_filePrefix
See user guide description for more information.
Definition: input_keys.h:4837
static const Key< std::vector< std::string > > modi_list_optionalQuantities
See user guide description for more information.
Definition: input_keys.h:4796
static const Key< std::string > modi_list_filename
See user guide description for more information.
Definition: input_keys.h:4702
static const Key< int > modi_listBox_shiftId
See user guide description for more information.
Definition: input_keys.h:4863
static const Key< int > modi_list_shiftId
See user guide description for more information.
Definition: input_keys.h:4732
static const Key< std::string > modi_list_filePrefix
See user guide description for more information.
Definition: input_keys.h:4715
static const Key< std::string > modi_listBox_filename
See user guide description for more information.
Definition: input_keys.h:4824
static const Key< std::string > modi_listBox_fileDirectory
See user guide description for more information.
Definition: input_keys.h:4811
Line consists of a line number and the contents of that line.
Used when external particle list is invalid.
Definition: listmodus.h:143
Used when external particle list cannot be found.
Definition: listmodus.h:136