15 #include <boost/filesystem/fstream.hpp> 26 #include "smash/config.h" 42 void usage(
const int rc,
const std::string &progname) {
127 std::printf(
"\nUsage: %s [option]\n\n", progname.c_str());
129 " -h, --help usage information\n" 131 " -i, --inputfile <file> path to input configuration file\n" 132 " (default: ./config.yaml)\n" 133 " -d, --decaymodes <file> override default decay modes from file\n" 134 " -p, --particles <file> override default particles from file\n" 136 " -c, --config <YAML> specify config value overrides\n" 137 " (multiple -c arguments are supported)\n" 138 " -m, --modus <modus> shortcut for -c 'General: { Modus: <modus> " 140 " -e, --endtime <time> shortcut for -c 'General: { End_Time: <time> " 144 " -o, --output <dir> output directory (default: ./data/<runid>)\n" 145 " -l, --list-2-to-n list all possible 2->n reactions (with n>1)\n" 146 " -r, --resonance <pdg> dump width(m) and m*spectral function(m^2)" 147 " for resonance pdg\n" 148 " -s, --cross-sections <pdg1>,<pdg2>[,mass1,mass2[,plab1,...]] \n" 149 " dump all partial cross-sections of " 150 "pdg1 + pdg2 reactions versus sqrt(s).\n" 151 " -S, --cross-sections-fs <pdg1>,<pdg2>[,mass1,mass2[,plab1,...]] \n" 152 " dump an approximation of the final-state" 154 " of pdg1 + pdg2 reactions versus sqrt(s).\n" 155 " Contributions from strings are not considered" 156 " for the final state.\n" 157 " Masses are optional, by default pole masses" 159 " Note the required comma and no spaces.\n" 160 " -f, --force force overwriting files in the output " 163 " -x, --dump_iSS Dump particle table in iSS format\n" 164 " This format is used in MUSIC and CLVisc\n" 165 " relativistic hydro codes\n" 166 " -v, --version\n\n");
173 <<
"###################################################################" 182 <<
" mss'.. ...s'm. sSA##As mAhh##hsh##s. .hA##ASa sS###As " 184 <<
" :a':'. .'':as sM#' .HHm''HMS''AMs mMA' .AMs aMA. " 186 <<
" .a:s'. ..''ss 'h#H#S. mMm 'M#' .HH. 'MH. :MA 'h#H#S. " 188 <<
" .::ss'. .... 'SMm .HH. SMa hMm sM#..mHMs 'AMa " 190 <<
" .s::' #SMASHh aMS .MH: HM: #MMMmMM. #SMASHh " 193 <<
"###################################################################" 196 <<
" This is SMASH version: " << VERSION_MAJOR <<
"\n" 197 <<
" Simulating Many Accelerated Strongly-interacting Hadrons" 200 <<
" Distributed under the GNU General Public License 3.0" 201 <<
" (GPLv3 or later)." 203 <<
" See LICENSE for details." 205 <<
" For the full list of contributors see AUTHORS." 208 <<
" When using SMASH, please cite" 210 <<
" J. Weil et al., Phys.Rev. C94 (2016) no.5, 054905" 212 <<
" and in addition, if Pythia is used please cite" 214 <<
" T. Sjöstrand, S. Mrenna and P. Skands, JHEP05 (2006) 026," 216 <<
" Comput. Phys. Comm. 178 (2008) 852." 219 <<
" Webpage: https://smash-transport.github.io" 222 <<
" Report issues at https://github.com/smash-transport/smash" 224 <<
" or contact us by email at elfner@th.physik.uni-frankfurt.de" 227 <<
"###################################################################" 239 using std::runtime_error::runtime_error;
248 using std::runtime_error::runtime_error;
253 const bf::path
p = bf::absolute(
"data");
254 if (!bf::exists(p)) {
258 for (
int id = 0; id < std::numeric_limits<int>::max(); ++id) {
259 p2 = p / std::to_string(
id);
260 if (!bf::exists(p2)) {
277 if (bf::exists(path)) {
278 if (!bf::is_directory(path)) {
280 ") exists, but it is not a directory.");
283 if (!bf::create_directories(path)) {
285 "Race condition detected: The directory " + path.native() +
286 " did not exist a few cycles ago, but was created in the meantime by " 287 "a different process.");
301 const std::vector<bool> nucleon_has_interacted = {};
303 const int N_proj = 0;
319 const std::string smash_version =
"1.7";
320 const std::set<std::string> compatible_config_versions = {
"1.7"};
322 const std::string config_version = configuration.
read({
"Version"});
324 if (compatible_config_versions.find(config_version) ==
325 compatible_config_versions.end()) {
326 std::stringstream err;
327 err <<
"The version of the configuration file (" << config_version
328 <<
") is not compatible with the SMASH version (" << smash_version
329 <<
").\nThe following config versions are supported:\n";
330 for (
auto it : compatible_config_versions) {
333 err <<
"\nPlease consider updating your config or using a compatible SMASH" 335 throw std::runtime_error(err.str());
345 if (report !=
"{}") {
346 throw std::runtime_error(
347 "The following configuration values were not used:\n" + report);
358 configuration.
take({
"Version"});
359 configuration.
take({
"particles"});
360 configuration.
take({
"decaymodes"});
361 configuration.
take({
"Modi"});
362 configuration.
take({
"General"});
363 if (configuration.
has_value({
"Output"})) {
364 configuration.
take({
"Output"});
366 if (configuration.
has_value({
"Lattice"})) {
367 configuration.
take({
"Lattice"});
369 if (configuration.
has_value({
"Potentials"})) {
370 configuration.
take({
"Potentials"});
372 if (configuration.
has_value({
"Forced_Thermalization"})) {
373 configuration.
take({
"Forced_Thermalization"});
391 int main(
int argc,
char *argv[]) {
392 using namespace smash;
394 const auto &log = logger<LogArea::Main>();
396 constexpr option longopts[] = {
397 {
"config", required_argument, 0,
'c'},
398 {
"decaymodes", required_argument, 0,
'd'},
399 {
"endtime", required_argument, 0,
'e'},
400 {
"force", no_argument, 0,
'f'},
401 {
"help", no_argument, 0,
'h'},
402 {
"inputfile", required_argument, 0,
'i'},
403 {
"modus", required_argument, 0,
'm'},
404 {
"particles", required_argument, 0,
'p'},
405 {
"output", required_argument, 0,
'o'},
406 {
"list-2-to-n", no_argument, 0,
'l'},
407 {
"resonance", required_argument, 0,
'r'},
408 {
"cross-sections", required_argument, 0,
's'},
409 {
"cross-sections-fs", required_argument, 0,
'S'},
410 {
"dump-iSS", no_argument, 0,
'x'},
411 {
"version", no_argument, 0,
'v'},
415 const std::string progname = bf::path(argv[0]).filename().native();
418 bool force_overwrite =
false;
420 std::vector<std::string> extra_config;
421 char *particles =
nullptr, *decaymodes =
nullptr, *modus =
nullptr,
422 *end_time =
nullptr, *pdg_string =
nullptr, *cs_string =
nullptr;
423 bool list2n_activated =
false;
424 bool resonance_dump_activated =
false;
425 bool cross_section_dump_activated =
false;
426 bool final_state_cross_sections =
false;
427 bool particles_dump_iSS_format =
false;
431 bool suppress_disclaimer =
false;
432 while ((opt = getopt_long(argc, argv,
"c:d:e:fhi:m:p:o:lr:s:S:xv", longopts,
436 extra_config.emplace_back(optarg);
442 force_overwrite =
true;
448 usage(EXIT_SUCCESS, progname);
460 output_path = optarg;
463 list2n_activated =
true;
464 suppress_disclaimer =
true;
467 resonance_dump_activated =
true;
469 suppress_disclaimer =
true;
472 final_state_cross_sections =
true;
475 cross_section_dump_activated =
true;
477 suppress_disclaimer =
true;
480 particles_dump_iSS_format =
true;
481 suppress_disclaimer =
true;
486 "Branch : %s\nSystem : %s\nCompiler : %s %s\n" 487 "Build : %s\nDate : %s\n",
488 VERSION_MAJOR, GIT_BRANCH, CMAKE_SYSTEM, CMAKE_CXX_COMPILER_ID,
489 CMAKE_CXX_COMPILER_VERSION, CMAKE_BUILD_TYPE, BUILD_DATE);
490 std::exit(EXIT_SUCCESS);
492 usage(EXIT_FAILURE, progname);
498 std::cout << argv[0] <<
": invalid argument -- '" << argv[optind]
500 usage(EXIT_FAILURE, progname);
503 if (!suppress_disclaimer) {
511 input_path.filename());
513 for (
const auto &config : extra_config) {
527 auto particles_and_decays =
533 log.warn(
"Ambiguity: particles from external file ", particles,
534 " requested, but there is also particle list in the config." 535 " Using particles from ",
543 log.warn(
"Ambiguity: decaymodes from external file ", decaymodes,
544 " requested, but there is also decaymodes list in the config." 545 " Using decaymodes from",
555 if (list2n_activated) {
564 scat_finder.dump_reactions();
565 std::exit(EXIT_SUCCESS);
567 if (particles_dump_iSS_format) {
568 ParticleTypePtrList list;
571 list.push_back(&ptype);
573 std::sort(list.begin(), list.end(),
575 return a->
mass() < b->mass();
578 if (ptype->pdgcode().is_lepton() || ptype->baryon_number() < 0) {
581 const auto &decay_modes = ptype->decay_modes();
582 const auto &modelist = decay_modes.decay_mode_list();
583 int ndecays = ptype->is_stable() ? 1 : modelist.size();
584 printf(
"%13i %s %10.5f %10.5f %5i %5i %5i %5i %5i %5i %5i %5i\n",
585 ptype->pdgcode().get_decimal(),
587 ptype->mass(), ptype->width_at_pole(),
588 ptype->pdgcode().spin_degeneracy(), ptype->baryon_number(),
589 ptype->strangeness(), ptype->pdgcode().charmness(),
590 ptype->pdgcode().bottomness(), ptype->isospin() + 1,
591 ptype->charge(), ndecays);
592 if (!ptype->is_stable()) {
593 for (
const auto &decay : modelist) {
594 auto ptypes = decay->particle_types();
595 printf(
"%13i %13i %20.5f %13i %13i %13i %13i %13i\n",
596 ptype->pdgcode().get_decimal(), 2, decay->weight(),
597 ptypes[0]->pdgcode().get_decimal(),
598 ptypes[1]->pdgcode().get_decimal(), 0, 0, 0);
601 printf(
"%13i %13i %20.5f %13i %13i %13i %13i %13i\n",
602 ptype->pdgcode().get_decimal(), 1, 1.0,
603 ptype->pdgcode().get_decimal(), 0, 0, 0, 0);
606 std::exit(EXIT_SUCCESS);
608 if (resonance_dump_activated) {
617 std::exit(EXIT_SUCCESS);
619 if (cross_section_dump_activated) {
620 std::string arg_string(cs_string);
621 std::vector<std::string> args =
split(arg_string,
',');
622 const unsigned int n_arg = args.size();
623 if (n_arg != 2 && n_arg != 4 && n_arg < 5) {
624 throw std::invalid_argument(
"-s usage: pdg1,pdg2[,m1,m2[,sqrts1,...]]");
626 PdgCode pdg_a(args[0]), pdg_b(args[1]);
630 for (
unsigned int i = 0; i < 4 - n_arg; i++) {
634 double ma = (args[2] ==
"") ? a.
mass() : std::stod(args[2]);
635 double mb = (args[3] ==
"") ? b.
mass() : std::stod(args[3]);
636 if (a.
is_stable() && args[2] !=
"" && std::stod(args[2]) != a.
mass()) {
638 std::cerr <<
"Warning: pole mass is used for stable particle " 639 << a.
name() <<
" instead of " << args[2] << std::endl;
641 if (b.
is_stable() && args[3] !=
"" && std::stod(args[3]) != b.
mass()) {
643 std::cerr <<
"Warning: pole mass is used for stable particle " 644 << b.
name() <<
" instead of " << args[3] << std::endl;
646 const size_t plab_size = n_arg <= 4 ? 0 : n_arg - 4;
647 std::vector<double> plab;
648 plab.reserve(plab_size);
649 for (
size_t i = 4; i < n_arg; i++) {
650 plab.push_back(std::stod(args.at(i)));
657 scat_finder.dump_cross_sections(a, b, ma, mb, final_state_cross_sections,
659 std::exit(EXIT_SUCCESS);
665 configuration[
"General"][
"End_Time"] = std::abs(std::atof(end_time));
675 const bf::path lock_path = output_path /
"smash.lock";
678 throw std::runtime_error(
679 "Another instance of SMASH is already writing to the specified " 680 "output directory. If you are sure this is not the case, remove \"" +
681 lock_path.native() +
"\".");
683 log.debug(
"output path: ", output_path);
684 if (!force_overwrite && bf::exists(output_path /
"config.yaml")) {
685 throw std::runtime_error(
686 "Output directory would get overwritten. Select a different output " 687 "directory, clean up, or tell SMASH to ignore existing files.");
692 bf::ofstream(output_path /
"config.yaml")
693 <<
"# " << VERSION_MAJOR <<
'\n' 694 <<
"# Branch : " << GIT_BRANCH <<
'\n' 695 <<
"# System : " << CMAKE_SYSTEM <<
'\n' 696 <<
"# Compiler : " << CMAKE_CXX_COMPILER_ID <<
' ' 697 << CMAKE_CXX_COMPILER_VERSION <<
'\n' 698 <<
"# Build : " << CMAKE_BUILD_TYPE <<
'\n' 699 <<
"# Date : " << BUILD_DATE <<
'\n' 716 }
catch (std::exception &e) {
717 log.fatal() <<
"SMASH failed with the following error:\n" << e.what();
int main(int argc, char *argv[])
Main program Smashes Many Accelerated Strongly-Interacting Hadrons :-)
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.
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.
std::string unused_values_report() const
Returns a string listing the key/value pairs that have not been taken yet.
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.
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.
static void load_decaymodes(const std::string &input)
Loads the DecayModes map as described in the input string.
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.
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.
ExperimentParameters create_experiment_parameters(Configuration config)
Gathers all general Experiment parameters.
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.
bf::path default_output_path()
static const ParticleTypeList & list_all()
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 ...
const std::string & name() const
#define source_location
Hackery that is required to output the location in the source code where the log statement occurs...
Value take(std::initializer_list< const char * > keys)
The default interface for SMASH to read configuration values.
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.
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...
A pointer-like interface to global references to ParticleType objects.
int64_t generate_63bit_seed()
Generates a seed with a truly random 63-bit value, if possible.
void dump_width_and_spectral_function() const
Prints out width and spectral function versus mass to the standard output.
std::unique_ptr< ExperimentBase > experiment(const Configuration &c=configuration())
Create an experiment.
void check_for_unused_config_values(const Configuration &configuration)
Checks if there are unused config values.
Helper structure for Experiment.
void ignore_simulation_config_values(Configuration &configuration)
Remove all config values that are only needed for simulations.