Version: SMASH-3.1
smash::ListModus Class Reference

#include <listmodus.h>

ListModus: Provides a modus for running SMASH on an external particle list, for example as an afterburner calculation.

To use this modus, choose Modus: List

General:
Modus: List

in the configuration file.

Options for ListModus go in the "Modi"→"List" section of the configuration:

Modi:
List:
# options here

For configuring see List.

Since SMASH is searching for collisions in computational frame time 't', all particles need to be at the same time. If this is not the case in the list provided, the particles will be propagated backwards on straight lines ("anti-freestreaming"). To avoid unphysical interactions of these particles, the back-propagated particles receive a formation_time and zero cross_section_scaling_factor. The cross-sections are set to zero during the time, where the particle will just propagate on a straight line again to appear at the formation_time into the system.

Definition at line 56 of file listmodus.h.

Inheritance diagram for smash::ListModus:
smash::ModusDefault smash::ListBoxModus

Classes

struct  LoadFailure
 Used when external particle list cannot be found. More...
 

Public Member Functions

 ListModus (Configuration modus_config, const ExperimentParameters &parameters)
 Constructor. More...
 
 ListModus ()=default
 Construct an empty list. More...
 
double initial_conditions (Particles *particles, const ExperimentParameters &parameters)
 Generates initial state of the particles in the system according to a list. More...
 
void backpropagate_to_same_time (Particles &particles)
 Judge whether formation times are the same for all the particles; Don't do anti-freestreaming if all particles start already at the same time. More...
 
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)
 Tries to add a new particle to particles and performs consistency checks: (i) The PDG code is legal and exists in SMASH. More...
 
bool is_list () const
 
- Public Member Functions inherited from smash::ModusDefault
int impose_boundary_conditions (Particles *, const OutputsList &={})
 Enforces sensible positions for the particles. More...
 
bool is_collider () const
 
bool is_box () const
 
bool is_list () const
 
bool is_sphere () const
 
double sqrt_s_NN () const
 
double impact_parameter () const
 
void sample_impact () const
 sample impact parameter for collider modus More...
 
double velocity_projectile () const
 
double velocity_target () const
 
FermiMotion fermi_motion () const
 
double max_timestep (double) const
 
double equilibration_time () const
 
double length () const
 
double radius () const
 
bool calculation_frame_is_fixed_target () const
 
double nuclei_passing_time () const
 Get the passing time of the two nuclei in a collision. More...
 
Grid< GridOptions::Normalcreate_grid (const Particles &particles, double min_cell_length, double timestep_duration, CollisionCriterion crit, const bool include_unformed_particles, CellSizeStrategy strategy=CellSizeStrategy::Optimal) const
 Creates the Grid with normal boundary conditions. More...
 
std::unique_ptr< GrandCanThermalizercreate_grandcan_thermalizer (Configuration &conf) const
 Creates GrandCanThermalizer. More...
 

Protected Attributes

double start_time_ = 0.
 Starting time for the List; changed to the earliest formation time. More...
 

Private Member Functions

bool file_has_events_ (std::filesystem::path filepath, std::streampos last_position)
 Check if the file given by filepath has events left after streampos last_position. More...
 
std::filesystem::path file_path_ (std::optional< int > file_id)
 Return the absolute path of the data file. More...
 
std::string next_event_ ()
 Read the next event. More...
 

Private Attributes

std::string particle_list_file_directory_
 File directory of the particle list. More...
 
std::string particle_list_filename_or_prefix_
 Prefix of the file(s) containing the particle list. More...
 
std::optional< int > file_id_
 The id of the current file. More...
 
int event_id_
 The unique id of the current event. More...
 
std::streampos last_read_position_ = 0
 Last read position in current file. More...
 
bool warn_about_mass_discrepancy_ = true
 Auxiliary flag to warn about mass-discrepancies only once per instance. More...
 
bool warn_about_off_shell_particles_ = true
 Auxiliary flag to warn about off-shell particles only once per instance. More...
 

Friends

