Version: SMASH-3.3
configuration.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2025
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #ifndef SRC_INCLUDE_SMASH_CONFIGURATION_H_
11 #define SRC_INCLUDE_SMASH_CONFIGURATION_H_
12 
13 #include <algorithm>
14 #include <array>
15 #include <exception>
16 #include <filesystem>
17 #include <iostream>
18 #include <map>
19 #include <optional>
20 #include <set>
21 #include <stdexcept>
22 #include <string>
23 #include <utility>
24 #include <vector>
25 
26 #include "yaml-cpp/yaml.h"
27 
28 #include "cxx17compat.h"
29 #include "forwarddeclarations.h"
30 #include "key.h"
31 #include "stringify.h"
32 
33 namespace YAML {
34 
41 template <typename T>
42 struct convert {
50  static Node encode(const T &x) {
51  if constexpr (std::is_convertible_v<T, std::string>) {
52  return Node{static_cast<std::string>(x)};
53  } else {
54  static_assert(smash::has_to_string_v<T>,
55  "Encoding type T to YAML::Node requires an overload of "
56  "smash::to_string(T) to convert T to an std::string.");
57  return Node{smash::to_string(x)};
58  }
59  }
60 
69  static bool decode(const Node &node, T &x) {
70  if (!node.IsScalar()) {
71  return false;
72  } else {
73  x = static_cast<T>(node.Scalar());
74  return true;
75  }
76  }
77 };
78 } // namespace YAML
79 
80 namespace smash {
81 
295  public:
300  struct IncorrectTypeInAssignment : public std::runtime_error {
301  using std::runtime_error::runtime_error;
302  };
307  struct ParseError : public std::runtime_error {
308  using std::runtime_error::runtime_error;
309  };
314  struct FileDoesNotExist : public std::runtime_error {
315  using std::runtime_error::runtime_error;
316  };
321  struct TakeSameKeyTwice : public std::logic_error {
322  using std::logic_error::logic_error;
323  };
324 
328  static const char InitializeFromYAMLString = 'S';
329 
334  enum class GetEmpty { Yes, No };
335 
340  enum class Is { Invalid, Deprecated, Valid };
341 
347  explicit Configuration(const std::filesystem::path &path);
348 
356  explicit Configuration(const std::filesystem::path &path,
357  const std::filesystem::path &filename);
358 
367  explicit Configuration(const char *yaml, const char sflag) {
368  if (sflag == InitializeFromYAMLString) {
369  merge_yaml(yaml);
370  } else {
371  throw std::runtime_error(
372  "Unknown control flag in Configuration constructor"
373  " with a YAML formatted string. Please, use"
374  " Configuration::InitializeFromYAMLString.");
375  }
376  }
377 
378 #ifdef BUILD_TESTS
387  explicit Configuration(const char *yaml) : root_node_(YAML::Load(yaml)) {
388  if (root_node_.IsNull())
389  root_node_ = YAML::Node{YAML::NodeType::Map};
390  }
391 #endif
392 
401  Configuration(const Configuration &) = delete;
409 
424 
431 
441  ~Configuration() noexcept(false);
442 
453  void merge_yaml(const std::string &yaml);
454 
456  std::vector<std::string> list_upmost_nodes();
457 
513  template <typename T>
514  T take(const Key<T> &key) {
515  if (has_value(key)) {
516  // The following return statement converts a Value into T
518  } else if (has_section(key.labels())) {
519  // In this case, if the Key type is a map, we take it, otherwise fails
520  if constexpr (isMap<typename Key<T>::type>::value) {
522  } else {
523  throw std::logic_error(
524  "Key " + std::string{key} + // NOLINT(whitespace/braces)
525  " was taken, but its value is not a map, although there is a "
526  "section in the configuration with its labels.");
527  }
528  } else if (did_key_exist_and_was_it_already_taken(key.labels())) {
529  throw TakeSameKeyTwice("Attempt to take key " +
530  std::string{key} + // NOLINT(whitespace/braces)
531  " twice.");
532  } else {
533  try {
534  /* Note that a key with invalid default value cannot be constructed,
535  hence we do not validate its default value here. */
536  return key.default_value();
537  } catch (std::bad_optional_access &) {
538  throw std::invalid_argument(
539  "Key " + std::string{key} + // NOLINT(whitespace/braces)
540  " without default value taken, but missing in configuration.");
541  }
542  }
543  }
544 
561  template <typename T>
562  T take(const Key<T> &key, T default_value) {
563  if (!key.has_dependent_default()) {
564  throw std::logic_error(
565  "An input Key without dependent default cannot be taken specifying a "
566  "default value! Either define the key as having a dependent default "
567  "or take it without a default value (which is a Key property).");
568  }
569  if (!key.validate(default_value)) {
570  throw std::logic_error("Invalid default value passed when taking " +
571  static_cast<std::string>(key) + " key.");
572  }
573  if (has_value(key)) {
574  return take(key);
575  }
576  return default_value;
577  }
578 
605  template <typename T>
606  T read(const Key<T> &key) const {
607  if (has_value(key)) {
608  // The following return statement converts a Value into T
610  } else if (has_section(key.labels())) {
611  // In this case, if the Key type is a map, we take it, otherwise fails
612  if constexpr (isMap<typename Key<T>::type>::value) {
614  } else {
615  throw std::logic_error(
616  "Key " + std::string{key} + // NOLINT(whitespace/braces)
617  " was read, but its value is not a map, although there is a "
618  "section in the configuration with its labels.");
619  }
620  } else {
621  try {
622  /* Note that a key with invalid default value cannot be constructed,
623  hence we do not validate its default value here. */
624  return key.default_value();
625  } catch (std::bad_optional_access &) {
626  throw std::invalid_argument(
627  "Key " + std::string{key} + // NOLINT(whitespace/braces)
628  " without default value read, but missing in configuration.");
629  }
630  }
631  }
632 
649  template <typename T>
650  T read(const Key<T> &key, T default_value) const {
651  if (!key.has_dependent_default()) {
652  throw std::logic_error(
653  "An input Key without dependent default cannot be read specifying a "
654  "default value! Either define the key as having a dependent default "
655  "or read it without a default value (which is a Key property).");
656  }
657  if (!key.validate(default_value)) {
658  throw std::logic_error("Invalid default value passed when reading " +
659  static_cast<std::string>(key) + " key.");
660  }
661  if (has_value(key)) {
662  return read(key);
663  }
664  return default_value;
665  }
666 
689  template <typename T, typename U = remove_cvref_t<T>,
690  typename std::enable_if_t<std::is_convertible_v<T, U>, bool> = true>
691  void set_value(Key<U> key, T &&value) {
693  {key.labels().begin(), key.labels().end()});
694  node = std::forward<T>(value);
695  }
696 
708  void remove_all_entries_in_section_but_one(const std::string &key,
709  KeyLabels section = {});
710 
731  KeyLabels section, Configuration::GetEmpty empty_if_not_existing =
733 
741  KeyLabels section, Configuration::GetEmpty empty_if_not_existing =
743 
749  void enclose_into_section(KeyLabels section);
750 
759  template <typename T>
760  bool has_key(const Key<T> &key) const {
761  const auto found_node =
762  find_existing_node({key.labels().begin(), key.labels().end()});
763  return found_node.has_value() && !(found_node.value().IsMap());
764  }
765 
773  template <typename T>
774  bool has_value(const Key<T> &key) const {
775  const auto found_node =
776  find_existing_node({key.labels().begin(), key.labels().end()});
777  return found_node.has_value() && !(found_node.value().IsNull()) &&
778  !(found_node.value().IsMap());
779  }
780 
786  bool has_section(const KeyLabels &labels) const {
787  const auto found_node = find_existing_node({labels.begin(), labels.end()});
788  return found_node.has_value() && found_node.value().IsMap();
789  }
790 
795  bool is_empty() const { return root_node_.size() == 0; }
796 
800  std::string to_string() const;
801 
808  void clear() { root_node_.reset(); }
809 
827  Is validate(bool full_validation = true) const;
828 
829  private:
839  class Value {
840  friend class Configuration;
841 
843  const YAML::Node node_;
845  const char *const key_;
846 
853  Value(const YAML::Node &n, const char *key) : node_(n), key_(key) {
854  if (!(n.IsScalar() || n.IsSequence() || n.IsMap())) {
855  std::stringstream err;
856  err << "Configuration value for \"" << key
857  << "\" is missing or invalid";
858  throw std::runtime_error(err.str());
859  }
860  }
861 
862  public:
864  Value(const Value &) = delete;
866  Value &operator=(const Value &) = delete;
867 
876  template <typename T>
877  operator T() const {
878  try {
879  return node_.as<T>();
880  } catch (YAML::TypedBadConversion<T> &e) {
882  "The value for key \"" + std::string(key_) +
883  "\" cannot be converted to the requested type.");
884  }
885  }
886 
892  template <typename T>
893  operator std::vector<T>() const {
894  try {
895  return node_.as<std::vector<T>>();
896  } catch (YAML::TypedBadConversion<T> &e) {
898  "One of the values in the sequence for key \"" + std::string(key_) +
899  "\" failed to convert to the requested type. E.g. [1 2] is a "
900  "sequence of one string \"1 2\" and [1, 2] is a sequence of two "
901  "integers. Often there is just a comma missing in the config "
902  "file.");
903  } catch (YAML::TypedBadConversion<std::vector<T>> &e) {
905  "The value for key \"" + std::string(key_) +
906  "\" cannot be converted to the requested type. A sequence was "
907  "expected but apparently not found.");
908  }
909  }
910 
918  template <typename T, size_t N>
919  operator std::array<T, N>() const {
920  const std::vector<T> vec = operator std::vector<T>();
921  const size_t n_read = vec.size();
922  // Alert if size does not match
923  if (n_read != N) {
924  throw IncorrectTypeInAssignment("Wrong number of values in array \"" +
925  std::string(key_) + "\". Expected " +
926  std::to_string(N) +
927  " values,"
928  " found " +
929  std::to_string(n_read) + ".");
930  }
931  std::array<T, N> arr;
932  std::copy_n(vec.begin(), N, arr.begin());
933  return arr;
934  }
935 
943  operator ReactionsBitSet() const {
944  const std::vector<std::string> v = operator std::vector<std::string>();
945  ReactionsBitSet s;
946  for (const auto &x : v) {
947  if (x == "All") {
948  s.set();
949  break;
950  } else if (x == "Elastic") {
952  } else if (x == "NN_to_NR") {
954  } else if (x == "NN_to_DR") {
956  } else if (x == "KN_to_KN") {
958  } else if (x == "KN_to_KDelta") {
960  } else if (x == "Strangeness_exchange") {
962  } else if (x == "NNbar") {
964  } else if (x == "PiDeuteron_to_NN") {
966  } else if (x == "PiDeuteron_to_pidprime") {
968  } else if (x == "NDeuteron_to_Ndprime") {
970  } else {
972  "The value for key \"" + std::string(key_) +
973  "\" should be \"All\", \"Elastic\", \"NN_to_NR\", \"NN_to_DR\","
974  "\"KN_to_KN\", \"KN_to_KDelta\", \"PiDeuteron_to_NN\", "
975  "\"PiDeuteron_to_pidprime\", \"NDeuteron_to_Ndprime\", "
976  "\"Strangeness_exchange\" or "
977  "\"NNbar\", or any combination of these.");
978  }
979  }
980  return s;
981  }
982 
990  operator MultiParticleReactionsBitSet() const {
991  const std::vector<std::string> v = operator std::vector<std::string>();
993  for (const auto &x : v) {
994  if (x == "All") {
995  s.set();
996  break;
997  } else if (x == "Meson_3to1") {
999  } else if (x == "Deuteron_3to2") {
1001  } else if (x == "NNbar_5to2") {
1003  } else if (x == "A3_Nuclei_4to2") {
1005  } else {
1007  "The value for key \"" + std::string(key_) +
1008  "\" should be \"All\", \"Meson_3to1\", "
1009  "\"Deuteron_3to2\" or \"NNbar_5to2\", "
1010  "\"A3_Nuclei_4to2\", or any combination of "
1011  "these.");
1012  }
1013  }
1014  return s;
1015  }
1016 
1024  operator std::set<ThermodynamicQuantity>() const {
1025  const std::vector<std::string> v = operator std::vector<std::string>();
1026  std::set<ThermodynamicQuantity> s;
1027  for (const auto &x : v) {
1028  if (x == "rho_eckart") {
1030  } else if (x == "tmn") {
1031  s.insert(ThermodynamicQuantity::Tmn);
1032  } else if (x == "tmn_landau") {
1034  } else if (x == "landau_velocity") {
1036  } else if (x == "j_QBS") {
1037  s.insert(ThermodynamicQuantity::j_QBS);
1038  } else {
1040  "The value for key \"" + std::string(key_) +
1041  "\" should be \"rho_eckart\", \"tmn\""
1042  ", \"tmn_landau\", \"landau_velocity\" or \"j_QBS\".");
1043  }
1044  }
1045  return s;
1046  }
1047 
1055  operator CalculationFrame() const {
1056  const std::string s = operator std::string();
1057  if (s == "center of velocity") {
1059  }
1060  if (s == "center of mass") {
1062  }
1063  if (s == "fixed target") {
1065  }
1067  "The value for key \"" + std::string(key_) +
1068  "\" should be \"center of velocity\" or \"center of mass\" "
1069  "or \"fixed target\".");
1070  }
1071 
1079  operator FermiMotion() const {
1080  const std::string s = operator std::string();
1081  if (s == "off") {
1082  return FermiMotion::Off;
1083  }
1084  if (s == "on") {
1085  return FermiMotion::On;
1086  }
1087  if (s == "frozen") {
1088  return FermiMotion::Frozen;
1089  }
1091  "The value for key \"" + std::string(key_) +
1092  "\" should be \"off\" or \"on\" or \"frozen\".");
1093  }
1094 
1102  operator DensityType() const {
1103  const std::string s = operator std::string();
1104  if (s == "hadron") {
1105  return DensityType::Hadron;
1106  }
1107  if (s == "baryon") {
1108  return DensityType::Baryon;
1109  }
1110  if (s == "baryonic isospin") {
1112  }
1113  if (s == "pion") {
1114  return DensityType::Pion;
1115  }
1116  if (s == "total isospin") {
1118  }
1119  if (s == "none") {
1120  return DensityType::None;
1121  }
1122  throw IncorrectTypeInAssignment("The value for key \"" +
1123  std::string(key_) +
1124  "\" should be \"hadron\" or \"baryon\" "
1125  "or \"baryonic isospin\" or \"pion\" "
1126  "or \"none\".");
1127  }
1128 
1136  operator ExpansionMode() const {
1137  const std::string s = operator std::string();
1138  if (s == "NoExpansion") {
1140  }
1141  if (s == "MasslessFRW") {
1143  }
1144  if (s == "MassiveFRW") {
1146  }
1147  if (s == "Exponential") {
1149  }
1151  "The value for key \"" + std::string(key_) +
1152  "\" should be \"NoExpansion\", \"MasslessFRW\"," +
1153  "\"MassiveFRW\" or \"Exponential\".");
1154  }
1155 
1159  operator DerivativesMode() const {
1160  const std::string s = operator std::string();
1161  if (s == "Covariant Gaussian") {
1163  }
1164  if (s == "Finite difference") {
1166  }
1167  if (s == "Off") {
1168  return DerivativesMode::Off;
1169  }
1171  "The value for key \"" + std::string(key_) +
1172  "\" should be \"Covariant Gaussian\", \"Finite difference\"," +
1173  " or \"Off\".");
1174  }
1175 
1179  operator FieldDerivativesMode() const {
1180  const std::string s = operator std::string();
1181  if (s == "Chain Rule") {
1183  }
1184  if (s == "Direct") {
1186  }
1188  "The value for key \"" + std::string(key_) +
1189  "\" should be \"Chain Rule\" or \"Direct\".");
1190  }
1191 
1195  operator SmearingMode() const {
1196  const std::string s = operator std::string();
1197  if (s == "Covariant Gaussian") {
1199  }
1200  if (s == "Discrete") {
1201  return SmearingMode::Discrete;
1202  }
1203  if (s == "Triangular") {
1204  return SmearingMode::Triangular;
1205  }
1207  "The value for key \"" + std::string(key_) +
1208  "\" should be \"Covariant Gaussian\", \"Discrete\"," +
1209  " or \"Triangular\".");
1210  }
1211 
1219  operator TimeStepMode() const {
1220  const std::string s = operator std::string();
1221  if (s == "None") {
1222  return TimeStepMode::None;
1223  }
1224  if (s == "Fixed") {
1225  return TimeStepMode::Fixed;
1226  }
1227  throw IncorrectTypeInAssignment("The value for key \"" +
1228  std::string(key_) +
1229  "\" should be \"None\" or \"Fixed\".");
1230  }
1231 
1239  operator BoxInitialCondition() const {
1240  const std::string s = operator std::string();
1241  if (s == "thermal momenta") {
1243  }
1244  if (s == "thermal momenta quantum") {
1246  }
1247  if (s == "peaked momenta") {
1249  }
1251  "The value for key \"" + std::string(key_) +
1252  "\" should be \"thermal momenta\", \"thermal momenta quantum\", " +
1253  "or \"peaked momenta\".");
1254  }
1255 
1263  operator SphereInitialCondition() const {
1264  const std::string s = operator std::string();
1265  if (s == "thermal momenta") {
1267  }
1268  if (s == "thermal momenta quantum") {
1270  }
1271  if (s == "IC_ES") {
1273  }
1274  if (s == "IC_1M") {
1276  }
1277  if (s == "IC_2M") {
1279  }
1280  if (s == "IC_Massive") {
1282  }
1284  "The value for key \"" + std::string(key_) +
1285  "\" should be \"thermal momenta\", \"thermal momenta quantum\", " +
1286  "\"IC_ES\", \"IC_1M\", \"IC_2M\" or" + "\"IC_Massive\".");
1287  }
1288 
1296  operator NNbarTreatment() const {
1297  const std::string s = operator std::string();
1298  if (s == "no annihilation") {
1300  }
1301  if (s == "resonances") {
1303  }
1304  if (s == "two to five") {
1306  }
1307  if (s == "strings") {
1308  return NNbarTreatment::Strings;
1309  }
1311  "The value for key \"" + std::string(key_) + "\" should be " +
1312  "\"no annihilation\", \"resonances\", \"two to five\" or " +
1313  " \"strings\".");
1314  }
1315 
1323  operator Sampling() const {
1324  const std::string s = operator std::string();
1325  if (s == "quadratic") {
1326  return Sampling::Quadratic;
1327  }
1328  if (s == "custom") {
1329  return Sampling::Custom;
1330  }
1331  if (s == "uniform") {
1332  return Sampling::Uniform;
1333  }
1335  "The value for key \"" + std::string(key_) +
1336  "\" should be \"quadratic\", \"uniform\" or \"custom\".");
1337  }
1338 
1346  operator ThermalizationAlgorithm() const {
1347  const std::string s = operator std::string();
1348  if (s == "mode sampling") {
1350  }
1351  if (s == "biased BF") {
1353  }
1354  if (s == "unbiased BF") {
1356  }
1358  "The value for key \"" + std::string(key_) +
1359  "\" should be \"mode sampling\", \"biased BF\" or \"unbiased BF\".");
1360  }
1361 
1369  operator CollisionCriterion() const {
1370  const std::string s = operator std::string();
1371  if (s == "Geometric") {
1373  }
1374  if (s == "Stochastic") {
1376  }
1377  if (s == "Covariant") {
1379  }
1381  "The value for key \"" + std::string(key_) + "\" should be " +
1382  "\"Geometric\", \"Stochastic\" " + "or \"Covariant\".");
1383  }
1384 
1392  operator SpinInteractionType() const {
1393  const std::string s = operator std::string();
1394  if (s == "On")
1395  return SpinInteractionType::On;
1396  if (s == "Off")
1397  return SpinInteractionType::Off;
1398  throw IncorrectTypeInAssignment("The value for key \"" +
1399  std::string(key_) + "\" should be " +
1400  "\"On\", \"Off\" " + "or \"Elastic\".");
1401  }
1402 
1410  operator TotalCrossSectionStrategy() const {
1411  const std::string s = operator std::string();
1412  if (s == "BottomUp") {
1414  }
1415  if (s == "TopDown") {
1417  }
1418  if (s == "TopDownMeasured") {
1420  }
1422  "The value for key \"" + std::string(key_) + "\" should be " +
1423  "\"BottomUp\", \"TopDown\" " + "or \"TopDownMeasured\".");
1424  }
1425 
1433  operator PseudoResonance() const {
1434  const std::string s = operator std::string();
1435  if (s == "None") {
1436  return PseudoResonance::None;
1437  }
1438  if (s == "Largest") {
1439  return PseudoResonance::Largest;
1440  }
1441  if (s == "Closest") {
1442  return PseudoResonance::Closest;
1443  }
1444  if (s == "LargestFromUnstable") {
1446  }
1447  if (s == "ClosestFromUnstable") {
1449  }
1451  "The value for key \"" + std::string(key_) + "\" should be " +
1452  "\"None\", \"Largest\", \"Closest\", \"LargestFromUnstable\", or "
1453  "\"ClosestFromUnstable\".");
1454  }
1455 
1464  operator FluidizationType() const {
1465  const std::string s = operator std::string();
1466  if (s == "Constant_Tau") {
1468  } else if (s == "Dynamic") {
1470  }
1471  throw IncorrectTypeInAssignment("The value for key \"" +
1472  std::string(key_) + "\" should be " +
1473  "\"Constant_Tau\" or \"Dynamic\".");
1474  }
1475 
1483  operator OutputOnlyFinal() const {
1484  const std::string s = operator std::string();
1485  if (s == "Yes") {
1486  return OutputOnlyFinal::Yes;
1487  }
1488  if (s == "No") {
1489  return OutputOnlyFinal::No;
1490  }
1491  if (s == "IfNotEmpty") {
1493  }
1494  throw IncorrectTypeInAssignment("The value for key \"" +
1495  std::string(key_) + "\" should be " +
1496  "\"Yes\", \"No\" or \"IfNotEmpty\".");
1497  }
1498 
1506  operator FluidizableProcessesBitSet() const {
1507  const std::vector<std::string> v = operator std::vector<std::string>();
1509  for (const auto &x : v) {
1510  if (x == "All") {
1511  s.set();
1512  break;
1513  } else if (x == "Elastic") {
1515  } else if (x == "Decay") {
1517  } else if (x == "Inelastic") {
1519  } else if (x == "SoftString") {
1521  } else if (x == "HardString") {
1523  } else {
1525  "The value for key \"" + std::string(key_) +
1526  "\" should be \"All\", \"Elastic\", \"Decay\", "
1527  "\"Inelastic\", \"SoftString\", \"HardString\", "
1528  "or any combination of these.");
1529  }
1530  }
1531  return s;
1532  }
1533  };
1534 
1542  Configuration(const YAML::Node &node) // NOLINT(runtime/explicit) : see above
1543  : root_node_(YAML::Clone(node)) {}
1544 
1557  std::vector<std::string_view> keys) const;
1558 
1581  std::optional<YAML::Node> find_existing_node(
1582  std::vector<std::string_view> keys) const;
1583 
1587  template <class T>
1588  struct isMap : std::false_type {};
1592  template <class Key, class Value>
1593  struct isMap<std::map<Key, Value>> : std::true_type {};
1594 
1607  template <typename T>
1608  T get_validated_key_value(const Key<T> &key, const T &value) const {
1609  if (key.validate(value)) {
1610  return value;
1611  } else {
1612  throw std::invalid_argument(
1613  "Invalid value detected in configuration file:\n " +
1614  key.as_yaml(value));
1615  }
1616  }
1617 
1629  template <typename T>
1631  // The following assignment converts a Configuration::Value into T
1632  T value = take({key.labels().begin(), key.labels().end()});
1633  return get_validated_key_value(key, value);
1634  }
1635 
1647  template <typename T>
1649  // The following assignment converts a Configuration::Value into T
1650  T value = read({key.labels().begin(), key.labels().end()});
1651  return get_validated_key_value(key, value);
1652  }
1653 
1665  Value take(std::vector<std::string_view> labels);
1666 
1678  Value read(std::vector<std::string_view> labels) const;
1679 
1689  return std::find(existing_keys_already_taken_.begin(),
1691  labels) != existing_keys_already_taken_.end();
1692  }
1693 
1695  YAML::Node root_node_{YAML::NodeType::Map};
1696 
1698  int uncaught_exceptions_{std::uncaught_exceptions()};
1699 
1701  std::vector<KeyLabels> existing_keys_already_taken_{};
1702 };
1703 
1704 } // namespace smash
1705 
1706 #endif // SRC_INCLUDE_SMASH_CONFIGURATION_H_
Proxy object to be used when taking or reading keys in the configuration.
Value(const YAML::Node &n, const char *key)
Construct the Value wrapper from a YAML::Node.
Value(const Value &)=delete
If you want to copy this you're doing it wrong.
const char *const key_
The key to be interpreted.
const YAML::Node node_
a YAML leaf node
Value & operator=(const Value &)=delete
If you want to copy this you're doing it wrong.
Interface to the SMASH configuration files.
Is
Return type of Configuration::validate which conveys more information that simply a two-state boolean...
T take(const Key< T > &key, T default_value)
Alternative method to take a key value, specifying the default value.
void set_value(Key< U > key, T &&value)
Overwrite the value of the YAML node corresponding to the specified key.
Configuration(const Configuration &)=delete
Prevent Configuration objects from being copied.
void merge_yaml(const std::string &yaml)
Merge the configuration in yaml into the existing tree.
std::string to_string() const
Return a string of the current YAML tree.
Configuration extract_sub_configuration(KeyLabels section, Configuration::GetEmpty empty_if_not_existing=Configuration::GetEmpty::No)
Create a new configuration from a then-removed section of the present object.
T read(const Key< T > &key) const
Additional interface for SMASH to read configuration values without removing them.
T unconditionally_read_and_validate(const Key< T > &key) const
Read a key unconditionally, validate and return its value.
bool is_empty() const
Configuration(const std::filesystem::path &path)
Read config.yaml from the specified path.
T unconditionally_take_and_validate(const Key< T > &key)
Take a key unconditionally, validate and return its value.
void enclose_into_section(KeyLabels section)
Enclose the configuration into the given section.
YAML::Node root_node_
The general_config.yaml contents - fully parsed.
YAML::Node find_node_creating_it_if_not_existing(std::vector< std::string_view > keys) const
Descend in and if needed modify the YAML tree from the given node using the provided keys.
Configuration(const YAML::Node &node)
Create a sub-object that has its root node at the given node.
int uncaught_exceptions_
Counter to be able to optionally throw in destructor.
bool did_key_exist_and_was_it_already_taken(const KeyLabels &labels) const
Find out whether a key has been already taken.
Configuration(const char *yaml)
bool has_value(const Key< T > &key) const
Return whether there is a non-empty value behind the requested key (which is supposed not to refer to...
void clear()
Erase the Configuration content.
Configuration(const char *yaml, const char sflag)
Initialize configuration with a YAML formatted string.
bool has_key(const Key< T > &key) const
Return whether the configuration has a (possibly empty) non-map key.
bool has_section(const KeyLabels &labels) const
Return whether there is a (possibly empty) section with the given labels.
Is validate(bool full_validation=true) const
Validate content of configuration in terms of YAML keys.
std::optional< YAML::Node > find_existing_node(std::vector< std::string_view > keys) const
Descend in the YAML tree from the given node using the provided keys.
~Configuration() noexcept(false)
Destroy the object, optionally throwing if not all keys were taken.
GetEmpty
Flag to tune method(s) behavior such that it is descriptive from the caller side.
static const char InitializeFromYAMLString
Flag to mark initialization with a YAML formatted string.
Configuration extract_complete_sub_configuration(KeyLabels section, Configuration::GetEmpty empty_if_not_existing=Configuration::GetEmpty::No)
Alternative method to extract a sub-configuration, which retains the labels from the top-level in the...
T take(const Key< T > &key)
The default interface for SMASH to read configuration values.
void remove_all_entries_in_section_but_one(const std::string &key, KeyLabels section={})
Remove all entries in the given section except for key.
std::vector< std::string > list_upmost_nodes()
Lists all YAML::Nodes from the configuration setup.
std::vector< KeyLabels > existing_keys_already_taken_
List of taken keys to throw on taking same key twice.
T read(const Key< T > &key, T default_value) const
Alternative method to read a key value, specifying the default value.
T get_validated_key_value(const Key< T > &key, const T &value) const
Validate and return the passed key value.
Configuration & operator=(const Configuration &)=delete
Prevent Configuration objects from being copy-assigned.
Object to store a YAML input file key together with metadata associated to it.
Definition: key.h:158
bool has_dependent_default() const noexcept
Ask whether the default value depends on other other keys.
Definition: key.h:259
bool validate(const default_type &value) const noexcept
Get whether the given key value is valid.
Definition: key.h:316
default_type default_value() const
Get the default value of the key.
Definition: key.h:251
const KeyLabels & labels() const
Method to access the Key labels.
Definition: key.h:397
std::string as_yaml([[maybe_unused]] std::optional< default_type > value=std::nullopt) const noexcept
Build and return a YAML-formatted string in the compact form (using braces as single line).
Definition: key.h:362
default_type type
Let the clients of this class have access to the key type.
Definition: key.h:242
SmearingMode
Modes of smearing.
FermiMotion
Option to use Fermi Motion.
@ On
Use fermi motion in combination with potentials.
@ Frozen
Use fermi motion without potentials.
@ Off
Don't use fermi motion.
std::bitset< 10 > ReactionsBitSet
Container for the 2 to 2 reactions in the code.
ThermalizationAlgorithm
Defines the algorithm used for the forced thermalization.
FluidizationType
Possible methods to convert SMASH particle into fluid cells.
@ ConstantTau
Hypersurface crossed at a fixed proper time.
@ Dynamic
Dynamic fluidization based on local densities.
NNbarTreatment
Treatment of N Nbar Annihilation.
@ NoAnnihilation
No Annihilation.
@ TwoToFive
Directly create 5 pions, use with multi-particle reactions.
@ Resonances
Use intermediate Resonances.
@ Strings
Use string fragmentation.
TimeStepMode
The time step mode.
@ Fixed
Use fixed time step.
@ None
Don't use time steps; propagate from action to action.
@ EckartDensity
Density in the Eckart frame.
@ Tmn
Energy-momentum tensor in lab frame.
@ LandauVelocity
Velocity of the Landau rest frame.
@ j_QBS
Electric (Q), baryonic (B) and strange (S) currents.
@ TmnLandau
Energy-momentum tensor in Landau rest frame.
std::bitset< 5 > FluidizableProcessesBitSet
TotalCrossSectionStrategy
Determine how total cross sections for collision finding should be computed.
@ TopDownMeasured
Mix the two above, using the parametrizations only for measured processes, and summing up partials fo...
@ TopDown
Use parametrizations based on existing data, rescaling with AQM for unmeasured processes.
@ BottomUp
Sum the existing partial contributions.
Sampling
Possible methods of impact parameter sampling.
@ Quadratic
Sample from areal / quadratic distribution.
@ Custom
Sample from custom, user-defined distribution.
@ Uniform
Sample from uniform distribution.
@ From_HardString
@ From_Inelastic
@ From_Elastic
@ From_SoftString
@ From_Decay
std::bitset< 4 > MultiParticleReactionsBitSet
Container for the n to m reactions in the code.
CalculationFrame
The calculation frame.
@ NNbar_5to2
@ A3_Nuclei_4to2
@ Deuteron_3to2
@ Meson_3to1
DerivativesMode
Modes of calculating the gradients.
CollisionCriterion
Criteria used to check collisions.
@ Stochastic
Stochastic Criteiron.
@ Geometric
Geometric criterion.
@ Covariant
Covariant Criterion.
FieldDerivativesMode
Modes of calculating the field gradients: chain rule or direct.
SphereInitialCondition
Initial condition for a particle in a sphere.
@ ThermalMomentaBoltzmann
A thermalized ensemble is generated, with momenta sampled from a Maxwell-Boltzmann distribution.
@ IC_ES
Off-equilibrium distribution used in massless comparisons of SMASH to the extended universe metric.
@ ThermalMomentaQuantum
A thermalized ensemble is generated, with momenta of baryons(mesons) sampled from a Fermi(Bose) distr...
@ IC_Massive
A generalization of IC_ES for the non-zero mass case; note that there is currently no analytical comp...
@ IC_2M
Off-equilibrium distribution used in massless comparisons of SMASH to the extended universe metric.
@ IC_1M
Off-equilibrium distribution used in massless comparisons of SMASH to the extended universe metric.
PseudoResonance
Which pseudo-resonance fills the inelastic gap in the transition to string region of cross sections.
@ Closest
Resonance with the pole mass closest from the invariant mass of incoming particles for all processes.
@ ClosestFromUnstable
Closest resonance for a given mass from processes with at least one resonance in the incoming particl...
@ None
No pseudo-resonance is created.
@ LargestFromUnstable
Heaviest possible resonance from processes with at least one resonance in the incoming particles.
@ Largest
Resonance of largest mass for all processes.
@ KN_to_KDelta
@ KN_to_KN
@ NN_to_NR
@ PiDeuteron_to_pidprime
@ NDeuteron_to_Ndprime
@ Strangeness_exchange
@ PiDeuteron_to_NN
@ NN_to_DR
DensityType
Allows to choose which kind of density to calculate.
OutputOnlyFinal
Whether and when only final state particles should be printed.
@ IfNotEmpty
Print only final-state particles, and those only if the event is not empty.
@ Yes
Print only final-state particles.
@ No
Print initial, intermediate and final-state particles.
SpinInteractionType
Possible spin interaction types.
@ On
All spin interactions.
@ Off
No spin interactions.
BoxInitialCondition
Initial condition for a particle in a box.
@ ThermalMomentaBoltzmann
A thermalized ensemble is generated, with momenta sampled from a Maxwell-Boltzmann distribution.
@ ThermalMomentaQuantum
A thermalized ensemble is generated, with momenta of baryons(mesons) sampled from a Fermi(Bose) distr...
@ PeakedMomenta
All particles have the same momentum with T being the temperature.
ExpansionMode
Defines properties of expansion for the metric (e.g.
constexpr int n
Neutron.
Definition: action.h:24
std::vector< std::string > KeyLabels
Descriptive alias for storing key labels, i.e.
Definition: key.h:45
@ Value
Normal default with a value associated to it.
std::string to_string(ThermodynamicQuantity quantity)
Convert a ThermodynamicQuantity enum value to its corresponding string.
Definition: stringify.cc:26
Convert from YAML::Node to SMASH-readable (C++) format and vice versa.
Definition: configuration.h:42
static bool decode(const Node &node, T &x)
Deserialization: Converts a YAML::Node to any SMASH-readable data type and returns whether or not thi...
Definition: configuration.h:69
static Node encode(const T &x)
Serialization: Converts x (of any type) to a YAML::Node.
Definition: configuration.h:50
Thrown if the file does not exist.
Thrown when the types in the config file and C++ don't match.
Thrown for YAML parse errors.
Thrown if a Key is taken twice.
Utility type trait (general case) for the take and read public methods.