25 #include "smash/config.h"
131 void usage(
const int rc,
const std::string &progname) {
132 std::printf(
"\nUsage: %s [option]\n\n", progname.c_str());
134 " -h, --help usage information\n"
136 " -i, --inputfile <file> path to input configuration file\n"
137 " (default: ./config.yaml)\n"
138 " -d, --decaymodes <file> override default decay modes from file\n"
139 " -p, --particles <file> override default particles from file\n"
141 " -c, --config <YAML> specify config value overrides\n"
142 " (multiple -c arguments are supported)\n"
143 " -m, --modus <modus> shortcut for -c 'General: { Modus: <modus> "
145 " -e, --endtime <time> shortcut for -c 'General: { End_Time: <time> "
149 " -o, --output <dir> output directory (default: ./data/<runid>)\n"
150 " -l, --list-2-to-n list all possible 2->n reactions (with n>1)\n"
151 " -r, --resonance <pdg> dump width(m) and m*spectral function(m^2)"
152 " for resonance pdg\n"
153 " -s, --cross-sections <pdg1>,<pdg2>[,mass1,mass2[,plab1,...]] \n"
154 " dump all partial cross-sections of "
155 "pdg1 + pdg2 reactions versus sqrt(s).\n"
156 " -S, --cross-sections-fs <pdg1>,<pdg2>[,mass1,mass2[,plab1,...]] \n"
157 " dump an approximation of the final-state"
159 " of pdg1 + pdg2 reactions versus sqrt(s).\n"
160 " Contributions from strings are not considered"
161 " for the final state.\n"
162 " Masses are optional, by default pole masses"
164 " Note the required comma and no spaces.\n"
165 " -f, --force force overwriting files in the output "
168 " -x, --dump_iSS Dump particle table in iSS format\n"
169 " This format is used in MUSIC and CLVisc\n"
170 " relativistic hydro codes\n"
171 " -q, --quiet Supress disclaimer print-out\n"
172 " -n, --no-cache Don't cache integrals on disk\n"
173 " -v, --version\n\n");
180 <<
"###################################################################"
189 <<
" mss'.. ...s'm. sSA##As mAhh##hsh##s. .hA##ASa sS###As "
191 <<
" :a':'. .'':as sM#' .HHm''HMS''AMs mMA' .AMs aMA. "
193 <<
" .a:s'. ..''ss 'h#H#S. mMm 'M#' .HH. 'MH. :MA 'h#H#S. "
195 <<
" .::ss'. .... 'SMm .HH. SMa hMm sM#..mHMs 'AMa "
197 <<
" .s::' #SMASHh aMS .MH: HM: #MMMmMM. #SMASHh "
200 <<
"###################################################################"
203 <<
" This is SMASH version: " << SMASH_VERSION <<
"\n"
204 <<
" Simulating Many Accelerated Strongly-interacting Hadrons"
207 <<
" Distributed under the GNU General Public License 3.0"
208 <<
" (GPLv3 or later)."
210 <<
" See LICENSE for details."
212 <<
" For the full list of contributors see the AUTHORS.md file."
215 <<
" When using SMASH, please cite"
217 <<
" J. Weil et al., Phys.Rev. C94 (2016) no.5, 054905"
219 <<
" together with the software DOI for the specific code version "
222 <<
" https://doi.org/10.5281/zenodo.3484711."
224 <<
" In addition, if Pythia is used please cite"
226 <<
" C. Bierlich et al, SciPost Phys. Codebases 8 (2022)"
228 <<
" together with the Codebase release you used:"
230 <<
" https://doi.org/10.21468/SciPostPhysCodeb.8-r8.3."
233 <<
" Webpage: https://smash-transport.github.io"
236 <<
" Report issues at https://github.com/smash-transport/smash"
238 <<
" or contact us by email at elfner@itp.uni-frankfurt.de"
241 <<
"###################################################################"
253 using std::runtime_error::runtime_error;
262 using std::runtime_error::runtime_error;
267 const std::filesystem::path
p = std::filesystem::absolute(
"data");
268 if (!std::filesystem::exists(
p)) {
271 std::filesystem::path p2;
272 for (
int id = 0; id < std::numeric_limits<int>::max(); ++id) {
273 p2 =
p / std::to_string(
id);
274 if (!std::filesystem::exists(p2)) {
291 if (std::filesystem::exists(path)) {
292 if (!std::filesystem::is_directory(path)) {
294 ") exists, but it is not a directory.");
297 if (!std::filesystem::create_directories(path)) {
299 "Race condition detected: The directory " + path.native() +
300 " did not exist a few cycles ago, but was created in the meantime by "
301 "a different process.");
323 throw std::runtime_error(
324 "The following configuration values were not used:\n" +
336 for (
const std::string s :
337 {
"particles",
"decaymodes",
"Modi",
"General",
"Output",
"Lattice",
338 "Potentials",
"Forced_Thermalization"}) {
339 if (configuration.
has_value({s.c_str()})) {
340 configuration.
take({s.c_str()});
359 int main(
int argc,
char *argv[]) {
360 using namespace smash;
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'},
383 const std::string progname =
384 std::filesystem::path(argv[0]).filename().native();
387 bool force_overwrite =
false;
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;
403 while ((opt = getopt_long(argc, argv,
"c:d:e:fhi:m:p:o:lr:s:S:xvnq",
404 longopts,
nullptr)) != -1) {
407 extra_config.emplace_back(optarg);
413 force_overwrite =
true;
419 usage(EXIT_SUCCESS, progname);
431 output_path = optarg;
434 list2n_activated =
true;
435 suppress_disclaimer =
true;
438 resonance_dump_activated =
true;
440 suppress_disclaimer =
true;
443 final_state_cross_sections =
true;
446 cross_section_dump_activated =
true;
448 suppress_disclaimer =
true;
451 particles_dump_iSS_format =
true;
452 suppress_disclaimer =
true;
460 "System : %s\nCompiler : %s %s\n"
461 "Build : %s\nDate : %s\n",
466 CMAKE_SYSTEM, CMAKE_CXX_COMPILER_ID, CMAKE_CXX_COMPILER_VERSION,
467 CMAKE_BUILD_TYPE, BUILD_DATE);
468 std::exit(EXIT_SUCCESS);
470 cache_integrals =
false;
473 suppress_disclaimer =
true;
476 usage(EXIT_FAILURE, progname);
482 std::cout << argv[0] <<
": invalid argument -- '" << argv[optind]
484 usage(EXIT_FAILURE, progname);
487 if (!suppress_disclaimer) {
492 decaymodes, extra_config);
498 std::string tabulations_path;
499 if (cache_integrals) {
500 tabulations_path = output_path.has_parent_path()
501 ? output_path.parent_path().string()
503 tabulations_path +=
"/tabulations";
505 tabulations_path =
"";
507 const std::string version(SMASH_VERSION);
509 if (list2n_activated) {
512 configuration.merge_yaml(
"{Collision_Term: {Two_to_One: False}}");
520 scat_finder.dump_reactions();
521 std::exit(EXIT_SUCCESS);
523 if (particles_dump_iSS_format) {
526 ParticleTypePtrList list;
529 list.push_back(&ptype);
531 std::sort(list.begin(), list.end(),
533 return a->mass() < b->mass();
536 if (ptype->pdgcode().is_lepton() || ptype->baryon_number() < 0) {
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(),
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);
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);
564 std::exit(EXIT_SUCCESS);
566 if (resonance_dump_activated) {
577 std::exit(EXIT_SUCCESS);
579 if (cross_section_dump_activated) {
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,...]]");
588 PdgCode pdg_a(args[0]), pdg_b(args[1]);
592 for (
unsigned int i = 0; i < 4 - n_arg; i++) {
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()) {
600 std::cerr <<
"Warning: pole mass is used for stable particle "
601 << a.
name() <<
" instead of " << args[2] << std::endl;
603 if (b.
is_stable() && args[3] !=
"" && std::stod(args[3]) != b.
mass()) {
605 std::cerr <<
"Warning: pole mass is used for stable particle "
606 << b.
name() <<
" instead of " << args[3] << std::endl;
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)));
619 scat_finder.dump_cross_sections(a, b, ma, mb, final_state_cross_sections,
621 std::exit(EXIT_SUCCESS);
624 configuration.set_value({
"General",
"Modus"}, std::string(modus));
627 configuration.set_value({
"General",
"End_Time"},
628 std::abs(std::atof(end_time)));
631 int64_t seed = configuration.read({
"General",
"Randomseed"});
633 configuration.set_value({
"General",
"Randomseed"},
638 const std::filesystem::path lock_path = output_path /
"smash.lock";
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() +
"\".");
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.");
656 std::ofstream(output_path /
"config.yaml")
657 <<
"# " << SMASH_VERSION <<
'\n'
659 <<
"# Branch : " << GIT_BRANCH <<
'\n'
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';
676 if (configuration.has_value({
"Version"})) {
677 configuration.take({
"Version"});
684 }
catch (std::exception &e) {
685 logg[
LMain].fatal() <<
"SMASH failed with the following error:\n"
Interface to the SMASH configuration files.
bool has_value(std::initializer_list< const char * > keys) const
Return whether there is a non-empty value behind the requested keys.
std::string to_string() const
Return a string of the current YAML tree.
Value take(std::initializer_list< const char * > keys)
The default interface for SMASH to read configuration values.
static std::unique_ptr< ExperimentBase > create(Configuration &config, const std::filesystem::path &output_path)
Factory method that creates and initializes a new Experiment<Modus>.
Guard to create a file lock.
bool acquire()
Try to acquire the file lock.
A pointer-like interface to global references to ParticleType objects.
Particle type contains the static properties of a particle species.
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.
const std::string & name() const
static const ParticleTypeList & list_all()
PdgCode stores a Particle Data Group Particle Numbering Scheme particle type number.
A simple scatter finder: Just loops through all particles and checks each pair for a collision.
#define SMASH_SOURCE_LOCATION
Hackery that is required to output the location in the source code where the log statement occurs.
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
std::unique_ptr< ExperimentBase > experiment(Configuration c)
Create an experiment given an input configuration.
void ignore_simulation_config_values(Configuration &configuration)
Remove all config values that are only needed for simulations.
ScatterActionsFinder actions_finder_for_dump(Configuration &configuration)
Prepares ActionsFinder for cross-section and reaction dumps.
void usage(const int rc, const std::string &progname)
Prints usage information and exits the program.
void ensure_path_is_valid(const std::filesystem::path &path)
Ensures the output path is valid.
void check_for_unused_config_values(const Configuration &configuration)
Checks if there are unused config values.
void print_disclaimer()
Print the disclaimer.
std::filesystem::path default_output_path()
int64_t generate_63bit_seed()
Generates a seed with a truly random 63-bit value, if possible.
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.
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...
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.
ExperimentParameters create_experiment_parameters(Configuration &config)
Gathers all general Experiment parameters.
void setup_default_float_traps()
Setup the floating-point traps used throughout SMASH.
static constexpr int LMain
int main(int argc, char *argv[])
Main program Smashes Many Accelerated Strongly-Interacting Hadrons :-)
Helper structure for Experiment.
std::optional< bool > use_monash_tune_default
Bool for the default usage of the monash tune in the collider modus.
Exception class that is thrown, if the requested output directory already exists and -f was not speci...
Exception class that is thrown, if no new output path can be generated (there is a directory name for...