std::ostream & operator<< (std::ostream &, const ListModus &)
 Writes the initial state for the List to the output stream. More...
 

Constructor & Destructor Documentation

◆ ListModus() [1/2]

smash::ListModus::ListModus ( Configuration  modus_config,
const ExperimentParameters parameters 
)
explicit

Constructor.

Gathers all configuration variables for the List.

Parameters
[in]modus_configThe configuration object that sets all initial conditions of the experiment.
[in]parametersNecessary because of templated usage in Experiment.

Definition at line 38 of file listmodus.cc.

40  : file_id_{std::nullopt}, event_id_{0} {
41  /*
42  * Extract the only expected section of the configuration to make this
43  * constructor work also for children classes. These do the same but have a
44  * different section name (like for instance 'ListBox' instead of 'List')
45  */
46  const auto config_sections = modus_config.list_upmost_nodes();
47  assert(config_sections.size() == 1);
48  auto plain_config =
49  modus_config.extract_sub_configuration({config_sections[0].c_str()});
50  // Impose strict requirement on possible keys present in configuration file
51  bool file_prefix_used = plain_config.has_value({"File_Prefix"});
52  bool filename_used = plain_config.has_value({"Filename"});
53  if (file_prefix_used == filename_used) {
54  throw std::invalid_argument(
55  "Either 'Filename' or 'File_Prefix' key must be used in 'List' section "
56  "in configuration file. Please, adjust your configuration file.");
57  }
58  std::string key_to_take = "Filename";
59  if (file_prefix_used) {
60  key_to_take = "File_Prefix";
61  file_id_ = plain_config.take({"Shift_Id"}, 0);
62  }
64  plain_config.take({key_to_take.c_str()})
67  plain_config.take({"File_Directory"})
68  .convert_for(particle_list_file_directory_);
69  if (param.n_ensembles > 1) {
70  throw std::runtime_error("ListModus only makes sense with one ensemble");
71  }
72 }
std::optional< int > file_id_
The id of the current file.
Definition: listmodus.h:202
std::string particle_list_filename_or_prefix_
Prefix of the file(s) containing the particle list.
Definition: listmodus.h:199
std::string particle_list_file_directory_
File directory of the particle list.
Definition: listmodus.h:193
int event_id_
The unique id of the current event.
Definition: listmodus.h:205

◆ ListModus() [2/2]

smash::ListModus::ListModus ( )
default

Construct an empty list.

This is needed for children construction but it is offered as public instead of protected as it is also useful for JetScape.

Member Function Documentation

◆ initial_conditions()

double smash::ListModus::initial_conditions ( Particles particles,
const ExperimentParameters parameters 
)

Generates initial state of the particles in the system according to a list.

Parameters
[out]particlesAn empty list that gets filled up by this function
[in]parametersUnused, but necessary because of templated use of this function
Returns
The starting time of the simulation
Exceptions
runtime_errorif an input list file could not be found
LoadFailureif an input list file is not correctly formatted
invalid_argumentif the listed charge of a particle does not correspond to its pdg charge

Definition at line 135 of file listmodus.cc.

