Version: SMASH-3.0
smash.cc File Reference
#include <getopt.h>
#include <filesystem>
#include <set>
#include <sstream>
#include <vector>
#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/sha256.h"
#include "smash/stringfunctions.h"
#include "smash/config.h"
#include "smash/library.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}::usage (const int rc, const std::string &progname)
 Prints usage information and exits the program. More...
 
void smash::anonymous_namespace{smash.cc}::print_disclaimer ()
 Print the disclaimer. More...
 
std::filesystem::path smash::anonymous_namespace{smash.cc}::default_output_path ()
 
void smash::anonymous_namespace{smash.cc}::ensure_path_is_valid (const std::filesystem::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_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

◆ main()

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 359 of file smash.cc.

359  {
360  using namespace smash; // NOLINT(build/namespaces)
361 
362  constexpr option longopts[] = {
363  {"config", required_argument, 0, 'c'},
364  {"decaymodes", required_argument, 0, 'd'},
365  {"endtime", required_argument, 0, 'e'},
366  {"force", no_argument, 0, 'f'},
367  {"help", no_argument, 0, 'h'},
368  {"inputfile", required_argument, 0, 'i'},
369  {"modus", required_argument, 0, 'm'},
370  {"particles", required_argument, 0, 'p'},
371  {"output", required_argument, 0, 'o'},
372  {"list-2-to-n", no_argument, 0, 'l'},
373  {"resonance", required_argument, 0, 'r'},
374  {"cross-sections", required_argument, 0, 's'},
375  {"cross-sections-fs", required_argument, 0, 'S'},
376  {"dump-iSS", no_argument, 0, 'x'},
377  {"version", no_argument, 0, 'v'},
378  {"no-cache", no_argument, 0, 'n'},
379  {"quiet", no_argument, 0, 'q'},
380  {nullptr, 0, 0, 0}};
381 
382  // strip any path to progname
383  const std::string progname =
384  std::filesystem::path(argv[0]).filename().native();
385 
386  try {
387  bool force_overwrite = false;
388  std::filesystem::path output_path = default_output_path();
389  std::string input_path("./config.yaml"), particles, decaymodes;
390  std::vector<std::string> extra_config;
391  char *modus = nullptr, *end_time = nullptr, *pdg_string = nullptr,
392  *cs_string = nullptr;
393  bool list2n_activated = false;
394  bool resonance_dump_activated = false;
395  bool cross_section_dump_activated = false;
396  bool final_state_cross_sections = false;
397  bool particles_dump_iSS_format = false;
398  bool cache_integrals = true;
399  bool suppress_disclaimer = false;
400 
401  // parse command-line arguments
402  int opt;
403  while ((opt = getopt_long(argc, argv, "c:d:e:fhi:m:p:o:lr:s:S:xvnq",
404  longopts, nullptr)) != -1) {
405  switch (opt) {
406  case 'c':
407  extra_config.emplace_back(optarg);
408  break;
409  case 'd':
410  decaymodes = optarg;
411  break;
412  case 'f':
413  force_overwrite = true;
414  break;
415  case 'i':
416  input_path = optarg;
417  break;
418  case 'h':
419  usage(EXIT_SUCCESS, progname);
420  break;
421  case 'm':
422  modus = optarg;
423  break;
424  case 'p':
425  particles = optarg;
426  break;
427  case 'e':
428  end_time = optarg;
429  break;
430  case 'o':
431  output_path = optarg;
432  break;
433  case 'l':
434  list2n_activated = true;
435  suppress_disclaimer = true;
436  break;
437  case 'r':
438  resonance_dump_activated = true;
439  pdg_string = optarg;
440  suppress_disclaimer = true;
441  break;
442  case 'S':
443  final_state_cross_sections = true;
444  // fallthrough
445  case 's':
446  cross_section_dump_activated = true;
447  cs_string = optarg;
448  suppress_disclaimer = true;
449  break;
450  case 'x':
451  particles_dump_iSS_format = true;
452  suppress_disclaimer = true;
453  break;
454  case 'v':
455  std::printf(
456  "%s\n"
457 #ifdef GIT_BRANCH
458  "Branch : %s\n"
459 #endif
460  "System : %s\nCompiler : %s %s\n"
461  "Build : %s\nDate : %s\n",
462  SMASH_VERSION,
463 #ifdef GIT_BRANCH
464  GIT_BRANCH,
465 #endif
466  CMAKE_SYSTEM, CMAKE_CXX_COMPILER_ID, CMAKE_CXX_COMPILER_VERSION,
467  CMAKE_BUILD_TYPE, BUILD_DATE);
468  std::exit(EXIT_SUCCESS);
469  case 'n':
470  cache_integrals = false;
471  break;
472  case 'q':
473  suppress_disclaimer = true;
474  break;
475  default:
476  usage(EXIT_FAILURE, progname);
477  }
478  }
479 
480  // Abort if there are unhandled arguments left.
481  if (optind < argc) {
482  std::cout << argv[0] << ": invalid argument -- '" << argv[optind]
483  << "'\n";
484  usage(EXIT_FAILURE, progname);
485  }
486 
487  if (!suppress_disclaimer) {
489  }
490 
491  auto configuration = setup_config_and_logging(input_path, particles,
492  decaymodes, extra_config);
493 
495 
496  // Check output path
497  ensure_path_is_valid(output_path);
498  std::string tabulations_path;
499  if (cache_integrals) {
500  tabulations_path = output_path.has_parent_path()
501  ? output_path.parent_path().string()
502  : ".";
503  tabulations_path += "/tabulations";
504  } else {
505  tabulations_path = "";
506  }
507  const std::string version(SMASH_VERSION);
508 
509  if (list2n_activated) {
510  /* Print only 2->n, n > 1. Do not dump decays, which can be found in
511  * decaymodes.txt anyway */
512  configuration.merge_yaml("{Collision_Term: {Two_to_One: False}}");
513  initialize_particles_decays_and_tabulations(configuration, version,
514  tabulations_path);
515  auto scat_finder = actions_finder_for_dump(configuration);
516 
517  ignore_simulation_config_values(configuration);
518  check_for_unused_config_values(configuration);
519 
520  scat_finder.dump_reactions();
521  std::exit(EXIT_SUCCESS);
522  }
523  if (particles_dump_iSS_format) {
524  initialize_particles_decays_and_tabulations(configuration, version,
525  tabulations_path);
526  ParticleTypePtrList list;
527  list.clear();
528  for (const auto &ptype : ParticleType::list_all()) {
529  list.push_back(&ptype);
530  }
531  std::sort(list.begin(), list.end(),
533  return a->mass() < b->mass();
534  });
535  for (const ParticleTypePtr &ptype : list) {
536  if (ptype->pdgcode().is_lepton() || ptype->baryon_number() < 0) {
537  continue;
538  }
539  const auto &decay_modes = ptype->decay_modes();
540  const auto &modelist = decay_modes.decay_mode_list();
541  int ndecays = ptype->is_stable() ? 1 : modelist.size();
542  std::printf("%13i %s %10.5f %10.5f %5i %5i %5i %5i %5i %5i %5i %5i\n",
543  ptype->pdgcode().get_decimal(),
544  smash::utf8::fill_left(ptype->name(), 12, ' ').c_str(),
545  ptype->mass(), ptype->width_at_pole(),
546  ptype->pdgcode().spin_degeneracy(), ptype->baryon_number(),
547  ptype->strangeness(), ptype->pdgcode().charmness(),
548  ptype->pdgcode().bottomness(), ptype->isospin() + 1,
549  ptype->charge(), ndecays);
550  if (!ptype->is_stable()) {
551  for (const auto &decay : modelist) {
552  auto ptypes = decay->particle_types();
553  std::printf("%13i %13i %20.5f %13i %13i %13i %13i %13i\n",
554  ptype->pdgcode().get_decimal(), 2, decay->weight(),
555  ptypes[0]->pdgcode().get_decimal(),
556  ptypes[1]->pdgcode().get_decimal(), 0, 0, 0);
557  }
558  } else {
559  std::printf("%13i %13i %20.5f %13i %13i %13i %13i %13i\n",
560  ptype->pdgcode().get_decimal(), 1, 1.0,
561  ptype->pdgcode().get_decimal(), 0, 0, 0, 0);
562  }
563  }
564  std::exit(EXIT_SUCCESS);
565  }
566  if (resonance_dump_activated) {
567  // Ignore config values that don't make sense.
568  initialize_particles_decays_and_tabulations(configuration, version,
569  tabulations_path);
570  const auto _dummy = ExperimentBase::create(configuration, output_path);
571  ignore_simulation_config_values(configuration);
572  check_for_unused_config_values(configuration);
573 
574  PdgCode pdg(pdg_string);
575  const ParticleType &res = ParticleType::find(pdg);
577  std::exit(EXIT_SUCCESS);
578  }
579  if (cross_section_dump_activated) {
580  initialize_particles_decays_and_tabulations(configuration, version,
581  tabulations_path);
582  std::string arg_string(cs_string);
583  std::vector<std::string> args = split(arg_string, ',');
584  const unsigned int n_arg = args.size();
585  if (n_arg != 2 && n_arg != 4 && n_arg < 5) {
586  throw std::invalid_argument("-s usage: pdg1,pdg2[,m1,m2[,sqrts1,...]]");
587  }
588  PdgCode pdg_a(args[0]), pdg_b(args[1]);
589  const ParticleType &a = ParticleType::find(pdg_a);
590  const ParticleType &b = ParticleType::find(pdg_b);
591  if (n_arg < 4) {
592  for (unsigned int i = 0; i < 4 - n_arg; i++) {
593  args.push_back("");
594  }
595  }
596  double ma = (args[2] == "") ? a.mass() : std::stod(args[2]);
597  double mb = (args[3] == "") ? b.mass() : std::stod(args[3]);
598  if (a.is_stable() && args[2] != "" && std::stod(args[2]) != a.mass()) {
599  ma = a.mass();
600  std::cerr << "Warning: pole mass is used for stable particle "
601  << a.name() << " instead of " << args[2] << std::endl;
602  }
603  if (b.is_stable() && args[3] != "" && std::stod(args[3]) != b.mass()) {
604  mb = b.mass();
605  std::cerr << "Warning: pole mass is used for stable particle "
606  << b.name() << " instead of " << args[3] << std::endl;
607  }
608  const size_t plab_size = n_arg <= 4 ? 0 : n_arg - 4;
609  std::vector<double> plab;
610  plab.reserve(plab_size);
611  for (size_t i = 4; i < n_arg; i++) {
612  plab.push_back(std::stod(args.at(i)));
613  }
614  auto scat_finder = actions_finder_for_dump(configuration);
615 
616  ignore_simulation_config_values(configuration);
617  check_for_unused_config_values(configuration);
618 
619  scat_finder.dump_cross_sections(a, b, ma, mb, final_state_cross_sections,
620  plab);
621  std::exit(EXIT_SUCCESS);
622  }
623  if (modus) {
624  configuration.set_value({"General", "Modus"}, std::string(modus));
625  }
626  if (end_time) {
627  configuration.set_value({"General", "End_Time"},
628  std::abs(std::atof(end_time)));
629  }
630 
631  int64_t seed = configuration.read({"General", "Randomseed"});
632  if (seed < 0) {
633  configuration.set_value({"General", "Randomseed"},
635  }
636 
637  // Avoid overwriting SMASH output
638  const std::filesystem::path lock_path = output_path / "smash.lock";
639  FileLock lock(lock_path);
640  if (!lock.acquire()) {
641  throw std::runtime_error(
642  "Another instance of SMASH is already writing to the specified "
643  "output directory. If you are sure this is not the case, remove \"" +
644  lock_path.native() + "\".");
645  }
646  logg[LMain].debug("output path: ", output_path);
647  if (!force_overwrite &&
648  std::filesystem::exists(output_path / "config.yaml")) {
649  throw std::runtime_error(
650  "Output directory would get overwritten. Select a different output "
651  "directory, clean up, or tell SMASH to ignore existing files.");
652  }
653 
654  /* Keep a copy of the configuration that was used in the output directory
655  * also save information about SMASH build as a comment */
656  std::ofstream(output_path / "config.yaml")
657  << "# " << SMASH_VERSION << '\n'
658 #ifdef GIT_BRANCH
659  << "# Branch : " << GIT_BRANCH << '\n'
660 #endif
661  << "# System : " << CMAKE_SYSTEM << '\n'
662  << "# Compiler : " << CMAKE_CXX_COMPILER_ID << ' '
663  << CMAKE_CXX_COMPILER_VERSION << '\n'
664  << "# Build : " << CMAKE_BUILD_TYPE << '\n'
665  << "# Date : " << BUILD_DATE << '\n'
666  << configuration.to_string() << '\n';
667 
668  initialize_particles_decays_and_tabulations(configuration, version,
669  tabulations_path);
670 
671  // Create an experiment
672  logg[LMain].trace(SMASH_SOURCE_LOCATION, " create Experiment");
673  auto experiment = ExperimentBase::create(configuration, output_path);
674 
675  // Version key is deprecated. If present, ignore it.
676  if (configuration.has_value({"Version"})) {
677  configuration.take({"Version"});
678  }
679  check_for_unused_config_values(configuration);
680 
681  // Run the experiment
682  logg[LMain].trace(SMASH_SOURCE_LOCATION, " run the Experiment");
683  experiment->run();
684  } catch (std::exception &e) {
685  logg[LMain].fatal() << "SMASH failed with the following error:\n"
686  << e.what();
687  return EXIT_FAILURE;
688  }
689 
690  logg[LMain].trace() << SMASH_SOURCE_LOCATION << " about to return from main";
691  return 0;
692 }
static std::unique_ptr< ExperimentBase > create(Configuration &config, const std::filesystem::path &output_path)
Factory method that creates and initializes a new Experiment<Modus>.
Definition: experiment.cc:22
Guard to create a file lock.
Definition: filelock.h:30
A pointer-like interface to global references to ParticleType objects.
Definition: particletype.h:672
Particle type contains the static properties of a particle species.
Definition: particletype.h:97
void dump_width_and_spectral_function() const
Prints out width and spectral function versus mass to the standard output.
static const ParticleType & find(PdgCode pdgcode)
Returns the ParticleType object for the given pdgcode.
Definition: particletype.cc:99
const std::string & name() const
Definition: particletype.h:141
static const ParticleTypeList & list_all()
Definition: particletype.cc:51
bool is_stable() const
Definition: particletype.h:242
double mass() const
Definition: particletype.h:144
PdgCode stores a Particle Data Group Particle Numbering Scheme particle type number.
Definition: pdgcode.h:110
#define SMASH_SOURCE_LOCATION
Hackery that is required to output the location in the source code where the log statement occurs.
Definition: logging.h:150
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
std::unique_ptr< ExperimentBase > experiment(Configuration c)
Create an experiment given an input configuration.
Definition: setup.h:162
void ignore_simulation_config_values(Configuration &configuration)
Remove all config values that are only needed for simulations.
Definition: smash.cc:335
ScatterActionsFinder actions_finder_for_dump(Configuration &configuration)
Prepares ActionsFinder for cross-section and reaction dumps.
Definition: smash.cc:312
void usage(const int rc, const std::string &progname)
Prints usage information and exits the program.
Definition: smash.cc:131
void ensure_path_is_valid(const std::filesystem::path &path)
Ensures the output path is valid.
Definition: smash.cc:290
void check_for_unused_config_values(const Configuration &configuration)
Checks if there are unused config values.
Definition: smash.cc:321
void print_disclaimer()
Print the disclaimer.
Definition: smash.cc:178
std::filesystem::path default_output_path()
Definition: smash.cc:266
int64_t generate_63bit_seed()
Generates a seed with a truly random 63-bit value, if possible.
Definition: random.cc:20
std::string fill_left(const std::string &s, size_t width, char fill=' ')
Fill string with characters to the left until the given width is reached.
Definition: action.h:24
std::vector< std::string > split(const std::string &s, char delim)
Split string by delimiter.
void initialize_particles_decays_and_tabulations(Configuration &configuration, const std::string &version, const std::string &tabulations_dir={})
Initialize the particles and decays from the given configuration, plus tabulate the resonance integra...
Definition: library.cc:45
Configuration setup_config_and_logging(const std::string &config_file, const std::string &particles_file={}, const std::string &decaymodes_file={}, const std::vector< std::string > &extra_config={})
Set up configuration and logging from input files and extra config.
Definition: library.cc:33
void setup_default_float_traps()
Setup the floating-point traps used throughout SMASH.
static constexpr int LMain
Definition: experiment.h:88