Version: SMASH-2.0
listmodus.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2013-2020
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #include "smash/listmodus.h"
11 
12 #include <cmath>
13 #include <cstdio>
14 #include <cstdlib>
15 #include <fstream>
16 #include <list>
17 #include <map>
18 #include <sstream>
19 #include <utility>
20 #include <vector>
21 
22 #include <boost/filesystem.hpp>
23 #include <boost/filesystem/fstream.hpp>
24 
25 #include "smash/configuration.h"
26 #include "smash/constants.h"
28 #include "smash/fourvector.h"
29 #include "smash/inputfunctions.h"
30 #include "smash/logging.h"
31 #include "smash/threevector.h"
32 
33 namespace smash {
34 static constexpr int LList = LogArea::List::id;
35 
117  : shift_id_(modus_config.take({"List", "Shift_Id"})) {
118  std::string fd = modus_config.take({"List", "File_Directory"});
120 
121  std::string fp = modus_config.take({"List", "File_Prefix"});
123 
124  event_id_ = 0;
126 }
127 
128 /* console output on startup of List specific parameters */
129 std::ostream &operator<<(std::ostream &out, const ListModus &m) {
130  out << "-- List Modus\nInput directory for external particle lists:\n"
131  << m.particle_list_file_directory_ << "\n";
132  return out;
133 }
134 
136  /* (1) If particles are already at the same time - don't touch them
137  AND start at the start_time_ from the config. */
138  double earliest_formation_time = DBL_MAX;
139  double formation_time_difference = 0.0;
140  double reference_formation_time = 0.0; // avoid compiler warning
141  bool first_particle = true;
142  for (const auto &particle : particles) {
143  const double t = particle.position().x0();
144  if (t < earliest_formation_time) {
145  earliest_formation_time = t;
146  }
147  if (first_particle) {
148  reference_formation_time = t;
149  first_particle = false;
150  } else {
151  formation_time_difference += std::abs(t - reference_formation_time);
152  }
153  }
154  /* (2) If particles are NOT at the same time -> anti-stream them to
155  the earliest time (Note: not to the start_time_ set by config) */
156  bool anti_streaming_needed = (formation_time_difference > really_small);
157  start_time_ = earliest_formation_time;
158  if (anti_streaming_needed) {
159  for (auto &particle : particles) {
160  /* for hydro output where formation time is different */
161  const double t = particle.position().x0();
162  const double delta_t = t - start_time_;
163  const ThreeVector r =
164  particle.position().threevec() - delta_t * particle.velocity();
165  particle.set_4position(FourVector(start_time_, r));
166  particle.set_formation_time(t);
167  particle.set_cross_section_scaling_factor(0.0);
168  }
169  }
170 }
171 
173  double t, double x, double y, double z,
174  double mass, double E, double px, double py,
175  double pz) {
176  constexpr int max_warns_precision = 10, max_warn_mass_consistency = 10;
177  try {
178  ParticleData &particle = particles.create(pdgcode);
179  // SMASH mass versus input mass consistency check
180  if (particle.type().is_stable() &&
181  std::abs(mass - particle.pole_mass()) > really_small) {
182  if (n_warns_precision_ < max_warns_precision) {
183  logg[LList].warn() << "Provided mass of " << particle.type().name()
184  << " = " << mass
185  << " [GeV] is inconsistent with SMASH value = "
186  << particle.pole_mass()
187  << ". Forcing E = sqrt(p^2 + m^2)"
188  << ", where m is SMASH mass.";
190  } else if (n_warns_precision_ == max_warns_precision) {
191  logg[LList].warn(
192  "Further warnings about SMASH mass versus input mass"
193  " inconsistencies will be suppressed.");
195  }
196  particle.set_4momentum(mass, ThreeVector(px, py, pz));
197  }
198  particle.set_4momentum(FourVector(E, px, py, pz));
199  // On-shell condition consistency check
200  if (std::abs(particle.momentum().sqr() - mass * mass) > really_small) {
201  if (n_warns_mass_consistency_ < max_warn_mass_consistency) {
202  logg[LList].warn()
203  << "Provided 4-momentum " << particle.momentum() << " and "
204  << " mass " << mass << " do not satisfy E^2 - p^2 = m^2."
205  << " This may originate from the lack of numerical"
206  << " precision in the input. Setting E to sqrt(p^2 + m^2).";
208  } else if (n_warns_mass_consistency_ == max_warn_mass_consistency) {
209  logg[LList].warn(
210  "Further warnings about E != sqrt(p^2 + m^2) will"
211  " be suppressed.");
213  }
214  particle.set_4momentum(mass, ThreeVector(px, py, pz));
215  }
216  // Set spatial coordinates, they will later be backpropagated if needed
217  particle.set_4position(FourVector(t, x, y, z));
218  particle.set_formation_time(t);
219  particle.set_cross_section_scaling_factor(1.0);
221  logg[LList].warn() << "SMASH does not recognize pdg code " << pdgcode
222  << " loaded from file. This particle will be ignored.\n";
223  }
224 }
225 
226 /* initial_conditions - sets particle data for @particles */
228  const ExperimentParameters &) {
229  std::string particle_list = next_event_();
230 
231  for (const Line &line : line_parser(particle_list)) {
232  std::istringstream lineinput(line.text);
233  double t, x, y, z, mass, E, px, py, pz;
234  int id, charge;
235  std::string pdg_string;
236  lineinput >> t >> x >> y >> z >> mass >> E >> px >> py >> pz >>
237  pdg_string >> id >> charge;
238  if (lineinput.fail()) {
239  throw LoadFailure(
240  build_error_string("While loading external particle lists data:\n"
241  "Failed to convert the input string to the "
242  "expected data types.",
243  line));
244  }
245  PdgCode pdgcode(pdg_string);
246  logg[LList].debug("Particle ", pdgcode, " (x,y,z)= (", x, ", ", y, ", ", z,
247  ")");
248 
249  // Charge consistency check
250  if (pdgcode.charge() != charge) {
251  logg[LList].error() << "Charge of pdg = " << pdgcode << " != " << charge;
252  throw std::invalid_argument("Inconsistent input (charge).");
253  }
254  try_create_particle(*particles, pdgcode, t, x, y, z, mass, E, px, py, pz);
255  }
256  if (particles->size() > 0) {
257  backpropagate_to_same_time(*particles);
258  } else {
259  start_time_ = 0.0;
260  }
261  event_id_++;
262 
263  return start_time_;
264 }
265 
266 bf::path ListModus::file_path_(const int file_id) {
267  std::stringstream fname;
268  fname << particle_list_file_prefix_ << file_id;
269 
270  const bf::path default_path = bf::absolute(particle_list_file_directory_);
271 
272  const bf::path fpath = default_path / fname.str();
273 
274  logg[LList].debug() << fpath.filename().native() << '\n';
275 
276  if (!bf::exists(fpath)) {
277  logg[LList].fatal() << fpath.filename().native() << " does not exist! \n"
278  << "\n Usage of smash with external particle lists:\n"
279  << "1. Put the external particle lists in file \n"
280  << "File_Directory/File_Prefix{id} where {id} "
281  << "traversal [Shift_Id, Nevent-1]\n"
282  << "2. Particles info: t x y z mass p0 px py pz"
283  << " pdg ID charge\n"
284  << "in units of: fm fm fm fm GeV GeV GeV GeV GeV"
285  << " none none e\n";
286  throw std::runtime_error("External particle list does not exist!");
287  }
288 
289  return fpath;
290 }
291 
292 std::string ListModus::next_event_() {
293  const bf::path fpath = file_path_(file_id_);
294  bf::ifstream ifs{fpath};
295  ifs.seekg(last_read_position_);
296 
297  if (!file_has_events_(fpath, last_read_position_)) {
298  // current file out of events. get next file and call this function
299  // recursively.
300  file_id_++;
302  ifs.close();
303  return next_event_();
304  }
305 
306  // read one event. events marked by line # event end i in case of Oscar
307  // output. Assume one event per file for all other output formats
308  std::string event_string;
309  const std::string needle = "end";
310  std::string line;
311  while (getline(ifs, line)) {
312  if (line.find(needle) == std::string::npos) {
313  event_string += line + "\n";
314  } else {
315  break;
316  }
317  }
318 
319  if (!ifs.eof() && (ifs.fail() || ifs.bad())) {
320  logg[LList].fatal() << "Error while reading " << fpath.filename().native();
321  throw std::runtime_error("Error while reading external particle list");
322  }
323  // save position for next event read
324  last_read_position_ = ifs.tellg();
325  ifs.close();
326 
327  return event_string;
328 }
329 
330 bool ListModus::file_has_events_(bf::path filepath,
331  std::streampos last_position) {
332  bf::ifstream ifs{filepath};
333  std::string line;
334 
335  // last event read read at end of file. we know this because errors are
336  // handled in next_event
337  if (last_position == -1) {
338  return false;
339  }
340  ifs.seekg(last_position);
341  // skip over comment lines, assume that a max. of four consecutive comment
342  // lines can occur
343  int skipped_lines = 0;
344  const int max_comment_lines = 4;
345  while (std::getline(ifs, line) && line[0] != '#' &&
346  skipped_lines++ < max_comment_lines) {
347  }
348 
349  if (ifs.eof()) {
350  return false;
351  }
352 
353  if (!ifs.good()) {
354  logg[LList].fatal() << "Error while reading "
355  << filepath.filename().native();
356  throw std::runtime_error("Error while reading external particle list");
357  }
358 
359  ifs.close();
360  return true;
361 }
362 
363 } // namespace smash
smash::line_parser
build_vector_< Line > line_parser(const std::string &input)
Helper function for parsing particles.txt and decaymodes.txt.
Definition: inputfunctions.cc:21
smash
Definition: action.h:24
smash::ListModus::LoadFailure
Definition: listmodus.h:138
smash::ParticleData::momentum
const FourVector & momentum() const
Get the particle's 4-momentum.
Definition: particledata.h:152
smash::build_error_string
std::string build_error_string(std::string message, const Line &line)
Builds a meaningful error message.
Definition: inputfunctions.h:42
smash::ParticleData::pole_mass
double pole_mass() const
Get the particle's pole mass ("on-shell").
Definition: particledata.h:109
smash::Particles::size
size_t size() const
Definition: particles.h:87
smash::ParticleData
Definition: particledata.h:52
smash::ListModus::particle_list_file_directory_
std::string particle_list_file_directory_
File directory of the particle list.
Definition: listmodus.h:151
smash::ListModus::initial_conditions
double initial_conditions(Particles *particles, const ExperimentParameters &parameters)
Generates initial state of the particles in the system according to a list.
Definition: listmodus.cc:227
smash::ListModus::n_warns_mass_consistency_
int n_warns_mass_consistency_
Counter for energy-momentum conservation warnings to avoid spamming.
Definition: listmodus.h:171
smash::Line
Line consists of a line number and the contents of that line.
Definition: inputfunctions.h:23
smash::ParticleType::PdgNotFoundFailure
Definition: particletype.h:491
smash::operator<<
std::ostream & operator<<(std::ostream &out, const ActionPtr &action)
Definition: action.h:518
smash::FourVector::sqr
double sqr() const
calculate the square of the vector (which is a scalar)
Definition: fourvector.h:450
experimentparameters.h
smash::ListModus::file_id_
int file_id_
file_id_ is the id of the current file
Definition: listmodus.h:166
fourvector.h
smash::ParticleData::set_4momentum
void set_4momentum(const FourVector &momentum_vector)
Set the particle's 4-momentum directly.
Definition: particledata.h:158
smash::logg
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
smash::ListModus::backpropagate_to_same_time
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:135
smash::really_small
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37
smash::Configuration
Interface to the SMASH configuration files.
Definition: configuration.h:464
smash::Particles::create
void create(size_t n, PdgCode pdg)
Add n particles of the same type (pdg) to the list.
Definition: particles.cc:66
smash::ListModus::start_time_
double start_time_
Starting time for the List; changed to the earliest formation time.
Definition: listmodus.h:147
smash::ThreeVector
Definition: threevector.h:31
smash::ParticleData::set_formation_time
void set_formation_time(const double &form_time)
Set the absolute formation time.
Definition: particledata.h:245
smash::PdgCode::charge
int charge() const
The charge of the particle.
Definition: pdgcode.h:479
smash::ListModus
Definition: listmodus.h:56
smash::ParticleType::is_stable
bool is_stable() const
Definition: particletype.h:239
threevector.h
smash::ParticleType::name
const std::string & name() const
Definition: particletype.h:141
smash::LList
static constexpr int LList
Definition: listmodus.cc:34
smash::PdgCode
Definition: pdgcode.h:108
smash::ParticleData::set_cross_section_scaling_factor
void set_cross_section_scaling_factor(const double &xsec_scal)
Set the particle's initial cross_section_scaling_factor.
Definition: particledata.h:287
smash::ListModus::try_create_particle
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:172
smash::Particles
Definition: particles.h:33
smash::ListModus::file_has_events_
bool file_has_events_(bf::path filepath, std::streampos last_position)
Check if the file given by filepath has events left after streampos last_position.
Definition: listmodus.cc:330
constants.h
smash::ListModus::n_warns_precision_
int n_warns_precision_
Counter for mass-check warnings to avoid spamming.
Definition: listmodus.h:169
logging.h
smash::ListModus::last_read_position_
std::streampos last_read_position_
last read position in current file
Definition: listmodus.h:185
configuration.h
smash::ListModus::next_event_
std::string next_event_()
Read the next event.
Definition: listmodus.cc:292
smash::ParticleData::set_4position
void set_4position(const FourVector &pos)
Set the particle's 4-position directly.
Definition: particledata.h:203
listmodus.h
smash::ExperimentParameters
Helper structure for Experiment.
Definition: experimentparameters.h:24
smash::FourVector
Definition: fourvector.h:33
smash::ListModus::particle_list_file_prefix_
std::string particle_list_file_prefix_
File prefix of the particle list.
Definition: listmodus.h:154
smash::ListModus::event_id_
int event_id_
event_id_ = the unique id of the current event
Definition: listmodus.h:163
smash::ParticleData::type
const ParticleType & type() const
Get the type of the particle.
Definition: particledata.h:122
inputfunctions.h
smash::ListModus::shift_id_
const int shift_id_
shift_id is the start number of file_id_
Definition: listmodus.h:160
smash::ListModus::ListModus
ListModus()
Construct an empty list. Useful for convenient JetScape connection.
Definition: listmodus.h:72
smash::ListModus::file_path_
bf::path file_path_(const int file_id)
Return the absolute file path based on given integer.
Definition: listmodus.cc:266