Version: SMASH-3.1
configuration.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2023
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 <exception>
15 #include <filesystem>
16 #include <optional>
17 #include <set>
18 #include <stdexcept>
19 #include <string>
20 #include <utility>
21 #include <vector>
22 
23 #include "yaml-cpp/yaml.h"
24 
25 #include "density.h"
26 #include "forwarddeclarations.h"
27 
28 namespace YAML {
29 
36 template <typename T>
37 struct convert {
45  static Node encode(const T &x) { return Node{static_cast<std::string>(x)}; }
46 
55  static bool decode(const Node &node, T &x) {
56  if (!node.IsScalar()) {
57  return false;
58  } else {
59  x = static_cast<T>(node.Scalar());
60  return true;
61  }
62  }
63 };
64 } // namespace YAML
65 
66 namespace smash {
67 
277  public:
282  struct IncorrectTypeInAssignment : public std::runtime_error {
283  using std::runtime_error::runtime_error;
284  };
289  struct ParseError : public std::runtime_error {
290  using std::runtime_error::runtime_error;
291  };
292 
297  struct FileDoesNotExist : public std::runtime_error {
298  using std::runtime_error::runtime_error;
299  };
300 
308  class Value {
309  friend class Configuration;
310 
312  const YAML::Node node_;
314  const char *const key_;
315 
322  Value(const YAML::Node &n, const char *key) : node_(n), key_(key) {
323  if (!(n.IsScalar() || n.IsSequence() || n.IsMap())) {
324  std::stringstream err;
325  err << "Configuration value for \"" << key
326  << "\" is missing or invalid";
327  throw std::runtime_error(err.str());
328  }
329  }
330 
331  public:
333  Value(const Value &) = delete;
335  Value &operator=(const Value &) = delete;
336 
363  template <typename T>
364  T convert_for(const T &) const {
365  return *this;
366  }
367 
376  template <typename T>
377  operator T() const {
378  try {
379  return node_.as<T>();
380  } catch (YAML::TypedBadConversion<T> &e) {
382  "The value for key \"" + std::string(key_) +
383  "\" cannot be converted to the requested type.");
384  }
385  }
386 
392  template <typename T>
393  operator std::vector<T>() const {
394  try {
395  return node_.as<std::vector<T>>();
396  } catch (YAML::TypedBadConversion<T> &e) {
398  "One of the values in the sequence for key \"" + std::string(key_) +
399  "\" failed to convert to the requested type. E.g. [1 2] is a "
400  "sequence of one string \"1 2\" and [1, 2] is a sequence of two "
401  "integers. Often there is just a comma missing in the config "
402  "file.");
403  } catch (YAML::TypedBadConversion<std::vector<T>> &e) {
405  "The value for key \"" + std::string(key_) +
406  "\" cannot be converted to the requested type. A sequence was "
407  "expected but apparently not found.");
408  }
409  }
410 
418  template <typename T, size_t N>
419  operator std::array<T, N>() const {
420  const std::vector<T> vec = operator std::vector<T>();
421  const size_t n_read = vec.size();
422  // Alert if size does not match
423  if (n_read != N) {
424  throw IncorrectTypeInAssignment("Wrong number of values in array \"" +
425  std::string(key_) + "\". Expected " +
426  std::to_string(N) +
427  " values,"
428  " found " +
429  std::to_string(n_read) + ".");
430  }
431  std::array<T, N> arr;
432  std::copy_n(vec.begin(), N, arr.begin());
433  return arr;
434  }
435 
443  operator ReactionsBitSet() const {
444  const std::vector<std::string> v = operator std::vector<std::string>();
445  ReactionsBitSet s;
446  for (const auto &x : v) {
447  if (x == "All") {
448  s.set();
449  break;
450  } else if (x == "Elastic") {
452  } else if (x == "NN_to_NR") {
454  } else if (x == "NN_to_DR") {
456  } else if (x == "KN_to_KN") {
458  } else if (x == "KN_to_KDelta") {
460  } else if (x == "Strangeness_exchange") {
462  } else if (x == "NNbar") {
464  } else if (x == "PiDeuteron_to_NN") {
466  } else if (x == "PiDeuteron_to_pidprime") {
468  } else if (x == "NDeuteron_to_Ndprime") {
470  } else {
472  "The value for key \"" + std::string(key_) +
473  "\" should be \"All\", \"Elastic\", \"NN_to_NR\", \"NN_to_DR\","
474  "\"KN_to_KN\", \"KN_to_KDelta\", \"PiDeuteron_to_NN\", "
475  "\"PiDeuteron_to_pidprime\", \"NDeuteron_to_Ndprime\", "
476  "\"Strangeness_exchange\" or "
477  "\"NNbar\", or any combination of these.");
478  }
479  }
480  return s;
481  }
482 
490  operator MultiParticleReactionsBitSet() const {
491  const std::vector<std::string> v = operator std::vector<std::string>();
493  for (const auto &x : v) {
494  if (x == "All") {
495  s.set();
496  break;
497  } else if (x == "Meson_3to1") {
499  } else if (x == "Deuteron_3to2") {
501  } else if (x == "NNbar_5to2") {
503  } else if (x == "A3_Nuclei_4to2") {
505  } else {
507  "The value for key \"" + std::string(key_) +
508  "\" should be \"All\", \"Meson_3to1\", "
509  "\"Deuteron_3to2\" or \"NNbar_5to2\", "
510  "\"A3_Nuclei_4to2\", or any combination of "
511  "these.");
512  }
513  }
514  return s;
515  }
516 
524  operator std::set<ThermodynamicQuantity>() const {
525  const std::vector<std::string> v = operator std::vector<std::string>();
526  std::set<ThermodynamicQuantity> s;
527  for (const auto &x : v) {
528  if (x == "rho_eckart") {
530  } else if (x == "tmn") {
531  s.insert(ThermodynamicQuantity::Tmn);
532  } else if (x == "tmn_landau") {
534  } else if (x == "landau_velocity") {
536  } else if (x == "j_QBS") {
538  } else {
540  "The value for key \"" + std::string(key_) +
541  "\" should be \"rho_eckart\", \"tmn\""
542  ", \"tmn_landau\", \"landau_velocity\" or \"j_QBS\".");
543  }
544  }
545  return s;
546  }
547 
555  operator CalculationFrame() const {
556  const std::string s = operator std::string();
557  if (s == "center of velocity") {
559  }
560  if (s == "center of mass") {
562  }
563  if (s == "fixed target") {
565  }
567  "The value for key \"" + std::string(key_) +
568  "\" should be \"center of velocity\" or \"center of mass\" "
569  "or \"fixed target\".");
570  }
571 
579  operator FermiMotion() const {
580  const std::string s = operator std::string();
581  if (s == "off") {
582  return FermiMotion::Off;
583  }
584  if (s == "on") {
585  return FermiMotion::On;
586  }
587  if (s == "frozen") {
588  return FermiMotion::Frozen;
589  }
591  "The value for key \"" + std::string(key_) +
592  "\" should be \"off\" or \"on\" or \"frozen\".");
593  }
594 
602  operator DensityType() const {
603  const std::string s = operator std::string();
604  if (s == "hadron") {
605  return DensityType::Hadron;
606  }
607  if (s == "baryon") {
608  return DensityType::Baryon;
609  }
610  if (s == "baryonic isospin") {
612  }
613  if (s == "pion") {
614  return DensityType::Pion;
615  }
616  if (s == "total isospin") {
618  }
619  if (s == "none") {
620  return DensityType::None;
621  }
622  throw IncorrectTypeInAssignment("The value for key \"" +
623  std::string(key_) +
624  "\" should be \"hadron\" or \"baryon\" "
625  "or \"baryonic isospin\" or \"pion\" "
626  "or \"none\".");
627  }
628 
636  operator ExpansionMode() const {
637  const std::string s = operator std::string();
638  if (s == "NoExpansion") {
640  }
641  if (s == "MasslessFRW") {
643  }
644  if (s == "MassiveFRW") {
646  }
647  if (s == "Exponential") {
649  }
651  "The value for key \"" + std::string(key_) +
652  "\" should be \"NoExpansion\", \"MasslessFRW\"," +
653  "\"MassiveFRW\" or \"Exponential\".");
654  }
655 
659  operator DerivativesMode() const {
660  const std::string s = operator std::string();
661  if (s == "Covariant Gaussian") {
663  }
664  if (s == "Finite difference") {
666  }
667  if (s == "Off") {
668  return DerivativesMode::Off;
669  }
671  "The value for key \"" + std::string(key_) +
672  "\" should be \"Covariant Gaussian\", \"Finite difference\"," +
673  " or \"Off\".");
674  }
675 
679  operator FieldDerivativesMode() const {
680  const std::string s = operator std::string();
681  if (s == "Chain Rule") {
683  }
684  if (s == "Direct") {
686  }
688  "The value for key \"" + std::string(key_) +
689  "\" should be \"Chain Rule\" or \"Direct\".");
690  }
691 
695  operator SmearingMode() const {
696  const std::string s = operator std::string();
697  if (s == "Covariant Gaussian") {
699  }
700  if (s == "Discrete") {
701  return SmearingMode::Discrete;
702  }
703  if (s == "Triangular") {
705  }
707  "The value for key \"" + std::string(key_) +
708  "\" should be \"Covariant Gaussian\", \"Discrete\"," +
709  " or \"Triangular\".");
710  }
711 
719  operator TimeStepMode() const {
720  const std::string s = operator std::string();
721  if (s == "None") {
722  return TimeStepMode::None;
723  }
724  if (s == "Fixed") {
725  return TimeStepMode::Fixed;
726  }
727  throw IncorrectTypeInAssignment("The value for key \"" +
728  std::string(key_) +
729  "\" should be \"None\" or \"Fixed\".");
730  }
731 
739  operator BoxInitialCondition() const {
740  const std::string s = operator std::string();
741  if (s == "thermal momenta") {
743  }
744  if (s == "thermal momenta quantum") {
746  }
747  if (s == "peaked momenta") {
749  }
751  "The value for key \"" + std::string(key_) +
752  "\" should be \"thermal momenta\", \"thermal momenta quantum\", " +
753  "or \"peaked momenta\".");
754  }
755 
763  operator SphereInitialCondition() const {
764  const std::string s = operator std::string();
765  if (s == "thermal momenta") {
767  }
768  if (s == "thermal momenta quantum") {
770  }
771  if (s == "IC_ES") {
773  }
774  if (s == "IC_1M") {
776  }
777  if (s == "IC_2M") {
779  }
780  if (s == "IC_Massive") {
782  }
784  "The value for key \"" + std::string(key_) +
785  "\" should be \"thermal momenta\", \"thermal momenta quantum\", " +
786  "\"IC_ES\", \"IC_1M\", \"IC_2M\" or" + "\"IC_Massive\".");
787  }
788 
796  operator NNbarTreatment() const {
797  const std::string s = operator std::string();
798  if (s == "no annihilation") {
800  }
801  if (s == "resonances") {
803  }
804  if (s == "two to five") {
806  }
807  if (s == "strings") {
809  }
811  "The value for key \"" + std::string(key_) + "\" should be " +
812  "\"no annihilation\", \"resonances\", \"two to five\" or " +
813  " \"strings\".");
814  }
815 
823  operator Sampling() const {
824  const std::string s = operator std::string();
825  if (s == "quadratic") {
826  return Sampling::Quadratic;
827  }
828  if (s == "custom") {
829  return Sampling::Custom;
830  }
831  if (s == "uniform") {
832  return Sampling::Uniform;
833  }
835  "The value for key \"" + std::string(key_) +
836  "\" should be \"quadratic\", \"uniform\" or \"custom\".");
837  }
838 
846  operator ThermalizationAlgorithm() const {
847  const std::string s = operator std::string();
848  if (s == "mode sampling") {
850  }
851  if (s == "biased BF") {
853  }
854  if (s == "unbiased BF") {
856  }
858  "The value for key \"" + std::string(key_) +
859  "\" should be \"mode sampling\", \"biased BF\" or \"unbiased BF\".");
860  }
861 
869  operator CollisionCriterion() const {
870  const std::string s = operator std::string();
871  if (s == "Geometric") {
873  }
874  if (s == "Stochastic") {
876  }
877  if (s == "Covariant") {
879  }
881  "The value for key \"" + std::string(key_) + "\" should be " +
882  "\"Geometric\", \"Stochastic\" " + "or \"Covariant\".");
883  }
884 
892  operator TotalCrossSectionStrategy() const {
893  const std::string s = operator std::string();
894  if (s == "BottomUp") {
896  }
897  if (s == "TopDown") {
899  }
900  if (s == "TopDownMeasured") {
902  }
904  "The value for key \"" + std::string(key_) + "\" should be " +
905  "\"BottomUp\", \"TopDown\" " + "or \"TopDownMeasured\".");
906  }
907 
915  operator PseudoResonance() const {
916  const std::string s = operator std::string();
917  if (s == "None") {
918  return PseudoResonance::None;
919  }
920  if (s == "Largest") {
922  }
923  if (s == "Closest") {
925  }
926  if (s == "LargestFromUnstable") {
928  }
929  if (s == "ClosestFromUnstable") {
931  }
933  "The value for key \"" + std::string(key_) + "\" should be " +
934  "\"None\", \"Largest\", \"Closest\", \"LargestFromUnstable\", or "
935  "\"ClosestFromUnstable\".");
936  }
937 
945  operator OutputOnlyFinal() const {
946  const std::string s = operator std::string();
947  if (s == "Yes") {
948  return OutputOnlyFinal::Yes;
949  }
950  if (s == "No") {
951  return OutputOnlyFinal::No;
952  }
953  if (s == "IfNotEmpty") {
955  }
956  throw IncorrectTypeInAssignment("The value for key \"" +
957  std::string(key_) + "\" should be " +
958  "\"Yes\", \"No\" or \"IfNotEmpty\".");
959  }
960  };
961 
965  static const char InitializeFromYAMLString = 'S';
966 
971  enum class GetEmpty { Yes, No };
972 
977  enum class Is { Invalid, Deprecated, Valid };
978 
984  explicit Configuration(const std::filesystem::path &path);
985 
993  explicit Configuration(const std::filesystem::path &path,
994  const std::filesystem::path &filename);
995 
1004  explicit Configuration(const char *yaml, const char sflag) {
1005  if (sflag == InitializeFromYAMLString) {
1006  merge_yaml(yaml);
1007  } else {
1008  throw std::runtime_error(
1009  "Unknown control flag in Configuration constructor"
1010  " with a YAML formatted string. Please, use"
1011  " Configuration::InitializeFromYAMLString.");
1012  }
1013  }
1014 
1015 #ifdef BUILD_TESTS
1024  explicit Configuration(const char *yaml) : root_node_(YAML::Load(yaml)) {
1025  if (root_node_.IsNull())
1026  root_node_ = YAML::Node{YAML::NodeType::Map};
1027  }
1028 #endif
1029 
1038  Configuration(const Configuration &) = delete;
1046 
1061 
1068 
1078  ~Configuration() noexcept(false);
1079 
1090  void merge_yaml(const std::string &yaml);
1091 
1093  std::vector<std::string> list_upmost_nodes();
1094 
1125  Value take(std::initializer_list<const char *> keys);
1126 
1128  template <typename T>
1129  T take(std::initializer_list<const char *> keys, T default_value) {
1130  if (has_value(keys)) {
1131  return take(keys);
1132  }
1133  return default_value;
1134  }
1135 
1150  Value read(std::initializer_list<const char *> keys) const;
1151 
1153  template <typename T>
1154  T read(std::initializer_list<const char *> keys, T default_value) {
1155  if (has_value(keys)) {
1156  return read(keys);
1157  }
1158  return default_value;
1159  }
1160 
1170  template <typename T>
1171  void set_value(std::initializer_list<const char *> keys, T &&value) {
1172  auto node = find_node_creating_it_if_not_existing(keys);
1173  node = std::forward<T>(value);
1174  }
1175 
1188  const std::string &key, std::initializer_list<const char *> section = {});
1189 
1210  std::initializer_list<const char *> keys,
1211  Configuration::GetEmpty empty_if_not_existing =
1213 
1219  std::initializer_list<const char *> keys) const;
1224  bool has_value(std::initializer_list<const char *> keys) const;
1225 
1230  bool is_empty() const { return root_node_.size() == 0; }
1231 
1235  std::string to_string() const;
1236 
1243  void clear() { root_node_.reset(); }
1244 
1262  Is validate(bool full_validation = true) const;
1263 
1264  private:
1272  Configuration(const YAML::Node &node) // NOLINT(runtime/explicit) : see above
1273  : root_node_(YAML::Clone(node)) {}
1274 
1287  std::vector<const char *> keys) const;
1288 
1311  std::optional<YAML::Node> find_existing_node(
1312  std::vector<const char *> keys) const;
1313 
1315  YAML::Node root_node_{YAML::NodeType::Map};
1316 
1318  int uncaught_exceptions_{std::uncaught_exceptions()};
1319 };
1320 
1321 } // namespace smash
1322 
1323 #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)
Construct 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.
Is
Return type of Configuration::validate which conveys more information that simply a two-state boolean...
bool has_value(std::initializer_list< const char * > keys) const
Return whether there is a non-empty value behind the requested keys.
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.
bool has_value_including_empty(std::initializer_list< const char * > keys) const
Return whether there is a (maybe empty) value behind the requested keys.
Configuration(const std::filesystem::path &path)
Read config.yaml from the specified path.
void remove_all_entries_in_section_but_one(const std::string &key, std::initializer_list< const char * > section={})
Remove all entries in the given section except for key.
YAML::Node find_node_creating_it_if_not_existing(std::vector< const char * > keys) const
Descend in and if needed modify the YAML tree from the given node using the provided keys.
YAML::Node root_node_
The general_config.yaml contents - fully parsed.
void set_value(std::initializer_list< const char * > keys, T &&value)
Overwrite the value of the specified YAML node.
Configuration extract_sub_configuration(std::initializer_list< const char * > keys, Configuration::GetEmpty empty_if_not_existing=Configuration::GetEmpty::No)
Create a new configuration from a then-removed section of the present object.
Configuration(const YAML::Node &node)
Create a subobject that has its root node at the given node.
int uncaught_exceptions_
Counter to be able to optionally throw in destructor.
Configuration(const char *yaml)
void clear()
Erase the Configuration content.
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.
Value read(std::initializer_list< const char * > keys) const
Additional interface for SMASH to read configuration values without removing them.
Is validate(bool full_validation=true) const
Validate content of configuration in terms of YAML 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.
std::optional< YAML::Node > find_existing_node(std::vector< const char * > keys) const
Descend in the YAML tree from the given node using the provided keys.
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.
Configuration & operator=(const Configuration &)=delete
Prevent Configuration objects from being copy-assigned.
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.
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.
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.
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
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.
@ 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
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:37
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:55
static Node encode(const T &x)
Serialization: Converts x (of any type) to a YAML::Node.
Definition: configuration.h:45
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.