10 #ifndef SRC_INCLUDE_SMASH_CONFIGURATION_H_
11 #define SRC_INCLUDE_SMASH_CONFIGURATION_H_
26 #include "yaml-cpp/yaml.h"
51 if constexpr (std::is_convertible_v<T, std::string>) {
52 return Node{
static_cast<std::string
>(x)};
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.");
69 static bool decode(
const Node &node, T &x) {
70 if (!node.IsScalar()) {
73 x =
static_cast<T
>(node.Scalar());
301 using std::runtime_error::runtime_error;
308 using std::runtime_error::runtime_error;
315 using std::runtime_error::runtime_error;
322 using std::logic_error::logic_error;
357 const std::filesystem::path &filename);
371 throw std::runtime_error(
372 "Unknown control flag in Configuration constructor"
373 " with a YAML formatted string. Please, use"
374 " Configuration::InitializeFromYAMLString.");
513 template <typename T>
523 throw std::logic_error(
524 "Key " + std::string{key} +
525 " was taken, but its value is not a map, although there is a "
526 "section in the configuration with its labels.");
536 return key.default_value();
537 }
catch (std::bad_optional_access &) {
538 throw std::invalid_argument(
539 "Key " + std::string{key} +
540 " without default value taken, but missing in configuration.");
561 template <
typename T>
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).");
570 throw std::logic_error(
"Invalid default value passed when taking " +
571 static_cast<std::string
>(key) +
" key.");
576 return default_value;
605 template <
typename T>
615 throw std::logic_error(
616 "Key " + std::string{key} +
617 " was read, but its value is not a map, although there is a "
618 "section in the configuration with its labels.");
625 }
catch (std::bad_optional_access &) {
626 throw std::invalid_argument(
627 "Key " + std::string{key} +
628 " without default value read, but missing in configuration.");
649 template <
typename T>
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).");
658 throw std::logic_error(
"Invalid default value passed when reading " +
659 static_cast<std::string
>(key) +
" key.");
664 return default_value;
689 template <
typename T,
typename U = remove_cvref_t<T>,
690 typename std::enable_if_t<std::is_convertible_v<T, U>,
bool> = true>
694 node = std::forward<T>(value);
759 template <
typename T>
761 const auto found_node =
763 return found_node.has_value() && !(found_node.value().IsMap());
773 template <
typename T>
775 const auto found_node =
777 return found_node.has_value() && !(found_node.value().IsNull()) &&
778 !(found_node.value().IsMap());
788 return found_node.has_value() && found_node.value().IsMap();
827 Is validate(
bool full_validation =
true)
const;
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());
876 template <
typename T>
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.");
892 template <
typename T>
893 operator std::vector<T>()
const {
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 "
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.");
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();
925 std::string(
key_) +
"\". Expected " +
931 std::array<T, N> arr;
932 std::copy_n(vec.begin(), N, arr.begin());
944 const std::vector<std::string> v =
operator std::vector<std::string>();
946 for (
const auto &x : v) {
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") {
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.");
991 const std::vector<std::string> v =
operator std::vector<std::string>();
993 for (
const auto &x : v) {
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") {
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 "
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") {
1032 }
else if (x ==
"tmn_landau") {
1034 }
else if (x ==
"landau_velocity") {
1036 }
else if (x ==
"j_QBS") {
1040 "The value for key \"" + std::string(
key_) +
1041 "\" should be \"rho_eckart\", \"tmn\""
1042 ", \"tmn_landau\", \"landau_velocity\" or \"j_QBS\".");
1056 const std::string s =
operator std::string();
1057 if (s ==
"center of velocity") {
1060 if (s ==
"center of mass") {
1063 if (s ==
"fixed target") {
1067 "The value for key \"" + std::string(
key_) +
1068 "\" should be \"center of velocity\" or \"center of mass\" "
1069 "or \"fixed target\".");
1080 const std::string s =
operator std::string();
1087 if (s ==
"frozen") {
1091 "The value for key \"" + std::string(
key_) +
1092 "\" should be \"off\" or \"on\" or \"frozen\".");
1103 const std::string s =
operator std::string();
1104 if (s ==
"hadron") {
1107 if (s ==
"baryon") {
1110 if (s ==
"baryonic isospin") {
1116 if (s ==
"total isospin") {
1124 "\" should be \"hadron\" or \"baryon\" "
1125 "or \"baryonic isospin\" or \"pion\" "
1137 const std::string s =
operator std::string();
1138 if (s ==
"NoExpansion") {
1141 if (s ==
"MasslessFRW") {
1144 if (s ==
"MassiveFRW") {
1147 if (s ==
"Exponential") {
1151 "The value for key \"" + std::string(
key_) +
1152 "\" should be \"NoExpansion\", \"MasslessFRW\"," +
1153 "\"MassiveFRW\" or \"Exponential\".");
1160 const std::string s =
operator std::string();
1161 if (s ==
"Covariant Gaussian") {
1164 if (s ==
"Finite difference") {
1171 "The value for key \"" + std::string(
key_) +
1172 "\" should be \"Covariant Gaussian\", \"Finite difference\"," +
1180 const std::string s =
operator std::string();
1181 if (s ==
"Chain Rule") {
1184 if (s ==
"Direct") {
1188 "The value for key \"" + std::string(
key_) +
1189 "\" should be \"Chain Rule\" or \"Direct\".");
1196 const std::string s =
operator std::string();
1197 if (s ==
"Covariant Gaussian") {
1200 if (s ==
"Discrete") {
1203 if (s ==
"Triangular") {
1207 "The value for key \"" + std::string(
key_) +
1208 "\" should be \"Covariant Gaussian\", \"Discrete\"," +
1209 " or \"Triangular\".");
1220 const std::string s =
operator std::string();
1229 "\" should be \"None\" or \"Fixed\".");
1240 const std::string s =
operator std::string();
1241 if (s ==
"thermal momenta") {
1244 if (s ==
"thermal momenta quantum") {
1247 if (s ==
"peaked momenta") {
1251 "The value for key \"" + std::string(
key_) +
1252 "\" should be \"thermal momenta\", \"thermal momenta quantum\", " +
1253 "or \"peaked momenta\".");
1264 const std::string s =
operator std::string();
1265 if (s ==
"thermal momenta") {
1268 if (s ==
"thermal momenta quantum") {
1280 if (s ==
"IC_Massive") {
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\".");
1297 const std::string s =
operator std::string();
1298 if (s ==
"no annihilation") {
1301 if (s ==
"resonances") {
1304 if (s ==
"two to five") {
1307 if (s ==
"strings") {
1311 "The value for key \"" + std::string(
key_) +
"\" should be " +
1312 "\"no annihilation\", \"resonances\", \"two to five\" or " +
1324 const std::string s =
operator std::string();
1325 if (s ==
"quadratic") {
1328 if (s ==
"custom") {
1331 if (s ==
"uniform") {
1335 "The value for key \"" + std::string(
key_) +
1336 "\" should be \"quadratic\", \"uniform\" or \"custom\".");
1347 const std::string s =
operator std::string();
1348 if (s ==
"mode sampling") {
1351 if (s ==
"biased BF") {
1354 if (s ==
"unbiased BF") {
1358 "The value for key \"" + std::string(
key_) +
1359 "\" should be \"mode sampling\", \"biased BF\" or \"unbiased BF\".");
1370 const std::string s =
operator std::string();
1371 if (s ==
"Geometric") {
1374 if (s ==
"Stochastic") {
1377 if (s ==
"Covariant") {
1381 "The value for key \"" + std::string(
key_) +
"\" should be " +
1382 "\"Geometric\", \"Stochastic\" " +
"or \"Covariant\".");
1393 const std::string s =
operator std::string();
1399 std::string(
key_) +
"\" should be " +
1400 "\"On\", \"Off\" " +
"or \"Elastic\".");
1411 const std::string s =
operator std::string();
1412 if (s ==
"BottomUp") {
1415 if (s ==
"TopDown") {
1418 if (s ==
"TopDownMeasured") {
1422 "The value for key \"" + std::string(
key_) +
"\" should be " +
1423 "\"BottomUp\", \"TopDown\" " +
"or \"TopDownMeasured\".");
1434 const std::string s =
operator std::string();
1438 if (s ==
"Largest") {
1441 if (s ==
"Closest") {
1444 if (s ==
"LargestFromUnstable") {
1447 if (s ==
"ClosestFromUnstable") {
1451 "The value for key \"" + std::string(
key_) +
"\" should be " +
1452 "\"None\", \"Largest\", \"Closest\", \"LargestFromUnstable\", or "
1453 "\"ClosestFromUnstable\".");
1465 const std::string s =
operator std::string();
1466 if (s ==
"Constant_Tau") {
1468 }
else if (s ==
"Dynamic") {
1472 std::string(
key_) +
"\" should be " +
1473 "\"Constant_Tau\" or \"Dynamic\".");
1484 const std::string s =
operator std::string();
1491 if (s ==
"IfNotEmpty") {
1495 std::string(
key_) +
"\" should be " +
1496 "\"Yes\", \"No\" or \"IfNotEmpty\".");
1507 const std::vector<std::string> v =
operator std::vector<std::string>();
1509 for (
const auto &x : v) {
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") {
1525 "The value for key \"" + std::string(
key_) +
1526 "\" should be \"All\", \"Elastic\", \"Decay\", "
1527 "\"Inelastic\", \"SoftString\", \"HardString\", "
1528 "or any combination of these.");
1557 std::vector<std::string_view> keys)
const;
1582 std::vector<std::string_view> keys)
const;
1592 template <
class Key,
class Value>
1593 struct isMap<std::map<Key, Value>> : std::true_type {};
1607 template <
typename T>
1612 throw std::invalid_argument(
1613 "Invalid value detected in configuration file:\n " +
1629 template <
typename T>
1647 template <
typename T>
1665 Value take(std::vector<std::string_view> labels);
1678 Value read(std::vector<std::string_view> labels)
const;
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.
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.
bool has_dependent_default() const noexcept
Ask whether the default value depends on other other keys.
bool validate(const default_type &value) const noexcept
Get whether the given key value is valid.
default_type default_value() const
Get the default value of the key.
const KeyLabels & labels() const
Method to access the Key labels.
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).
default_type type
Let the clients of this class have access to the key type.
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.
std::bitset< 4 > MultiParticleReactionsBitSet
Container for the n to m reactions in the code.
CalculationFrame
The calculation frame.
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.
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.
std::vector< std::string > KeyLabels
Descriptive alias for storing key labels, i.e.
@ Value
Normal default with a value associated to it.
std::string to_string(ThermodynamicQuantity quantity)
Convert a ThermodynamicQuantity enum value to its corresponding string.
Convert from YAML::Node to SMASH-readable (C++) format and vice versa.
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...
static Node encode(const T &x)
Serialization: Converts x (of any type) to a YAML::Node.
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.