136  {
137  std::string particle_list = next_event_();
138  for (const Line &line : line_parser(particle_list)) {
139  std::istringstream lineinput(line.text);
140  double t, x, y, z, mass, E, px, py, pz;
141  int id, charge;
142  std::string pdg_string;
143  lineinput >> t >> x >> y >> z >> mass >> E >> px >> py >> pz >>
144  pdg_string >> id >> charge;
145  if (lineinput.fail()) {
146  throw LoadFailure(
147  build_error_string("While loading external particle lists data:\n"
148  "Failed to convert the input string to the "
149  "expected data types.",
150  line));
151  }
152  PdgCode pdgcode(pdg_string);
153  logg[LList].debug("Particle ", pdgcode, " (x,y,z)= (", x, ", ", y, ", ", z,
154  ")");
155 
156  // Charge consistency check
157  if (pdgcode.charge() != charge) {
158  logg[LList].error() << "Charge of pdg = " << pdgcode << " != " << charge;
159  throw std::invalid_argument("Inconsistent input (charge).");
160  }
161  try_create_particle(*particles, pdgcode, t, x, y, z, mass, E, px, py, pz);
162  }
163  if (particles->size() > 0) {
164  backpropagate_to_same_time(*particles);
165  } else {
166  start_time_ = 0.0;
167  }
168  event_id_++;
169 
170  return start_time_;
171 }
void backpropagate_to_same_time(Particles &particles)
Judge whether formation times are the same for all the particles; Don't do anti-freestreaming if all ...
Definition: listmodus.cc:81
double start_time_
Starting time for the List; changed to the earliest formation time.
Definition: listmodus.h:152
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)
Tries to add a new particle to particles and performs consistency checks: (i) The PDG code is legal a...
Definition: listmodus.cc:118
std::string next_event_()
Read the next event.
Definition: listmodus.cc:198
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
build_vector_< Line > line_parser(const std::string &input)
Helper function for parsing particles.txt and decaymodes.txt.
static constexpr int LList
Definition: listmodus.cc:36
std::string build_error_string(std::string message, const Line &line)
Builds a meaningful error message.

◆ backpropagate_to_same_time()

void smash::ListModus::backpropagate_to_same_time ( Particles particles)

Judge whether formation times are the same for all the particles; Don't do anti-freestreaming if all particles start already at the same time.

If particles are at different times, calculate earliest formation time as start_time_ and free-stream all particles back to this time.

Parameters
particlesparticles to be checked and possibly back-streamed

Definition at line 81 of file listmodus.cc.

81  {
82  /* (1) If particles are already at the same time - don't touch them
83  AND start at the start_time_ from the config. */
84  double earliest_formation_time = DBL_MAX;
85  double formation_time_difference = 0.0;
86  double reference_formation_time = 0.0; // avoid compiler warning
87  bool first_particle = true;
88  for (const auto &particle : particles) {
89  const double t = particle.position().x0();
90  if (t < earliest_formation_time) {
91  earliest_formation_time = t;
92  }
93  if (first_particle) {
94  reference_formation_time = t;
95  first_particle = false;
96  } else {
97  formation_time_difference += std::abs(t - reference_formation_time);
98  }
99  }
100  /* (2) If particles are NOT at the same time -> anti-stream them to
101  the earliest time (Note: not to the start_time_ set by config) */
102  bool anti_streaming_needed = (formation_time_difference > really_small);
103  start_time_ = earliest_formation_time;
104  if (anti_streaming_needed) {
105  for (auto &particle : particles) {
106  /* for hydro output where formation time is different */
107  const double t = particle.position().x0();
108  const double delta_t = t - start_time_;
109  const ThreeVector r =
110  particle.position().threevec() - delta_t * particle.velocity();
111  particle.set_4position(FourVector(start_time_, r));
112  particle.set_formation_time(t);
113  particle.set_cross_section_scaling_factor(0.0);
114  }
115  }
116 }
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37

◆ try_create_particle()

void smash::ListModus::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 
)

Tries to add a new particle to particles and performs consistency checks: (i) The PDG code is legal and exists in SMASH.

If not, a warning is printed and the particle is ignored. (ii) The mass matches the pole mass of pdgcode in SMASH. If it does not, then a warning is printed, the pole mass of the particle is set equal to the corresponding mass from SMASH particle table and it's energy is recomputed as \( E^2 = p^2 + m^2 \). (iii) Any stable particle is on-shell, i.e. \( E^2 - p^2 = m^2 \). If it is not, then a warning is printed and the energy is set to \( E^2 = p^2 + m^2 \). (iv) If there are nan values in the position or momentum of the particle an exception is thrown.

This very tolerant behaviour is justified by the practical usage of SMASH as afterburner. Usually particles unknown to SMASH are rare resonances, which do not play a large role. Mass mismatch is typically less than 1% and comes from rounding and from SMASH enforcing isospin symmetry (for example the mass of neutral pion is artificially forced to be the same as charged pion). On-shellness violation typically comes from the insufficient number of significant digits in the input file + rounding.

