Version: SMASH-1.6
smash.cc File Reference
#include <getopt.h>
#include <set>
#include <sstream>
#include <vector>
#include <boost/filesystem/fstream.hpp>
#include "smash/cxx14compat.h"
#include "smash/decaymodes.h"
#include "smash/experiment.h"
#include "smash/filelock.h"
#include "smash/random.h"
#include "smash/scatteractionsfinder.h"
#include "smash/setup_particles_decaymodes.h"
#include "smash/stringfunctions.h"
#include "smash/config.h"

Go to the source code of this file.

Classes

struct  smash::anonymous_namespace{smash.cc}::OutputDirectoryExists
 Exception class that is thrown, if the requested output directory already exists and -f was not specified on the command line. More...
 
struct  smash::anonymous_namespace{smash.cc}::OutputDirectoryOutOfIds
 Exception class that is thrown, if no new output path can be generated (there is a directory name for each positive integer value) More...
 

Namespaces

 smash
 
 smash::anonymous_namespace{smash.cc}
 

Functions

void smash::anonymous_namespace{smash.cc}::print_disclaimer ()
 Print the disclaimer. More...
 
bf::path smash::anonymous_namespace{smash.cc}::default_output_path ()
 
void smash::anonymous_namespace{smash.cc}::ensure_path_is_valid (const bf::path &path)
 Ensures the output path is valid. More...
 
ScatterActionsFinder smash::anonymous_namespace{smash.cc}::actions_finder_for_dump (Configuration configuration)
 Prepares ActionsFinder for cross-section and reaction dumps. More...
 
void smash::anonymous_namespace{smash.cc}::check_config_version_is_compatible (Configuration configuration)
 Checks if the SMASH version is compatible with the version of the configuration file. More...
 
void smash::anonymous_namespace{smash.cc}::check_for_unused_config_values (const Configuration &configuration)
 Checks if there are unused config values. More...
 
void smash::anonymous_namespace{smash.cc}::ignore_simulation_config_values (Configuration &configuration)
 Remove all config values that are only needed for simulations. More...
 
int main (int argc, char *argv[])
 Main program Smashes Many Accelerated Strongly-Interacting Hadrons :-) More...
 

Function Documentation

int main ( int  argc,
char *  argv[] 
)

Main program Smashes Many Accelerated Strongly-Interacting Hadrons :-)

Do command line parsing and hence decides modus

Parameters
[in]argcNumber of arguments on command-line
[in]argvList of arguments on command-line
Returns
Either 0 or EXIT_FAILURE.

Definition at line 382 of file smash.cc.

