15 #include <boost/filesystem/fstream.hpp>
27 #include "smash/config.h"
43 void usage(
const int rc,
const std::string &progname) {
131 std::printf(
"\nUsage: %s [option]\n\n", progname.c_str());
133 " -h, --help usage information\n"
135 " -i, --inputfile <file> path to input configuration file\n"
136 " (default: ./config.yaml)\n"
137 " -d, --decaymodes <file> override default decay modes from file\n"
138 " -p, --particles <file> override default particles from file\n"
140 " -c, --config <YAML> specify config value overrides\n"
141 " (multiple -c arguments are supported)\n"
142 " -m, --modus <modus> shortcut for -c 'General: { Modus: <modus> "
144 " -e, --endtime <time> shortcut for -c 'General: { End_Time: <time> "
148 " -o, --output <dir> output directory (default: ./data/<runid>)\n"
149 " -l, --list-2-to-n list all possible 2->n reactions (with n>1)\n"
150 " -r, --resonance <pdg> dump width(m) and m*spectral function(m^2)"
151 " for resonance pdg\n"
152 " -s, --cross-sections <pdg1>,<pdg2>[,mass1,mass2[,plab1,...]] \n"
153 " dump all partial cross-sections of "
154 "pdg1 + pdg2 reactions versus sqrt(s).\n"
155 " -S, --cross-sections-fs <pdg1>,<pdg2>[,mass1,mass2[,plab1,...]] \n"
156 " dump an approximation of the final-state"
158 " of pdg1 + pdg2 reactions versus sqrt(s).\n"
159 " Contributions from strings are not considered"
160 " for the final state.\n"
161 " Masses are optional, by default pole masses"
163 " Note the required comma and no spaces.\n"
164 " -f, --force force overwriting files in the output "
167 " -x, --dump_iSS Dump particle table in iSS format\n"
168 " This format is used in MUSIC and CLVisc\n"
169 " relativistic hydro codes\n"
170 " -q, --quiet Supress disclaimer print-out\n"
171 " -n, --no-cache Don't cache integrals on disk\n"
172 " -v, --version\n\n");
179 <<
"###################################################################"
188 <<
" mss'.. ...s'm. sSA##As mAhh##hsh##s. .hA##ASa sS###As "
190 <<
" :a':'. .'':as sM#' .HHm''HMS''AMs mMA' .AMs aMA. "
192 <<
" .a:s'. ..''ss 'h#H#S. mMm 'M#' .HH. 'MH. :MA 'h#H#S. "
194 <<
" .::ss'. .... 'SMm .HH. SMa hMm sM#..mHMs 'AMa "
196 <<
" .s::' #SMASHh aMS .MH: HM: #MMMmMM. #SMASHh "
199 <<
"###################################################################"
202 <<
" This is SMASH version: " << VERSION_MAJOR <<
"\n"
203 <<
" Simulating Many Accelerated Strongly-interacting Hadrons"
206 <<
" Distributed under the GNU General Public License 3.0"
207 <<
" (GPLv3 or later)."
209 <<
" See LICENSE for details."
211 <<
" For the full list of contributors see AUTHORS."
214 <<
" When using SMASH, please cite"
216 <<
" J. Weil et al., Phys.Rev. C94 (2016) no.5, 054905"
218 <<
" together with the software DOI for the specific code version "
221 <<
" https://doi.org/10.5281/zenodo.3484711."
223 <<
" In addition, if Pythia is used please cite"
225 <<
" T. Sjöstrand, S. Mrenna and P. Skands, JHEP05 (2006) 026,"
227 <<
" Comput. Phys. Comm. 178 (2008) 852."
230 <<
" Webpage: https://smash-transport.github.io"
233 <<
" Report issues at https://github.com/smash-transport/smash"
235 <<
" or contact us by email at elfner@itp.uni-frankfurt.de"
238 <<
"###################################################################"
250 using std::runtime_error::runtime_error;
259 using std::runtime_error::runtime_error;
264 const bf::path
p = bf::absolute(
"data");
265 if (!bf::exists(
p)) {
269 for (
int id = 0; id < std::numeric_limits<int>::max(); ++id) {
270 p2 =
p / std::to_string(
id);
271 if (!bf::exists(p2)) {
288 if (bf::exists(path)) {
289 if (!bf::is_directory(path)) {
291 ") exists, but it is not a directory.");
294 if (!bf::create_directories(path)) {
296 "Race condition detected: The directory " + path.native() +
297 " did not exist a few cycles ago, but was created in the meantime by "
298 "a different process.");
312 const std::vector<bool> nucleon_has_interacted = {};
314 const int N_proj = 0;
330 const std::string smash_version =
"1.8";
331 const std::set<std::string> compatible_config_versions = {
"1.8"};
335 if (compatible_config_versions.find(config_version) ==
336 compatible_config_versions.end()) {
337 std::stringstream err;
338 err <<
"The version of the configuration file (" << config_version
339 <<
") is not compatible with the SMASH version (" << smash_version
340 <<
").\nThe following config versions are supported:\n";
341 for (
auto it : compatible_config_versions) {
344 err <<
"\nPlease consider updating your config or using a compatible SMASH"
346 throw std::runtime_error(err.str());
356 if (report !=
"{}") {
357 throw std::runtime_error(
358 "The following configuration values were not used:\n" + report);
369 for (
const std::string s :
370 {
"Version",
"particles",
"decaymodes",
"Modi",
"General",
"Output",
371 "Lattice",
"Potentials",
"Forced_Thermalization"}) {
390 bf::path tabulations_path) {
392 logg[
LMain].info(
"Tabulating cross section integrals...");
410 int main(
int argc,
char *argv[]) {
411 using namespace smash;
413 constexpr option longopts[] = {
414 {
"config", required_argument, 0,
'c'},
415 {
"decaymodes", required_argument, 0,
'd'},
416 {
"endtime", required_argument, 0,
'e'},
417 {
"force", no_argument, 0,
'f'},
418 {
"help", no_argument, 0,
'h'},
419 {
"inputfile", required_argument, 0,
'i'},
420 {
"modus", required_argument, 0,
'm'},
421 {
"particles", required_argument, 0,
'p'},
422 {
"output", required_argument, 0,
'o'},
423 {
"list-2-to-n", no_argument, 0,
'l'},
424 {
"resonance", required_argument, 0,
'r'},
425 {
"cross-sections", required_argument, 0,
's'},
426 {
"cross-sections-fs", required_argument, 0,
'S'},
427 {
"dump-iSS", no_argument, 0,
'x'},
428 {
"version", no_argument, 0,
'v'},
429 {
"no-cache", no_argument, 0,
'n'},
430 {
"quiet", no_argument, 0,
'q'},
434 const std::string progname = bf::path(argv[0]).filename().native();
437 bool force_overwrite =
false;
439 std::vector<std::string> extra_config;
440 char *particles =
nullptr, *decaymodes =
nullptr, *modus =
nullptr,
441 *end_time =
nullptr, *pdg_string =
nullptr, *cs_string =
nullptr;
442 bool list2n_activated =
false;
443 bool resonance_dump_activated =
false;
444 bool cross_section_dump_activated =
false;
445 bool final_state_cross_sections =
false;
446 bool particles_dump_iSS_format =
false;
447 bool cache_integrals =
true;
451 bool suppress_disclaimer =
false;
452 while ((opt = getopt_long(argc, argv,
"c:d:e:fhi:m:p:o:lr:s:S:xvnq",
453 longopts,
nullptr)) != -1) {
456 extra_config.emplace_back(optarg);
462 force_overwrite =
true;
468 usage(EXIT_SUCCESS, progname);
480 output_path = optarg;
483 list2n_activated =
true;
484 suppress_disclaimer =
true;
487 resonance_dump_activated =
true;
489 suppress_disclaimer =
true;
492 final_state_cross_sections =
true;
495 cross_section_dump_activated =
true;
497 suppress_disclaimer =
true;
500 particles_dump_iSS_format =
true;
501 suppress_disclaimer =
true;
506 "Branch : %s\nSystem : %s\nCompiler : %s %s\n"
507 "Build : %s\nDate : %s\n",
508 VERSION_MAJOR, GIT_BRANCH, CMAKE_SYSTEM, CMAKE_CXX_COMPILER_ID,
509 CMAKE_CXX_COMPILER_VERSION, CMAKE_BUILD_TYPE, BUILD_DATE);
510 std::exit(EXIT_SUCCESS);
512 cache_integrals =
false;
515 suppress_disclaimer =
true;
518 usage(EXIT_FAILURE, progname);
524 std::cout << argv[0] <<
": invalid argument -- '" << argv[optind]
526 usage(EXIT_FAILURE, progname);
529 if (!suppress_disclaimer) {
535 input_path.filename());
537 for (
const auto &config : extra_config) {
552 " create ParticleType and DecayModes");
554 auto particles_and_decays =
561 "Ambiguity: particles from external file ", particles,
562 " requested, but there is also particle list in the config."
563 " Using particles from ",
572 "Ambiguity: decaymodes from external file ", decaymodes,
573 " requested, but there is also decaymodes list in the config."
574 " Using decaymodes from",
582 const std::string version(VERSION_MAJOR);
586 hash_context.
update(version);
587 hash_context.
update(particle_string);
588 hash_context.
update(decay_string);
589 const auto hash = hash_context.
finalize();
592 bf::path tabulations_path;
593 if (cache_integrals) {
594 tabulations_path = output_path.parent_path() /
"tabulations";
595 bf::create_directories(tabulations_path);
596 logg[
LMain].info() <<
"Tabulations path: " << tabulations_path;
598 tabulations_path =
"";
600 if (list2n_activated) {
604 logg[
LMain].info() <<
"Tabulations path: " << tabulations_path;
611 scat_finder.dump_reactions();
612 std::exit(EXIT_SUCCESS);
614 if (particles_dump_iSS_format) {
616 ParticleTypePtrList list;
619 list.push_back(&ptype);
621 std::sort(list.begin(), list.end(),
623 return a->mass() < b->mass();
626 if (ptype->pdgcode().is_lepton() || ptype->baryon_number() < 0) {
629 const auto &decay_modes = ptype->decay_modes();
630 const auto &modelist = decay_modes.decay_mode_list();
631 int ndecays = ptype->is_stable() ? 1 : modelist.size();
632 std::printf(
"%13i %s %10.5f %10.5f %5i %5i %5i %5i %5i %5i %5i %5i\n",
633 ptype->pdgcode().get_decimal(),
635 ptype->mass(), ptype->width_at_pole(),
636 ptype->pdgcode().spin_degeneracy(), ptype->baryon_number(),
637 ptype->strangeness(), ptype->pdgcode().charmness(),
638 ptype->pdgcode().bottomness(), ptype->isospin() + 1,
639 ptype->charge(), ndecays);
640 if (!ptype->is_stable()) {
641 for (
const auto &decay : modelist) {
642 auto ptypes = decay->particle_types();
643 std::printf(
"%13i %13i %20.5f %13i %13i %13i %13i %13i\n",
644 ptype->pdgcode().get_decimal(), 2, decay->weight(),
645 ptypes[0]->pdgcode().get_decimal(),
646 ptypes[1]->pdgcode().get_decimal(), 0, 0, 0);
649 std::printf(
"%13i %13i %20.5f %13i %13i %13i %13i %13i\n",
650 ptype->pdgcode().get_decimal(), 1, 1.0,
651 ptype->pdgcode().get_decimal(), 0, 0, 0, 0);
654 std::exit(EXIT_SUCCESS);
656 if (resonance_dump_activated) {
666 std::exit(EXIT_SUCCESS);
668 if (cross_section_dump_activated) {
670 std::string arg_string(cs_string);
671 std::vector<std::string> args =
split(arg_string,
',');
672 const unsigned int n_arg = args.size();
673 if (n_arg != 2 && n_arg != 4 && n_arg < 5) {
674 throw std::invalid_argument(
"-s usage: pdg1,pdg2[,m1,m2[,sqrts1,...]]");
676 PdgCode pdg_a(args[0]), pdg_b(args[1]);
680 for (
unsigned int i = 0; i < 4 - n_arg; i++) {
684 double ma = (args[2] ==
"") ? a.
mass() : std::stod(args[2]);
685 double mb = (args[3] ==
"") ? b.
mass() : std::stod(args[3]);
686 if (a.
is_stable() && args[2] !=
"" && std::stod(args[2]) != a.
mass()) {
688 std::cerr <<
"Warning: pole mass is used for stable particle "
689 << a.
name() <<
" instead of " << args[2] << std::endl;
691 if (b.
is_stable() && args[3] !=
"" && std::stod(args[3]) != b.
mass()) {
693 std::cerr <<
"Warning: pole mass is used for stable particle "
694 << b.
name() <<
" instead of " << args[3] << std::endl;
696 const size_t plab_size = n_arg <= 4 ? 0 : n_arg - 4;
697 std::vector<double> plab;
698 plab.reserve(plab_size);
699 for (
size_t i = 4; i < n_arg; i++) {
700 plab.push_back(std::stod(args.at(i)));
707 scat_finder.dump_cross_sections(a, b, ma, mb, final_state_cross_sections,
709 std::exit(EXIT_SUCCESS);
715 configuration[
"General"][
"End_Time"] = std::abs(std::atof(end_time));
725 const bf::path lock_path = output_path /
"smash.lock";
728 throw std::runtime_error(
729 "Another instance of SMASH is already writing to the specified "
730 "output directory. If you are sure this is not the case, remove \"" +
731 lock_path.native() +
"\".");
733 logg[
LMain].debug(
"output path: ", output_path);
734 if (!force_overwrite && bf::exists(output_path /
"config.yaml")) {
735 throw std::runtime_error(
736 "Output directory would get overwritten. Select a different output "
737 "directory, clean up, or tell SMASH to ignore existing files.");
742 bf::ofstream(output_path /
"config.yaml")
743 <<
"# " << VERSION_MAJOR <<
'\n'
744 <<
"# Branch : " << GIT_BRANCH <<
'\n'
745 <<
"# System : " << CMAKE_SYSTEM <<
'\n'
746 <<
"# Compiler : " << CMAKE_CXX_COMPILER_ID <<
' '
747 << CMAKE_CXX_COMPILER_VERSION <<
'\n'
748 <<
"# Build : " << CMAKE_BUILD_TYPE <<
'\n'
749 <<
"# Date : " << BUILD_DATE <<
'\n'
752 " create ParticleType and DecayModes");
767 }
catch (std::exception &e) {
768 logg[
LMain].fatal() <<
"SMASH failed with the following error:\n"