15 #include <boost/filesystem/fstream.hpp> 26 #include "smash/config.h" 42 void usage(
const int rc,
const std::string &progname) {
117 std::printf(
"\nUsage: %s [option]\n\n", progname.c_str());
119 " -h, --help usage information\n" 121 " -i, --inputfile <file> path to input configuration file\n" 122 " (default: ./config.yaml)\n" 123 " -d, --decaymodes <file> override default decay modes from file\n" 124 " -p, --particles <file> override default particles from file\n" 126 " -c, --config <YAML> specify config value overrides\n" 127 " (multiple -c arguments are supported)\n" 128 " -m, --modus <modus> shortcut for -c 'General: { Modus: <modus> " 130 " -e, --endtime <time> shortcut for -c 'General: { End_Time: <time> " 134 " -o, --output <dir> output directory (default: ./data/<runid>)\n" 135 " -l, --list-2-to-n list all possible 2->n reactions (with n>1)\n" 136 " -r, --resonance <pdg> dump width(m) and m*spectral function(m^2)" 137 " for resonance pdg\n" 138 " -s, --cross-sections <pdg1>,<pdg2>[,mass1,mass2] \n" 139 " dump all partial cross-sections of " 140 "pdg1 + pdg2 reactions versus sqrt(s).\n" 141 " -S, --cross-sections-fs <pdg1>,<pdg2>[,mass1,mass2] \n" 142 " dump all partial final-state cross-sections " 143 "of pdg1 + pdg2 reactions versus sqrt(s). Non-deterministic if strings " 145 " Masses are optional, by default pole masses" 147 " Note the required comma and no spaces.\n" 148 " -f, --force force overwriting files in the output " 151 " -v, --version\n\n");
158 <<
"###################################################################" 167 <<
" mss'.. ...s'm. sSA##As mAhh##hsh##s. .hA##ASa sS###As " 169 <<
" :a':'. .'':as sM#' .HHm''HMS''AMs mMA' .AMs aMA. " 171 <<
" .a:s'. ..''ss 'h#H#S. mMm 'M#' .HH. 'MH. :MA 'h#H#S. " 173 <<
" .::ss'. .... 'SMm .HH. SMa hMm sM#..mHMs 'AMa " 175 <<
" .s::' #SMASHh aMS .MH: HM: #MMMmMM. #SMASHh " 178 <<
"###################################################################" 181 <<
" This is SMASH version: " << VERSION_MAJOR <<
"\n" 182 <<
" Simulating Many Accelerated Strongly-interacting Hadrons" 185 <<
" Distributed under the GNU General Public License 3.0" 186 <<
" (GPLv3 or later)." 188 <<
" See LICENSE for details." 190 <<
" For the full list of contributors see AUTHORS." 193 <<
" When using SMASH, please cite" 195 <<
" J. Weil et al., Phys.Rev. C94 (2016) no.5, 054905" 197 <<
" and in addition, if Pythia is used please cite" 199 <<
" T. Sjöstrand, S. Mrenna and P. Skands, JHEP05 (2006) 026," 201 <<
" Comput. Phys. Comm. 178 (2008) 852." 204 <<
" Webpage: https://smash-transport.github.io" 207 <<
" Report issues at https://github.com/smash-transport/smash" 209 <<
" or contact us by email at elfner@th.physik.uni-frankfurt.de" 212 <<
"###################################################################" 224 using std::runtime_error::runtime_error;
233 using std::runtime_error::runtime_error;
238 const bf::path
p = bf::absolute(
"data");
239 if (!bf::exists(
p)) {
243 for (
int id = 0; id < std::numeric_limits<int>::max(); ++id) {
244 p2 =
p / std::to_string(
id);
245 if (!bf::exists(p2)) {
262 if (bf::exists(path)) {
263 if (!bf::is_directory(path)) {
265 ") exists, but it is not a directory.");
268 if (!bf::create_directories(path)) {
270 "Race condition detected: The directory " + path.native() +
271 " did not exist a few cycles ago, but was created in the meantime by " 272 "a different process.");
284 std::vector<bool> nucleon_has_interacted = {};
299 const std::string smash_version =
"1.5";
300 const std::set<std::string> compatible_config_versions = {
"1.5"};
304 if (compatible_config_versions.find(config_version) ==
305 compatible_config_versions.end()) {
306 std::stringstream err;
307 err <<
"The version of the configuration file (" << config_version
308 <<
") is not compatible with the SMASH version (" << smash_version
309 <<
").\nThe following config versions are supported:\n";
310 for (
auto it : compatible_config_versions) {
313 err <<
"\nPlease consider updating your config or using a compatible SMASH" 315 throw std::runtime_error(err.str());
333 int main(
int argc,
char *argv[]) {
334 using namespace smash;
336 const auto &log = logger<LogArea::Main>();
338 constexpr option longopts[] = {
339 {
"config", required_argument, 0,
'c'},
340 {
"decaymodes", required_argument, 0,
'd'},
341 {
"endtime", required_argument, 0,
'e'},
342 {
"force", no_argument, 0,
'f'},
343 {
"help", no_argument, 0,
'h'},
344 {
"inputfile", required_argument, 0,
'i'},
345 {
"modus", required_argument, 0,
'm'},
346 {
"particles", required_argument, 0,
'p'},
347 {
"output", required_argument, 0,
'o'},
348 {
"list-2-to-n", no_argument, 0,
'l'},
349 {
"resonance", required_argument, 0,
'r'},
350 {
"cross-sections", required_argument, 0,
's'},
351 {
"cross-sections-fs", required_argument, 0,
'S'},
352 {
"version", no_argument, 0,
'v'},
356 const std::string progname = bf::path(argv[0]).filename().native();
359 bool force_overwrite =
false;
361 std::vector<std::string> extra_config;
362 char *particles =
nullptr, *decaymodes =
nullptr, *modus =
nullptr,
363 *end_time =
nullptr, *pdg_string =
nullptr, *cs_string =
nullptr;
364 bool list2n_activated =
false;
365 bool resonance_dump_activated =
false;
366 bool cross_section_dump_activated =
false;
367 bool final_state_cross_sections =
false;
371 bool suppress_disclaimer =
false;
372 while ((opt = getopt_long(argc, argv,
"c:d:e:fhi:m:p:o:lr:s:S:v", longopts,
376 extra_config.emplace_back(optarg);
382 force_overwrite =
true;
388 usage(EXIT_SUCCESS, progname);
400 output_path = optarg;
403 list2n_activated =
true;
404 suppress_disclaimer =
true;
407 resonance_dump_activated =
true;
409 suppress_disclaimer =
true;
412 final_state_cross_sections =
true;
415 cross_section_dump_activated =
true;
417 suppress_disclaimer =
true;
422 "Branch : %s\nSystem : %s\nCompiler : %s %s\n" 423 "Build : %s\nDate : %s\n",
424 VERSION_MAJOR, GIT_BRANCH, CMAKE_SYSTEM, CMAKE_CXX_COMPILER_ID,
425 CMAKE_CXX_COMPILER_VERSION, CMAKE_BUILD_TYPE, BUILD_DATE);
426 std::exit(EXIT_SUCCESS);
428 usage(EXIT_FAILURE, progname);
434 std::cout << argv[0] <<
": invalid argument -- '" << argv[optind]
436 usage(EXIT_FAILURE, progname);
439 if (!suppress_disclaimer) {
447 input_path.filename());
448 for (
const auto &config : extra_config) {
456 if (!bf::exists(particles)) {
457 std::stringstream err;
458 err <<
"The particles file was expected at '" << particles
459 <<
"', but the file does not exist.";
460 throw std::runtime_error(err.str());
462 std::string particle_string =
read_all(bf::ifstream{particles});
464 std::stringstream err;
465 err <<
"The particles file has CR LF line endings. Please use LF" 467 throw std::runtime_error(err.str());
472 if (!bf::exists(decaymodes)) {
473 std::stringstream err;
474 err <<
"The decay modes file was expected at '" << decaymodes
475 <<
"', but the file does not exist.";
476 throw std::runtime_error(err.str());
478 std::string decay_string =
read_all(bf::ifstream{decaymodes});
480 std::stringstream err;
481 err <<
"The decay mode file has CR LF line endings. Please use LF" 483 throw std::runtime_error(err.str());
487 if (list2n_activated) {
495 scat_finder.dump_reactions();
496 std::exit(EXIT_SUCCESS);
498 if (resonance_dump_activated) {
505 std::exit(EXIT_SUCCESS);
507 if (cross_section_dump_activated) {
511 std::string arg_string(cs_string);
512 std::vector<std::string> args =
split(arg_string,
',');
513 const unsigned int n_arg = args.size();
514 if (n_arg < 2 || n_arg > 4) {
515 throw std::invalid_argument(
"-s usage: pdg1,pdg2[,m1][,m2]");
517 PdgCode pdg_a(args[0]), pdg_b(args[1]);
520 for (
unsigned int i = 0; i < 4 - n_arg; i++) {
523 double ma = (args[2] ==
"") ? a.
mass() : std::stod(args[2]);
524 double mb = (args[3] ==
"") ? b.
mass() : std::stod(args[3]);
527 std::cout <<
"Warning: pole mass is used for stable particle " 528 << a.
name() <<
" instead of " << args[2] << std::endl;
532 std::cout <<
"Warning: pole mass is used for stable particle " 533 << b.
name() <<
" instead of " << args[3] << std::endl;
536 scat_finder.dump_cross_sections(a, b, ma, mb, final_state_cross_sections);
537 std::exit(EXIT_SUCCESS);
543 configuration[
"General"][
"End_Time"] = std::abs(std::atof(end_time));
554 std::random_device rd;
555 static_assert(std::is_same<decltype(rd()), uint32_t>::value,
556 "random_device is assumed to generate uint32_t");
557 uint64_t unsigned_seed =
558 (
static_cast<uint64_t
>(rd()) << 32) |
static_cast<uint64_t
>(rd());
560 seed =
static_cast<int64_t
>(unsigned_seed >> 1);
566 const bf::path lock_path = output_path /
"smash.lock";
569 throw std::runtime_error(
570 "Another instance of SMASH is already writing to the specified " 571 "output directory. If you are sure this is not the case, remove \"" +
572 lock_path.native() +
"\".");
574 log.debug(
"output path: ", output_path);
575 if (!force_overwrite && bf::exists(output_path /
"config.yaml")) {
576 throw std::runtime_error(
577 "Output directory would get overwritten. Select a different output " 578 "directory, clean up, or tell SMASH to ignore existing files.");
583 bf::ofstream(output_path /
"config.yaml")
584 <<
"# " << VERSION_MAJOR <<
'\n' 585 <<
"# Branch : " << GIT_BRANCH <<
'\n' 586 <<
"# System : " << CMAKE_SYSTEM <<
'\n' 587 <<
"# Compiler : " << CMAKE_CXX_COMPILER_ID <<
' ' 588 << CMAKE_CXX_COMPILER_VERSION <<
'\n' 589 <<
"# Build : " << CMAKE_BUILD_TYPE <<
'\n' 590 <<
"# Date : " << BUILD_DATE <<
'\n' 607 if (report !=
"{}") {
608 throw std::runtime_error(
609 "The following configuration values were not used:\n" + report);
615 }
catch (std::exception &e) {
616 log.fatal() <<
"SMASH failed with the following error:\n" << e.what();
Value read(std::initializer_list< const char *> keys) const
Additional interface for SMASH to read configuration values without removing them.
int main(int argc, char *argv[])
Main program Smashes Many Accelerated Strongly-Interacting Hadrons :-)
std::string unused_values_report() const
Returns a string listing the key/value pairs that have not been taken yet.
Configuration configuration(std::string overrides={})
Return a configuration object filled with data from src/config.yaml.
Exception class that is thrown, if the requested output directory already exists and -f was not speci...
bool acquire()
Try to acquire the file lock.
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.
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.
static void load_decaymodes(const std::string &input)
Loads the DecayModes map as described in the input string.
void dump_width_and_spectral_function() const
Prints out width and spectral function versus mass to the standard output.
void ensure_path_is_valid(const bf::path &path)
Ensures the output path is valid.
std::vector< std::string > split(const std::string &s, char delim)
Split string by delimiter.
Interface to the SMASH configuration files.
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 const ParticleType & find(PdgCode pdgcode)
Returns the ParticleType object for the given pdgcode.
bf::path default_output_path()
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 ...
#define source_location
Hackery that is required to output the location in the source code where the log statement occurs...
Guard to create a file lock.
Particle type contains the static properties of a particle species.
A simple scatter finder: Just loops through all particles and checks each pair for a collision...
void print_disclaimer()
Print the disclaimer.
PdgCode stores a Particle Data Group Particle Numbering Scheme particle type number.
static void create_type_list(const std::string &particles)
Initialize the global ParticleType list (list_all) from the given input data.
bool has_crlf_line_ending(const std::string in)
Check if a line in the string ends with \r\n.
void set_default_loglevel(einhard::LogLevel level)
Set the default log level (what will be returned from subsequent default_loglevel calls)...
Exception class that is thrown, if no new output path can be generated (there is a directory name for...
Value take(std::initializer_list< const char *> keys)
The default interface for SMASH to read configuration values.
std::unique_ptr< ExperimentBase > experiment(const Configuration &c=configuration())
Create an experiment.
Helper structure for Experiment.
std::string to_string() const
Returns a YAML string of the current tree.
const std::string & name() const
std::string read_all(std::istream &&input)
Utility function to read a complete input stream (e.g.