Parameters
[in]pdgcodepdg code of added particle
[in]ttime of added particle
[in]xx-coordinate of added particle
[in]yy-coordinate of added particle
[in]zz-coordinate of added particle
[in]massmass of added particle
[in]Eenergy of added particle
[in]pxx-component of momentum of added particle
[in]pyy-component of momentum of added particle
[in]pzz-component of momentum of added particle
[out]particlesstructure, to which the particle is added

Definition at line 118 of file listmodus.cc.

121  {
122  try {
123  ParticleData new_particle =
125  pdgcode, mass, {t, x, y, z}, {E, px, py, pz}, LList,
127  particles.insert(new_particle);
128  } catch (ParticleType::PdgNotFoundFailure &) {
129  logg[LList].warn() << "SMASH does not recognize pdg code " << pdgcode
130  << " loaded from file. This particle will be ignored.\n";
131  }
132 }
bool warn_about_mass_discrepancy_
Auxiliary flag to warn about mass-discrepancies only once per instance.
Definition: listmodus.h:211
bool warn_about_off_shell_particles_
Auxiliary flag to warn about off-shell particles only once per instance.
Definition: listmodus.h:213
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.

◆ is_list()

bool smash::ListModus::is_list ( ) const
inline
Returns
whether the modus is list modus (which is, yes, trivially true)

Definition at line 148 of file listmodus.h.

148 { return true; }

◆ file_has_events_()

bool smash::ListModus::file_has_events_ ( std::filesystem::path  filepath,
std::streampos  last_position 
)
private

Check if the file given by filepath has events left after streampos last_position.

Parameters
[in]filepathPath to file to be checked.
[in]last_positionStream position in file after which check is performed
Returns
True if there is at least one event left, false otherwise
Exceptions
runtime_errorIf file could not be read for whatever reason.

Definition at line 241 of file listmodus.cc.

242  {
243  std::ifstream ifs{filepath};
244  std::string line;
245 
246  // last event read read at end of file. we know this because errors are
247  // handled in next_event
248  if (last_position == -1) {
249  return false;
250  }
251  ifs.seekg(last_position);
252  // skip over comment lines, assume that a max. of four consecutive comment
253  // lines can occur
254  int skipped_lines = 0;
255  const int max_comment_lines = 4;
256  while (std::getline(ifs, line) && line[0] != '#' &&
257  skipped_lines++ < max_comment_lines) {
258  }
259 
260  if (ifs.eof()) {
261  return false;
262  }
263 
264  if (!ifs.good()) {
265  logg[LList].fatal() << "Error while reading "
266  << filepath.filename().native();
267  throw std::runtime_error("Error while reading external particle list");
268  }
269 
270  ifs.close();
271  return true;
272 }

◆ file_path_()

std::filesystem::path smash::ListModus::file_path_ ( std::optional< int >  file_id)
private

Return the absolute path of the data file.

If an integer is passed, the filename is constructed using particle_list_filename_or_prefix_ concatenated with the given number, otherwise the file prefix is understood to be the full filename. The file is expected to be in particle_list_file_directory_ folder.

Parameters
[in]file_idAn std::optional integer
Returns
Absolute file path to file
Exceptions
runtime_errorif file does not exist.

Definition at line 173 of file listmodus.cc.

173  {
174  std::string fname = particle_list_filename_or_prefix_ +
175  ((file_id) ? std::to_string(*file_id) : "");
176 
177  const std::filesystem::path default_path =
178  std::filesystem::absolute(particle_list_file_directory_);
179 
180  const std::filesystem::path fpath = default_path / fname;
181 
182  logg[LList].debug() << "File: " << std::filesystem::absolute(fpath) << '\n';
183 
184  if (!std::filesystem::exists(fpath)) {
185  logg[LList].fatal()
186  << fpath.filename().native() << " does not exist! \n\n"
187  << "Usage of smash with external particle lists:\n"
188  << " 1. Put the external particle lists in one or more files\n"
189  << " according to the user guide instructions.\n"
190  << " 2. Particles info: t x y z mass p0 px py pz pdg ID charge\n"
191  << " in units of: fm fm fm fm GeV GeV GeV GeV GeV none none e\n";
192  throw std::runtime_error("External particle list does not exist!");
193  }
194 
195  return fpath;
196 }

