Version: SMASH-2.1
configuration.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2021
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 <array>
14 #include <set>
15 #include <stdexcept>
16 #include <string>
17 #include <utility>
18 #include <vector>
19 
20 #include <yaml-cpp/yaml.h> // NOLINT(build/include_order)
21 
22 #include "density.h"
23 #include "forwarddeclarations.h"
24 
25 namespace YAML {
26 
33 template <typename T>
34 struct convert {
42  static Node encode(const T &x) { return Node{static_cast<std::string>(x)}; }
43 
52  static bool decode(const Node &node, T &x) {
53  if (!node.IsScalar()) {
54  return false;
55  } else {
56  x = static_cast<T>(node.Scalar());
57  return true;
58  }
59  }
60 };
61 } // namespace YAML
62 
63 namespace smash {
473  public:
478  struct IncorrectTypeInAssignment : public std::runtime_error {
479  using std::runtime_error::runtime_error;
480  };
485  struct ParseError : public std::runtime_error {
486  using std::runtime_error::runtime_error;
487  };
488 
493  struct FileDoesNotExist : public std::runtime_error {
494  using std::runtime_error::runtime_error;
495  };
496 
504  class Value {
505  friend class Configuration;
506 
508  const YAML::Node node_;
510  const char *const key_;
511 
518  Value(const YAML::Node &n, const char *key) : node_(n), key_(key) {
519  if (!(n.IsScalar() || n.IsSequence() || n.IsMap())) {
520  std::stringstream err;
521  err << "Configuration value for \"" << key
522  << "\" is missing or invalid";
523  throw std::runtime_error(err.str());
524  }
525  }
526 
527  public:
529  Value(const Value &) = delete;
531  Value &operator=(const Value &) = delete;
532 
559  template <typename T>
560  T convert_for(const T &) const {
561  return *this;
562  }
563 
572  template <typename T>
573  operator T() const {
574  try {
575  return node_.as<T>();
576  } catch (YAML::TypedBadConversion<T> &e) {
578  "The value for key \"" + std::string(key_) +
579  "\" cannot be converted to the requested type.");
580  }
581  }
582 
588  template <typename T>
589  operator std::vector<T>() const {
590  try {
591  return node_.as<std::vector<T>>();
592  } catch (YAML::TypedBadConversion<T> &e) {
594  "One of the values in the sequence for key \"" + std::string(key_) +
595  "\" failed to convert to the requested type. E.g. [1 2] is a "
596  "sequence of one string \"1 2\" and [1, 2] is a sequence of two "
597  "integers. Often there is just a comma missing in the config "
598  "file.");
599  } catch (YAML::TypedBadConversion<std::vector<T>> &e) {
601  "The value for key \"" + std::string(key_) +
602  "\" cannot be converted to the requested type. A sequence was "
603  "expected but apparently not found.");
604  }
605  }
606 
614  template <typename T, size_t N>
615  operator std::array<T, N>() const {
616  const std::vector<T> vec = operator std::vector<T>();
617  const size_t n_read = vec.size();
618  // Alert if size does not match
619  if (n_read != N) {
620  throw IncorrectTypeInAssignment("Wrong number of values in array \"" +
621  std::string(key_) + "\". Expected " +
622  std::to_string(N) +
623  " values,"
624  " found " +
625  std::to_string(n_read) + ".");
626  }
627  std::array<T, N> arr;
628  std::copy_n(vec.begin(), N, arr.begin());
629  return arr;
630  }
631 
639  operator ReactionsBitSet() const {
640  const std::vector<std::string> v = operator std::vector<std::string>();
641  ReactionsBitSet s;
642  for (const auto &x : v) {
643  if (x == "All") {
644  s.set();
645  break;
646  } else if (x == "Elastic") {
648  } else if (x == "NN_to_NR") {
650  } else if (x == "NN_to_DR") {
652  } else if (x == "KN_to_KN") {
654  } else if (x == "KN_to_KDelta") {
656  } else if (x == "Strangeness_exchange") {
658  } else if (x == "NNbar") {
660  } else if (x == "PiDeuteron_to_NN") {
662  } else if (x == "PiDeuteron_to_pidprime") {
664  } else if (x == "NDeuteron_to_Ndprime") {
666  } else {
668  "The value for key \"" + std::string(key_) +
669  "\" should be \"All\", \"Elastic\", \"NN_to_NR\", \"NN_to_DR\","
670  "\"KN_to_KN\", \"KN_to_KDelta\", \"PiDeuteron_to_NN\", "
671  "\"PiDeuteron_to_pidprime\", \"NDeuteron_to_Ndprime\", "
672  "\"Strangeness_exchange\" or "
673  "\"NNbar\", or any combination of these.");
674  }
675  }
676  return s;
677  }
678 
686  operator MultiParticleReactionsBitSet() const {
687  const std::vector<std::string> v = operator std::vector<std::string>();
689  for (const auto &x : v) {
690  if (x == "All") {
691  s.set();
692  break;
693  } else if (x == "Meson_3to1") {
695  } else if (x == "Deuteron_3to2") {
697  } else if (x == "NNbar_5to2") {
699  } else {
701  "The value for key \"" + std::string(key_) +
702  "\" should be \"All\", \"Meson_3to1\", "
703  "\"Deuteron_3to2\" or \"NNbar_5to2\", or any combination of "
704  "these.");
705  }
706  }
707  return s;
708  }
709 
717  operator std::set<ThermodynamicQuantity>() const {
718  const std::vector<std::string> v = operator std::vector<std::string>();
719  std::set<ThermodynamicQuantity> s;
720  for (const auto &x : v) {
721  if (x == "rho_eckart") {
723  } else if (x == "tmn") {
724  s.insert(ThermodynamicQuantity::Tmn);
725  } else if (x == "tmn_landau") {
727  } else if (x == "landau_velocity") {
729  } else if (x == "j_QBS") {
731  } else {
733  "The value for key \"" + std::string(key_) +
734  "\" should be \"rho_eckart\", \"tmn\""
735  ", \"tmn_landau\", \"landau_velocity\" or \"j_QBS\".");
736  }
737  }
738  return s;
739  }
740 
748  operator CalculationFrame() const {
749  const std::string s = operator std::string();
750  if (s == "center of velocity") {
752  }
753  if (s == "center of mass") {
755  }
756  if (s == "fixed target") {
758  }
760  "The value for key \"" + std::string(key_) +
761  "\" should be \"center of velocity\" or \"center of mass\" "
762  "or \"fixed target\".");
763  }
764 
772  operator FermiMotion() const {
773  const std::string s = operator std::string();
774  if (s == "off") {
775  return FermiMotion::Off;
776  }
777  if (s == "on") {
778  return FermiMotion::On;
779  }
780  if (s == "frozen") {
781  return FermiMotion::Frozen;
782  }
784  "The value for key \"" + std::string(key_) +
785  "\" should be \"off\" or \"on\" or \"frozen\".");
786  }
787 
795  operator DensityType() const {
796  const std::string s = operator std::string();
797  if (s == "hadron") {
798  return DensityType::Hadron;
799  }
800  if (s == "baryon") {
801  return DensityType::Baryon;
802  }
803  if (s == "baryonic isospin") {
805  }
806  if (s == "pion") {
807  return DensityType::Pion;
808  }
809  if (s == "total isospin") {
811  }
812  if (s == "none") {
813  return DensityType::None;
814  }
815  throw IncorrectTypeInAssignment("The value for key \"" +
816  std::string(key_) +
817  "\" should be \"hadron\" or \"baryon\" "
818  "or \"baryonic isospin\" or \"pion\" "
819  "or \"none\".");
820  }
821 
829  operator ExpansionMode() const {
830  const std::string s = operator std::string();
831  if (s == "NoExpansion") {
833  }
834  if (s == "MasslessFRW") {
836  }
837  if (s == "MassiveFRW") {
839  }
840  if (s == "Exponential") {
842  }
844  "The value for key \"" + std::string(key_) +
845  "\" should be \"NoExpansion\", \"MasslessFRW\"," +
846  "\"MassiveFRW\" or \"Exponential\".");
847  }
848 
852  operator DerivativesMode() const {
853  const std::string s = operator std::string();
854  if (s == "Covariant Gaussian") {
856  }
857  if (s == "Finite difference") {
859  }
860  if (s == "Off") {
861  return DerivativesMode::Off;
862  }
864  "The value for key \"" + std::string(key_) +
865  "\" should be \"Covariant Gaussian\", \"Finite difference\"," +
866  " or \"Off\".");
867  }
868 
873  const std::string s = operator std::string();
874  if (s == "On") {
876  }
877  if (s == "Off") {
879  }
880  throw IncorrectTypeInAssignment("The value for key \"" +
881  std::string(key_) +
882  "\" should be \"On\" or \"Off\".");
883  }
884 
888  operator FieldDerivativesMode() const {
889  const std::string s = operator std::string();
890  if (s == "Chain Rule") {
892  }
893  if (s == "Direct") {
895  }
897  "The value for key \"" + std::string(key_) +
898  "\" should be \"Chain Rule\" or \"Direct\".");
899  }
900 
904  operator SmearingMode() const {
905  const std::string s = operator std::string();
906  if (s == "Covariant Gaussian") {
908  }
909  if (s == "Discrete") {
910  return SmearingMode::Discrete;
911  }
912  if (s == "Triangular") {
914  }
916  "The value for key \"" + std::string(key_) +
917  "\" should be \"Covariant Gaussian\", \"Discrete\"," +
918  " or \"Triangular\".");
919  }
920 
928  operator TimeStepMode() const {
929  const std::string s = operator std::string();
930  if (s == "None") {
931  return TimeStepMode::None;
932  }
933  if (s == "Fixed") {
934  return TimeStepMode::Fixed;
935  }
936  throw IncorrectTypeInAssignment("The value for key \"" +
937  std::string(key_) +
938  "\" should be \"None\" or \"Fixed\".");
939  }
940 
948  operator BoxInitialCondition() const {
949  const std::string s = operator std::string();
950  if (s == "thermal momenta") {
952  }
953  if (s == "thermal momenta quantum") {
955  }
956  if (s == "peaked momenta") {
958  }
960  "The value for key \"" + std::string(key_) +
961  "\" should be \"thermal momenta\", \"thermal momenta quantum\", " +
962  "or \"peaked momenta\".");
963  }
964 
972  operator SphereInitialCondition() const {
973  const std::string s = operator std::string();
974  if (s == "thermal momenta") {
976  }
977  if (s == "thermal momenta quantum") {
979  }
980  if (s == "IC_ES") {
982  }
983  if (s == "IC_1M") {
985  }
986  if (s == "IC_2M") {
988  }
989  if (s == "IC_Massive") {
991  }
993  "The value for key \"" + std::string(key_) +
994  "\" should be \"thermal momenta\", \"thermal momenta quantum\", " +
995  "\"IC_ES\", \"IC_1M\", \"IC_2M\" or" + "\"IC_Massive\".");
996  }
997 
1005  operator NNbarTreatment() const {
1006  const std::string s = operator std::string();
1007  if (s == "no annihilation") {
1009  }
1010  if (s == "resonances") {
1012  }
1013  if (s == "two to five") {
1015  }
1016  if (s == "strings") {
1017  return NNbarTreatment::Strings;
1018  }
1020  "The value for key \"" + std::string(key_) + "\" should be " +
1021  "\"no annihilation\", \"resonances\", \"two to five\" or " +
1022  " \"strings\".");
1023  }
1024 
1032  operator Sampling() const {
1033  const std::string s = operator std::string();
1034  if (s == "quadratic") {
1035  return Sampling::Quadratic;
1036  }
1037  if (s == "custom") {
1038  return Sampling::Custom;
1039  }
1040  if (s == "uniform") {
1041  return Sampling::Uniform;
1042  }
1044  "The value for key \"" + std::string(key_) +
1045  "\" should be \"quadratic\", \"uniform\" or \"custom\".");
1046  }
1047 
1055  operator ThermalizationAlgorithm() const {
1056  const std::string s = operator std::string();
1057  if (s == "mode sampling") {
1059  }
1060  if (s == "biased BF") {
1062  }
1063  if (s == "unbiased BF") {
1065  }
1067  "The value for key \"" + std::string(key_) +
1068  "\" should be \"mode sampling\", \"biased BF\" or \"unbiased BF\".");
1069  }
1070 
1078  operator CollisionCriterion() const {
1079  const std::string s = operator std::string();
1080  if (s == "Geometric") {
1082  }
1083  if (s == "Stochastic") {
1085  }
1086  if (s == "Covariant") {
1088  }
1090  "The value for key \"" + std::string(key_) + "\" should be " +
1091  "\"Geometric\", \"Stochastic\" " + "or \"Covariant\".");
1092  }
1093 
1101  operator OutputOnlyFinal() const {
1102  const std::string s = operator std::string();
1103  if (s == "Yes") {
1104  return OutputOnlyFinal::Yes;
1105  }
1106  if (s == "No") {
1107  return OutputOnlyFinal::No;
1108  }
1109  if (s == "IfNotEmpty") {
1111  }
1112  throw IncorrectTypeInAssignment("The value for key \"" +
1113  std::string(key_) + "\" should be " +
1114  "\"Yes\", \"No\" or \"IfNotEmpty\".");
1115  }
1116  };
1117 
1121  static const char InitializeFromYAMLString = 'S';
1122 
1128  explicit Configuration(const bf::path &path);
1129 
1137  explicit Configuration(const bf::path &path, const bf::path &filename);
1138 
1147  explicit Configuration(const char *yaml, const char sflag) {
1148  if (sflag == InitializeFromYAMLString) {
1149  merge_yaml(yaml);
1150  } else {
1151  throw std::runtime_error(
1152  "Unknown control flag in Configuration constructor"
1153  " with a YAML formatted string. Please, use"
1154  " Configuration::InitializeFromYAMLString.");
1155  }
1156  }
1157 
1163  explicit Configuration(int invalue) {
1164  if (invalue == 0) {
1165  invalue = 1;
1166  }
1167  }
1168 
1169 #ifdef BUILD_TESTS
1178  explicit Configuration(const char *yaml) : root_node_(YAML::Load(yaml)) {}
1179 #endif
1180 
1182  Configuration(const Configuration &) = default;
1185 
1190 
1201  void merge_yaml(const std::string &yaml);
1202 
1204  std::vector<std::string> list_upmost_nodes();
1205 
1227  Value take(std::initializer_list<const char *> keys);
1228 
1230  template <typename T>
1231  T take(std::initializer_list<const char *> keys, T default_value) {
1232  if (has_value(keys)) {
1233  return take(keys);
1234  }
1235  return default_value;
1236  }
1237 
1252  Value read(std::initializer_list<const char *> keys) const;
1253 
1255  template <typename T>
1256  T read(std::initializer_list<const char *> keys, T default_value) {
1257  if (has_value(keys)) {
1258  return read(keys);
1259  }
1260  return default_value;
1261  }
1262 
1268  void remove_all_but(const std::string &key);
1269 
1284  template <typename T>
1286  return root_node_[std::forward<T>(key)];
1287  }
1288 
1296  template <typename T>
1297  Configuration &operator=(T &&value) {
1298  root_node_ = std::forward<T>(value);
1299  return *this;
1300  }
1301 
1307  std::initializer_list<const char *> keys) const;
1312  bool has_value(std::initializer_list<const char *> keys) const;
1313 
1317  std::string unused_values_report() const;
1318 
1324  std::string to_string() const;
1325 
1326  private:
1333  Configuration(const YAML::Node &node) // NOLINT(runtime/explicit) : see above
1334  : root_node_(node) {}
1335 
1337  YAML::Node root_node_;
1338 };
1339 
1340 } // namespace smash
1341 
1342 #endif // SRC_INCLUDE_SMASH_CONFIGURATION_H_
Return type of Configuration::take that automatically determines the target type.
Value(const YAML::Node &n, const char *key)
Constructs the Value wrapper from a YAML::Node.
Value(const Value &)=delete
If you want to copy this you're doing it wrong.
T convert_for(const T &) const
Convert the value to the type of the supplied argument.
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.
bool has_value(std::initializer_list< const char * > keys) const
Returns whether there is a non-empty value behind the requested keys.
Configuration & operator=(const Configuration &)=default
If you want to copy this you're doing it wrong.
void merge_yaml(const std::string &yaml)
Merge the configuration in yaml into the existing tree.
std::string to_string() const
Returns a YAML string of the current tree.
bool has_value_including_empty(std::initializer_list< const char * > keys) const
Returns if there is a (maybe empty) value behind the requested keys.
std::string unused_values_report() const
Returns a string listing the key/value pairs that have not been taken yet.
Configuration(const Configuration &)=default
If you want to copy this you're doing it wrong.
void remove_all_but(const std::string &key)
Removes all entries in the map except for key.
Configuration & operator=(Configuration &&)=default
Moving is fine.
YAML::Node root_node_
the general_config.yaml contents - fully parsed
Configuration(const bf::path &path)
Reads config.yaml from the specified path.
Configuration(int invalue)
Trivial constructor for testing purposes.
Configuration(const YAML::Node &node)
Creates a subobject that has its root node at the given node.
Configuration & operator=(T &&value)
Assignment overwrites the value of the current YAML node.
Configuration(const char *yaml)
Value take(std::initializer_list< const char * > keys)
The default interface for SMASH to read configuration values.
Configuration(const char *yaml, const char sflag)
Initialize configuration with a YAML formatted string.
Configuration operator[](T &&key)
Access to the YAML::Node behind the requested keys.
Configuration(Configuration &&)=default
Moving is fine.
Value read(std::initializer_list< const char * > keys) const
Additional interface for SMASH to read configuration values without removing them.
T take(std::initializer_list< const char * > keys, T default_value)
static const char InitializeFromYAMLString
Flag to mark initialization with a YAML formatted string.
T read(std::initializer_list< const char * > keys, T default_value)
std::vector< std::string > list_upmost_nodes()
Lists all YAML::Nodes from the configuration setup.
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.
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.
RestFrameDensityDerivativesMode
Modes of calculating the gradients: whether to calculate the rest frame density derivatives.
TimeStepMode
The time step mode.
@ Fixed
Use fixed time step.
@ None
Don't use time steps; propagate from action to action.
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.
CalculationFrame
The calculation frame.
@ NNbar_5to2
@ Deuteron_3to2
@ Meson_3to1
DerivativesMode
Modes of calculating the gradients.
CollisionCriterion
Criteria used to check collisions.
@ Stochastic
Stochastic Criteiron.
@ Geometric
(Default) 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.
@ KN_to_KDelta
@ KN_to_KN
@ NN_to_NR
@ PiDeuteron_to_pidprime
@ NDeuteron_to_Ndprime
@ Strangeness_exchange
@ PiDeuteron_to_NN
@ NN_to_DR
std::bitset< 3 > MultiParticleReactionsBitSet
Container for the n to m reactions in the code.
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.
BoxInitialCondition
Initial condition for a particle in a box.
ExpansionMode
Defines properties of expansion for the metric (e.g.
constexpr int n
Neutron.
Definition: action.h:24
DensityType
Allows to choose which kind of density to calculate.
Definition: density.h:36
Convert from YAML::Node to SMASH-readable (C++) format and vice versa.
Definition: configuration.h:34
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:52
static Node encode(const T &x)
Serialization: Converts x (of any type) to a YAML::Node.
Definition: configuration.h:42
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.