382  {
383  using namespace smash; // NOLINT(build/namespaces)
384 
385  const auto &log = logger<LogArea::Main>();
386 
387  constexpr option longopts[] = {
388  {"config", required_argument, 0, 'c'},
389  {"decaymodes", required_argument, 0, 'd'},
390  {"endtime", required_argument, 0, 'e'},
391  {"force", no_argument, 0, 'f'},
392  {"help", no_argument, 0, 'h'},
393  {"inputfile", required_argument, 0, 'i'},
394  {"modus", required_argument, 0, 'm'},
395  {"particles", required_argument, 0, 'p'},
396  {"output", required_argument, 0, 'o'},
397  {"list-2-to-n", no_argument, 0, 'l'},
398  {"resonance", required_argument, 0, 'r'},
399  {"cross-sections", required_argument, 0, 's'},
400  {"cross-sections-fs", required_argument, 0, 'S'},
401  {"version", no_argument, 0, 'v'},
402  {nullptr, 0, 0, 0}};
403 
404  // strip any path to progname
405  const std::string progname = bf::path(argv[0]).filename().native();
406 
407  try {
408  bool force_overwrite = false;
409  bf::path output_path = default_output_path(), input_path("./config.yaml");
410  std::vector<std::string> extra_config;
411  char *particles = nullptr, *decaymodes = nullptr, *modus = nullptr,
412  *end_time = nullptr, *pdg_string = nullptr, *cs_string = nullptr;
413  bool list2n_activated = false;
414  bool resonance_dump_activated = false;
415  bool cross_section_dump_activated = false;
416  bool final_state_cross_sections = false;
417 
418  // parse command-line arguments
419  int opt;
420  bool suppress_disclaimer = false;
421  while ((opt = getopt_long(argc, argv, "c:d:e:fhi:m:p:o:lr:s:S:v", longopts,
422  nullptr)) != -1) {
423  switch (opt) {
424  case 'c':
425  extra_config.emplace_back(optarg);
426  break;
427  case 'd':
428  decaymodes = optarg;
429  break;
430  case 'f':
431  force_overwrite = true;
432  break;
433  case 'i':
434  input_path = optarg;
435  break;
436  case 'h':
437  usage(EXIT_SUCCESS, progname);
438  break;
439  case 'm':
440  modus = optarg;
441  break;
442  case 'p':
443  particles = optarg;
444  break;
445  case 'e':
446  end_time = optarg;
447  break;
448  case 'o':
449  output_path = optarg;
450  break;
451  case 'l':
452  list2n_activated = true;
453  suppress_disclaimer = true;
454  break;
455  case 'r':
456  resonance_dump_activated = true;
457  pdg_string = optarg;
458  suppress_disclaimer = true;
459  break;
460  case 'S':
461  final_state_cross_sections = true;
462  // fallthrough
463  case 's':
464  cross_section_dump_activated = true;
465  cs_string = optarg;
466  suppress_disclaimer = true;
467  break;
468  case 'v':
469  std::printf(
470  "%s\n"
471  "Branch : %s\nSystem : %s\nCompiler : %s %s\n"
472  "Build : %s\nDate : %s\n",
473  VERSION_MAJOR, GIT_BRANCH, CMAKE_SYSTEM, CMAKE_CXX_COMPILER_ID,
474  CMAKE_CXX_COMPILER_VERSION, CMAKE_BUILD_TYPE, BUILD_DATE);
475  std::exit(EXIT_SUCCESS);
476  default:
477  usage(EXIT_FAILURE, progname);
478  }
479  }
480 
481  // Abort if there are unhandled arguments left.
482  if (optind < argc) {
483  std::cout << argv[0] << ": invalid argument -- '" << argv[optind]
484  << "'\n";
485  usage(EXIT_FAILURE, progname);
486  }
487 
488  if (!suppress_disclaimer) {
490  }
491 
493 
494  // Read in config file
495  Configuration configuration(input_path.parent_path(),
496  input_path.filename());
497  // Merge config passed via command line
498  for (const auto &config : extra_config) {
499  configuration.merge_yaml(config);
500  }
501 
502  // Set up logging
504  configuration.take({"Logging", "default"}, einhard::ALL));
505  create_all_loggers(configuration["Logging"]);
506 
507  // check if version matches before doing anything else
509 
510  log.trace(source_location, " create ParticleType and DecayModes");
511 
512  auto particles_and_decays =
513  load_particles_and_decaymodes(particles, decaymodes);
514  /* For particles and decaymodes: external file is superior to config.
515  * Hovever, warn in case of conflict.
516  */
517  if (configuration.has_value({"particles"}) && particles) {
518  log.warn("Ambiguity: particles from external file ", particles,
519  " requested, but there is also particle list in the config."
520  " Using particles from ",
521  particles);
522  }
523  if (!configuration.has_value({"particles"}) || particles) {
524  configuration["particles"] = particles_and_decays.first;
525  }
526 
527  if (configuration.has_value({"decaymodes"}) && decaymodes) {
528  log.warn("Ambiguity: decaymodes from external file ", decaymodes,
529  " requested, but there is also decaymodes list in the config."
530  " Using decaymodes from",
531  decaymodes);
532  }
533  if (!configuration.has_value({"decaymodes"}) || decaymodes) {
534  configuration["decaymodes"] = particles_and_decays.second;
535  }
539 
540  if (list2n_activated) {
541  /* Print only 2->n, n > 1. Do not dump decays, which can be found in
542  * decaymodes.txt anyway */
543  configuration.merge_yaml("{Collision_Term: {Two_to_One: False}}");
544  auto scat_finder = actions_finder_for_dump(configuration);
545 
548 
549  scat_finder.dump_reactions();
550  std::exit(EXIT_SUCCESS);
551  }
552  if (resonance_dump_activated) {
553  // Ignore config values that don't make sense.
554  const auto _dummy = ExperimentBase::create(configuration, output_path);
557 
558  PdgCode pdg(pdg_string);
559  const ParticleType &res = ParticleType::find(pdg);
561  std::exit(EXIT_SUCCESS);
562  }
563  if (cross_section_dump_activated) {
564  std::string arg_string(cs_string);
565  std::vector<std::string> args = split(arg_string, ',');
566  const unsigned int n_arg = args.size();
567  if (n_arg != 2 && n_arg != 4 && n_arg < 5) {
568  throw std::invalid_argument("-s usage: pdg1,pdg2[,m1,m2[,sqrts1,...]]");
569  }
570  PdgCode pdg_a(args[0]), pdg_b(args[1]);
571  const ParticleType &a = ParticleType::find(pdg_a);
572  const ParticleType &b = ParticleType::find(pdg_b);
573  if (n_arg < 4) {
574  for (unsigned int i = 0; i < 4 - n_arg; i++) {
575  args.push_back("");
576  }
577  }
578  double ma = (args[2] == "") ? a.mass() : std::stod(args[2]);
579  double mb = (args[3] == "") ? b.mass() : std::stod(args[3]);
580  if (a.is_stable() && args[2] != "" && std::stod(args[2]) != a.mass()) {
581  ma = a.mass();
582  std::cerr << "Warning: pole mass is used for stable particle "
583  << a.name() << " instead of " << args[2] << std::endl;
584  }
585  if (b.is_stable() && args[3] != "" && std::stod(args[3]) != b.mass()) {
586  mb = b.mass();
587  std::cerr << "Warning: pole mass is used for stable particle "
588  << b.name() << " instead of " << args[3] << std::endl;
589  }
590  const size_t plab_size = n_arg <= 4 ? 0 : n_arg - 4;
591  std::vector<double> plab;
592  plab.reserve(plab_size);
593  for (size_t i = 4; i < n_arg; i++) {
594  plab.push_back(std::stod(args.at(i)));
595  }
596  auto scat_finder = actions_finder_for_dump(configuration);
597 
600 
601  scat_finder.dump_cross_sections(a, b, ma, mb, final_state_cross_sections,
602  plab);
603  std::exit(EXIT_SUCCESS);
604  }
605  if (modus) {
606  configuration["General"]["Modus"] = std::string(modus);
607  }
608  if (end_time) {
609  configuration["General"]["End_Time"] = std::abs(std::atof(end_time));
610  }
611 
612  int64_t seed = configuration.read({"General", "Randomseed"});
613  if (seed < 0) {
614  configuration["General"]["Randomseed"] = random::generate_63bit_seed();
615  }
616 
617  // Check output path
618  ensure_path_is_valid(output_path);
619  const bf::path lock_path = output_path / "smash.lock";
620  FileLock lock(lock_path);
621  if (!lock.acquire()) {
622  throw std::runtime_error(
623  "Another instance of SMASH is already writing to the specified "
624  "output directory. If you are sure this is not the case, remove \"" +
625  lock_path.native() + "\".");
626  }
627  log.debug("output path: ", output_path);
628  if (!force_overwrite && bf::exists(output_path / "config.yaml")) {
629  throw std::runtime_error(
630  "Output directory would get overwritten. Select a different output "
631  "directory, clean up, or tell SMASH to ignore existing files.");
632  }
633 
634  /* Keep a copy of the configuration that was used in the output directory
635  * also save information about SMASH build as a comment */
636  bf::ofstream(output_path / "config.yaml")
637  << "# " << VERSION_MAJOR << '\n'
638  << "# Branch : " << GIT_BRANCH << '\n'
639  << "# System : " << CMAKE_SYSTEM << '\n'
640  << "# Compiler : " << CMAKE_CXX_COMPILER_ID << ' '
641  << CMAKE_CXX_COMPILER_VERSION << '\n'
642  << "# Build : " << CMAKE_BUILD_TYPE << '\n'
643  << "# Date : " << BUILD_DATE << '\n'
644  << configuration.to_string() << '\n';
645  configuration.take({"particles"});
646  configuration.take({"decaymodes"});
647 
648  // Create an experiment
649  log.trace(source_location, " create Experiment");
650  auto experiment = ExperimentBase::create(configuration, output_path);
651 
652  // Version value is not used in experiment. Get rid of it to prevent
653  // warning.
654  configuration.take({"Version"});
656 
657  // Run the experiment
658  log.trace(source_location, " run the Experiment");
659  experiment->run();
660  } catch (std::exception &e) {
661  log.fatal() << "SMASH failed with the following error:\n" << e.what();
662  return EXIT_FAILURE;
663  }
664 
665  log.trace() << source_location << " about to return from main";
666  return 0;
667 }
std::string to_string() const
Returns a YAML string of the current tree.
Configuration configuration(std::string overrides={})
Return a configuration object filled with data from src/config.yaml.
Definition: setup.h:161
static std::unique_ptr< ExperimentBase > create(Configuration config, const bf::path &output_path)
Factory method that creates and initializes a new Experiment<Modus>.
ScatterActionsFinder actions_finder_for_dump(Configuration configuration)
Prepares ActionsFinder for cross-section and reaction dumps.
Definition: smash.cc:289
bool is_stable() const
Definition: particletype.h:236
static void check_consistency()
void check_config_version_is_compatible(Configuration configuration)
Checks if the SMASH version is compatible with the version of the configuration file.
Definition: smash.cc:309
static void load_decaymodes(const std::string &input)
Loads the DecayModes map as described in the input string.
Definition: decaymodes.cc:163
std::pair< std::string, std::string > load_particles_and_decaymodes(const char *particles_file, const char *decaymodes_file)
Loads particles and decaymodes from provided files particles_file and decaymodes_file.
void ensure_path_is_valid(const bf::path &path)
Ensures the output path is valid.
Definition: smash.cc:267
Value read(std::initializer_list< const char * > keys) const
Additional interface for SMASH to read configuration values without removing them.
std::vector< std::string > split(const std::string &s, char delim)
Split string by delimiter.
Interface to the SMASH configuration files.
bool has_value(std::initializer_list< const char * > keys) const
Returns whether there is a non-empty value behind the requested keys.
void setup_default_float_traps()
Setup the floating-point traps used throughout SMASH.
static const ParticleType & find(PdgCode pdgcode)
Returns the ParticleType object for the given pdgcode.
double mass() const
Definition: particletype.h:144
void merge_yaml(const std::string &yaml)
Merge the configuration in yaml into the existing tree.
void create_all_loggers(Configuration config)
Called from main() right after the Configuration object is fully set up to create all logger objects ...
Definition: logging.cc:116
const std::string & name() const
Definition: particletype.h:141
#define source_location
Hackery that is required to output the location in the source code where the log statement occurs...
Definition: logging.h:246
Value take(std::initializer_list< const char * > keys)
The default interface for SMASH to read configuration values.
Guard to create a file lock.
Definition: filelock.h:30
Particle type contains the static properties of a particle species.
Definition: particletype.h:97
void print_disclaimer()
Print the disclaimer.
Definition: smash.cc:162
PdgCode stores a Particle Data Group Particle Numbering Scheme particle type number.
Definition: pdgcode.h:108
static void create_type_list(const std::string &particles)
Initialize the global ParticleType list (list_all) from the given input data.
void set_default_loglevel(einhard::LogLevel level)
Set the default log level (what will be returned from subsequent default_loglevel calls)...
Definition: logging.cc:24
int64_t generate_63bit_seed()
Generates a seed with a truly random 63-bit value, if possible.
Definition: random.cc:17
void dump_width_and_spectral_function() const
Prints out width and spectral function versus mass to the standard output.
Log all message.
Definition: einhard.hpp:106
std::unique_ptr< ExperimentBase > experiment(const Configuration &c=configuration())
Create an experiment.
Definition: setup.h:175
void check_for_unused_config_values(const Configuration &configuration)
Checks if there are unused config values.
Definition: smash.cc:333
void ignore_simulation_config_values(Configuration &configuration)
Remove all config values that are only needed for simulations.
Definition: smash.cc:348
Definition: action.h:24

Here is the call graph for this function:

Here is the caller graph for this function: