Version: SMASH-1.8
listmodus.cc
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2013-2019
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/algorithms.h"
26 #include "smash/angles.h"
27 #include "smash/configuration.h"
28 #include "smash/constants.h"
29 #include "smash/distributions.h"
31 #include "smash/fourvector.h"
32 #include "smash/inputfunctions.h"
33 #include "smash/logging.h"
34 #include "smash/macros.h"
35 #include "smash/particles.h"
36 #include "smash/random.h"
37 #include "smash/threevector.h"
38 
39 namespace smash {
40 static constexpr int LList = LogArea::List::id;
41 
123  : shift_id_(modus_config.take({"List", "Shift_Id"})) {
124  std::string fd = modus_config.take({"List", "File_Directory"});
126 
127  std::string fp = modus_config.take({"List", "File_Prefix"});
129 
130  event_id_ = 0;
132 }
133 
134 /* console output on startup of List specific parameters */
135 std::ostream &operator<<(std::ostream &out, const ListModus &m) {
136  out << "-- List Modus\nInput directory for external particle lists:\n"
137  << m.particle_list_file_directory_ << "\n";
138  return out;
139 }
140 
142  /* (1) If particles are already at the same time - don't touch them
143  AND start at the start_time_ from the config. */
144  double earliest_formation_time = DBL_MAX;
145  double formation_time_difference = 0.0;
146  double reference_formation_time = 0.0; // avoid compiler warning
147  bool first_particle = true;
148  for (const auto &particle : particles) {
149  const double t = particle.position().x0();
150  if (t < earliest_formation_time) {
151  earliest_formation_time = t;
152  }
153  if (first_particle) {
154  reference_formation_time = t;
155  first_particle = false;
156  } else {
157  formation_time_difference += std::abs(t - reference_formation_time);
158  }
159  }
160  /* (2) If particles are NOT at the same time -> anti-stream them to
161  the earliest time (Note: not to the start_time_ set by config) */
162  bool anti_streaming_needed = (formation_time_difference > really_small);
163  start_time_ = earliest_formation_time;
164  if (anti_streaming_needed) {
165  for (auto &particle : particles) {
166  /* for hydro output where formation time is different */
167  const double t = particle.position().x0();
168  const double delta_t = t - start_time_;
169  const ThreeVector r =
170  particle.position().threevec() - delta_t * particle.velocity();
171  particle.set_4position(FourVector(start_time_, r));
172  particle.set_formation_time(t);
173  particle.set_cross_section_scaling_factor(0.0);
174  }
175  }
176 }
177 
179  double t, double x, double y, double z,
180  double mass, double E, double px, double py,
181  double pz) {
182  constexpr int max_warns_precision = 10, max_warn_mass_consistency = 10;
183  try {
184  ParticleData &particle = particles.create(pdgcode);
185  // SMASH mass versus input mass consistency check
186  if (particle.type().is_stable() &&
187  std::abs(mass - particle.pole_mass()) > really_small) {
188  if (n_warns_precision_ < max_warns_precision) {
189  logg[LList].warn() << "Provided mass of " << particle.type().name()
190  << " = " << mass
191  << " [GeV] is inconsistent with SMASH value = "
192  << particle.pole_mass()
193  << ". Forcing E = sqrt(p^2 + m^2)"
194  << ", where m is SMASH mass.";
196  } else if (n_warns_precision_ == max_warns_precision) {
197  logg[LList].warn(
198  "Further warnings about SMASH mass versus input mass"
199  " inconsistencies will be suppressed.");
201  }
202  particle.set_4momentum(mass, ThreeVector(px, py, pz));
203  }
204  particle.set_4momentum(FourVector(E, px, py, pz));
205  // On-shell condition consistency check
206  if (std::abs(particle.momentum().sqr() - mass * mass) > really_small) {
207  if (n_warns_mass_consistency_ < max_warn_mass_consistency) {
208  logg[LList].warn()
209  << "Provided 4-momentum " << particle.momentum() << " and "
210  << " mass " << mass << " do not satisfy E^2 - p^2 = m^2."
211  << " This may originate from the lack of numerical"
212  << " precision in the input. Setting E to sqrt(p^2 + m^2).";
214  } else if (n_warns_mass_consistency_ == max_warn_mass_consistency) {
215  logg[LList].warn(
216  "Further warnings about E != sqrt(p^2 + m^2) will"
217  " be suppressed.");
219  }
220  particle.set_4momentum(mass, ThreeVector(px, py, pz));
221  }
222  // Set spatial coordinates, they will later be backpropagated if needed
223  particle.set_4position(FourVector(t, x, y, z));
224  particle.set_formation_time(t);
225  particle.set_cross_section_scaling_factor(1.0);
227  logg[LList].warn() << "SMASH does not recognize pdg code " << pdgcode
228  << " loaded from file. This particle will be ignored.\n";
229  }
230 }
231 
232 /* initial_conditions - sets particle data for @particles */
234  const ExperimentParameters &) {
235  std::string particle_list = next_event_();
236 
237  for (const Line &line : line_parser(particle_list)) {
238  std::istringstream lineinput(line.text);
239  double t, x, y, z, mass, E, px, py, pz;
240  int id, charge;
241  std::string pdg_string;
242  lineinput >> t >> x >> y >> z >> mass >> E >> px >> py >> pz >>
243  pdg_string >> id >> charge;
244  if (lineinput.fail()) {
245  throw LoadFailure(
246  build_error_string("While loading external particle lists data:\n"
247  "Failed to convert the input string to the "
248  "expected data types.",
249  line));
250  }
251  PdgCode pdgcode(pdg_string);
252  logg[LList].debug("Particle ", pdgcode, " (x,y,z)= (", x, ", ", y, ", ", z,
253  ")");
254 
255  // Charge consistency check
256  if (pdgcode.charge() != charge) {
257  logg[LList].error() << "Charge of pdg = " << pdgcode << " != " << charge;
258  throw std::invalid_argument("Inconsistent input (charge).");
259  }
260  try_create_particle(*particles, pdgcode, t, x, y, z, mass, E, px, py, pz);
261  }
262  if (particles->size() > 0) {
263  backpropagate_to_same_time(*particles);
264  } else {
265  start_time_ = 0.0;
266  }
267  event_id_++;
268 
269  return start_time_;
270 }
271 
272 bf::path ListModus::file_path_(const int file_id) {
273  std::stringstream fname;
274  fname << particle_list_file_prefix_ << file_id;
275 
276  const bf::path default_path = bf::absolute(particle_list_file_directory_);
277 
278  const bf::path fpath = default_path / fname.str();
279 
280  logg[LList].debug() << fpath.filename().native() << '\n';
281 
282  if (!bf::exists(fpath)) {
283  logg[LList].fatal() << fpath.filename().native() << " does not exist! \n"
284  << "\n Usage of smash with external particle lists:\n"
285  << "1. Put the external particle lists in file \n"
286  << "File_Directory/File_Prefix{id} where {id} "
287  << "traversal [Shift_Id, Nevent-1]\n"
288  << "2. Particles info: t x y z mass p0 px py pz"
289  << " pdg ID charge\n"
290  << "in units of: fm fm fm fm GeV GeV GeV GeV GeV"
291  << " none none none\n";
292  throw std::runtime_error("External particle list does not exist!");
293  }
294 
295  return fpath;
296 }
297 
298 std::string ListModus::next_event_() {
299  const bf::path fpath = file_path_(file_id_);
300  bf::ifstream ifs{fpath};
301  ifs.seekg(last_read_position_);
302 
303  if (!file_has_events_(fpath, last_read_position_)) {
304  // current file out of events. get next file and call this function
305  // recursively.
306  file_id_++;
308  ifs.close();
309  return next_event_();
310  }
311 
312  // read one event. events marked by line # event end i in case of Oscar
313  // output. Assume one event per file for all other output formats
314  std::string event_string;
315  const std::string needle = "end";
316  std::string line;
317  while (getline(ifs, line)) {
318  if (line.find(needle) == std::string::npos) {
319  event_string += line + "\n";
320  } else {
321  break;
322  }
323  }
324 
325  if (!ifs.eof() && (ifs.fail() || ifs.bad())) {
326  logg[LList].fatal() << "Error while reading " << fpath.filename().native();
327  throw std::runtime_error("Error while reading external particle list");
328  }
329  // save position for next event read
330  last_read_position_ = ifs.tellg();
331  ifs.close();
332 
333  return event_string;
334 }
335 
336 bool ListModus::file_has_events_(bf::path filepath,
337  std::streampos last_position) {
338  bf::ifstream ifs{filepath};
339  std::string line;
340 
341  // last event read read at end of file. we know this because errors are
342  // handled in next_event
343  if (last_position == -1) {
344  return false;
345  }
346  ifs.seekg(last_position);
347  // skip over comment lines, assume that a max. of four consecutive comment
348  // lines can occur
349  int skipped_lines = 0;
350  const int max_comment_lines = 4;
351  while (std::getline(ifs, line) && line[0] != '#' &&
352  skipped_lines++ < max_comment_lines) {
353  }
354 
355  if (ifs.eof()) {
356  return false;
357  }
358 
359  if (!ifs.good()) {
360  logg[LList].fatal() << "Error while reading "
361  << filepath.filename().native();
362  throw std::runtime_error("Error while reading external particle list");
363  }
364 
365  ifs.close();
366  return true;
367 }
368 
369 } // 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
algorithms.h
smash::ParticleData::momentum
const FourVector & momentum() const
Get the particle's 4-momentum.
Definition: particledata.h:142
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:99
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:233
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:489
macros.h
smash::operator<<
std::ostream & operator<<(std::ostream &out, const ActionPtr &action)
Definition: action.h:463
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:148
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:141
smash::really_small
constexpr double really_small
Numerical error tolerance.
Definition: constants.h:37
random.h
angles.h
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:235
smash::PdgCode::charge
int charge() const
The charge of the particle.
Definition: pdgcode.h:467
smash::ListModus
Definition: listmodus.h:56
smash::ParticleType::is_stable
bool is_stable() const
Definition: particletype.h:236
threevector.h
smash::ParticleType::name
const std::string & name() const
Definition: particletype.h:141
distributions.h
smash::LList
static constexpr int LList
Definition: listmodus.cc:40
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:277
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:178
particles.h
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:336
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:298
smash::ParticleData::set_4position
void set_4position(const FourVector &pos)
Set the particle's 4-position directly.
Definition: particledata.h:193
listmodus.h
smash::ExperimentParameters
Helper structure for Experiment.
Definition: experimentparameters.h:23
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:112
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:272