◆ next_event_()

std::string smash::ListModus::next_event_ ( )
private

Read the next event.

Either from the current file if it has more events or from the next file (with file_id += 1)

Returns
One event as string.
Exceptions
runtime_errorIf file could not be read for whatever reason.

Definition at line 198 of file listmodus.cc.

198  {
199  const std::filesystem::path fpath = file_path_(file_id_);
200  std::ifstream ifs{fpath};
201  ifs.seekg(last_read_position_);
202 
203  if (!file_has_events_(fpath, last_read_position_)) {
204  if (file_id_) {
205  // Get next file and call this function recursively
206  (*file_id_)++;
208  ifs.close();
209  return next_event_();
210  } else {
211  throw std::runtime_error(
212  "Attempt to read in next event in Listmodus object but no further "
213  "data found in single provided file. Please, check your setup.");
214  }
215  }
216 
217  // read one event. events marked by line # event end i in case of Oscar
218  // output. Assume one event per file for all other output formats
219  std::string event_string;
220  const std::string needle = "end";
221  std::string line;
222  while (getline(ifs, line)) {
223  if (line.find(needle) == std::string::npos) {
224  event_string += line + "\n";
225  } else {
226  break;
227  }
228  }
229 
230  if (!ifs.eof() && (ifs.fail() || ifs.bad())) {
231  logg[LList].fatal() << "Error while reading " << fpath.filename().native();
232  throw std::runtime_error("Error while reading external particle list");
233  }
234  // save position for next event read
235  last_read_position_ = ifs.tellg();
236  ifs.close();
237 
238  return event_string;
239 }
bool file_has_events_(std::filesystem::path filepath, std::streampos last_position)
Check if the file given by filepath has events left after streampos last_position.
Definition: listmodus.cc:241
std::filesystem::path file_path_(std::optional< int > file_id)
Return the absolute path of the data file.
Definition: listmodus.cc:173
std::streampos last_read_position_
Last read position in current file.
Definition: listmodus.h:208

Member Data Documentation

◆ start_time_

double smash::ListModus::start_time_ = 0.
protected

Starting time for the List; changed to the earliest formation time.

Definition at line 152 of file listmodus.h.

◆ particle_list_file_directory_

std::string smash::ListModus::particle_list_file_directory_
private

File directory of the particle list.

Definition at line 193 of file listmodus.h.

◆ particle_list_filename_or_prefix_

std::string smash::ListModus::particle_list_filename_or_prefix_
private

Prefix of the file(s) containing the particle list.

If the user want to use a single file without numbering, this will contain the full filename.

Definition at line 199 of file listmodus.h.

◆ file_id_

std::optional<int> smash::ListModus::file_id_
private

The id of the current file.

Definition at line 202 of file listmodus.h.

◆ event_id_

int smash::ListModus::event_id_
private

The unique id of the current event.

Definition at line 205 of file listmodus.h.

◆ last_read_position_

std::streampos smash::ListModus::last_read_position_ = 0
private

Last read position in current file.

Definition at line 208 of file listmodus.h.

◆ warn_about_mass_discrepancy_

bool smash::ListModus::warn_about_mass_discrepancy_ = true
private

Auxiliary flag to warn about mass-discrepancies only once per instance.

Definition at line 211 of file listmodus.h.

◆ warn_about_off_shell_particles_

bool smash::ListModus::warn_about_off_shell_particles_ = true
private

Auxiliary flag to warn about off-shell particles only once per instance.

Definition at line 213 of file listmodus.h.


The documentation for this class was generated from the following files: