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;
329 using std::invalid_argument::invalid_argument;
336 using std::invalid_argument::invalid_argument;
371 const std::filesystem::path &filename);
385 throw std::runtime_error(
386 "Unknown control flag in Configuration constructor"
387 " with a YAML formatted string. Please, use"
388 " Configuration::InitializeFromYAMLString.");
527 template <typename T>
537 throw std::logic_error(
538 "Key " + std::string{key} +
539 " was taken, but its value is not a map, although there is a "
540 "section in the configuration with its labels.");
550 return key.default_value();
551 }
catch (std::bad_optional_access &) {
553 "Key " + std::string{key} +
554 " without default value taken, but missing in configuration.");
575 template <
typename T>
578 throw std::logic_error(
579 "An input Key without dependent default cannot be taken specifying a "
580 "default value! Either define the key as having a dependent default "
581 "or take it without a default value (which is a Key property).");
584 throw std::logic_error(
"Invalid default value passed when taking " +
585 static_cast<std::string
>(key) +
" key.");
590 return default_value;
619 template <
typename T>
629 throw std::logic_error(
630 "Key " + std::string{key} +
631 " was read, but its value is not a map, although there is a "
632 "section in the configuration with its labels.");
639 }
catch (std::bad_optional_access &) {
641 "Key " + std::string{key} +
642 " without default value read, but missing in configuration.");
663 template <
typename T>
666 throw std::logic_error(
667 "An input Key without dependent default cannot be read specifying a "
668 "default value! Either define the key as having a dependent default "
669 "or read it without a default value (which is a Key property).");
672 throw std::logic_error(
"Invalid default value passed when reading " +
673 static_cast<std::string
>(key) +
" key.");
678 return default_value;
703 template <
typename T,
typename U = remove_cvref_t<T>,
704 typename std::enable_if_t<std::is_convertible_v<T, U>,
bool> = true>
708 node = std::forward<T>(value);
773 template <
typename T>
775 const auto found_node =
777 return found_node.has_value() && !(found_node.value().IsMap());
787 template <
typename T>
789 const auto found_node =
791 return found_node.has_value() && !(found_node.value().IsNull()) &&
792 !(found_node.value().IsMap());
802 return found_node.has_value() && found_node.value().IsMap();
841 Is validate(
bool full_validation =
true)
const;
868 if (!(
n.IsScalar() ||
n.IsSequence() ||
n.IsMap())) {
869 std::stringstream err;
870 err <<
"Configuration value for \"" << key
871 <<
"\" is missing or invalid";
872 throw std::runtime_error(err.str());
890 template <
typename T>
893 return node_.as<T>();
894 }
catch (YAML::TypedBadConversion<T> &e) {
896 "The value for key \"" + std::string(
key_) +
897 "\" cannot be converted to the requested type.");
906 template <
typename T>
907 operator std::vector<T>()
const {
909 return node_.as<std::vector<T>>();
910 }
catch (YAML::TypedBadConversion<T> &e) {
912 "One of the values in the sequence for key \"" + std::string(
key_) +
913 "\" failed to convert to the requested type. E.g. [1 2] is a "
914 "sequence of one string \"1 2\" and [1, 2] is a sequence of two "
915 "integers. Often there is just a comma missing in the config "
917 }
catch (YAML::TypedBadConversion<std::vector<T>> &e) {
919 "The value for key \"" + std::string(
key_) +
920 "\" cannot be converted to the requested type. A sequence was "
921 "expected but apparently not found.");
932 template <
typename T,
size_t N>
933 operator std::array<T, N>()
const {
934 const std::vector<T> vec =
operator std::vector<T>();
935 const size_t n_read = vec.size();
939 std::string(
key_) +
"\". Expected " +
945 std::array<T, N> arr;
946 std::copy_n(vec.begin(), N, arr.begin());
958 const std::vector<std::string> v =
operator std::vector<std::string>();
960 for (
const auto &x : v) {
964 }
else if (x ==
"Elastic") {
966 }
else if (x ==
"NN_to_NR") {
968 }
else if (x ==
"NN_to_DR") {
970 }
else if (x ==
"KN_to_KN") {
972 }
else if (x ==
"KN_to_KDelta") {
974 }
else if (x ==
"Strangeness_exchange") {
976 }
else if (x ==
"NNbar") {
978 }
else if (x ==
"PiDeuteron_to_NN") {
980 }
else if (x ==
"PiDeuteron_to_pidprime") {
982 }
else if (x ==
"NDeuteron_to_Ndprime") {
984 }
else if (x ==
"Charm_T-matrix") {
988 "The value for key \"" + std::string(
key_) +
989 "\" should be \"All\", \"Elastic\", \"NN_to_NR\", \"NN_to_DR\","
990 "\"KN_to_KN\", \"KN_to_KDelta\", \"PiDeuteron_to_NN\", "
991 "\"PiDeuteron_to_pidprime\", \"NDeuteron_to_Ndprime\", "
992 "\"Strangeness_exchange\", \"NNbar\", or \"Charm_T-matrix\" "
993 "or any combination of these.");
1007 const std::vector<std::string> v =
operator std::vector<std::string>();
1009 for (
const auto &x : v) {
1013 }
else if (x ==
"Meson_3to1") {
1015 }
else if (x ==
"Deuteron_3to2") {
1017 }
else if (x ==
"NNbar_5to2") {
1019 }
else if (x ==
"A3_Nuclei_4to2") {
1023 "The value for key \"" + std::string(
key_) +
1024 "\" should be \"All\", \"Meson_3to1\", "
1025 "\"Deuteron_3to2\" or \"NNbar_5to2\", "
1026 "\"A3_Nuclei_4to2\", or any combination of "
1040 operator std::set<ThermodynamicQuantity>()
const {
1041 const std::vector<std::string> v =
operator std::vector<std::string>();
1042 std::set<ThermodynamicQuantity> s;
1043 for (
const auto &x : v) {
1044 if (x ==
"rho_eckart") {
1046 }
else if (x ==
"tmn") {
1048 }
else if (x ==
"tmn_landau") {
1050 }
else if (x ==
"landau_velocity") {
1052 }
else if (x ==
"j_QBS") {
1056 "The value for key \"" + std::string(
key_) +
1057 "\" should be \"rho_eckart\", \"tmn\""
1058 ", \"tmn_landau\", \"landau_velocity\" or \"j_QBS\".");
1072 const std::string s =
operator std::string();
1073 if (s ==
"center of velocity") {
1076 if (s ==
"center of mass") {
1079 if (s ==
"fixed target") {
1083 "The value for key \"" + std::string(
key_) +
1084 "\" should be \"center of velocity\" or \"center of mass\" "
1085 "or \"fixed target\".");
1096 const std::string s =
operator std::string();
1107 "The value for key \"" + std::string(
key_) +
1108 "\" should be \"FF1\" or \"FF2\" or \"Off\".");
1119 const std::string s =
operator std::string();
1126 if (s ==
"frozen") {
1130 "The value for key \"" + std::string(
key_) +
1131 "\" should be \"off\" or \"on\" or \"frozen\".");
1142 const std::string s =
operator std::string();
1143 if (s ==
"hadron") {
1146 if (s ==
"baryon") {
1149 if (s ==
"baryonic isospin") {
1155 if (s ==
"total isospin") {
1163 "\" should be \"hadron\" or \"baryon\" "
1164 "or \"baryonic isospin\" or \"pion\" "
1176 const std::string s =
operator std::string();
1177 if (s ==
"NoExpansion") {
1180 if (s ==
"MasslessFRW") {
1183 if (s ==
"MassiveFRW") {
1186 if (s ==
"Exponential") {
1190 "The value for key \"" + std::string(
key_) +
1191 "\" should be \"NoExpansion\", \"MasslessFRW\"," +
1192 "\"MassiveFRW\" or \"Exponential\".");
1199 const std::string s =
operator std::string();
1200 if (s ==
"Covariant Gaussian") {
1203 if (s ==
"Finite difference") {
1210 "The value for key \"" + std::string(
key_) +
1211 "\" should be \"Covariant Gaussian\", \"Finite difference\"," +
1219 const std::string s =
operator std::string();
1220 if (s ==
"Chain Rule") {
1223 if (s ==
"Direct") {
1227 "The value for key \"" + std::string(
key_) +
1228 "\" should be \"Chain Rule\" or \"Direct\".");
1235 const std::string s =
operator std::string();
1236 if (s ==
"Covariant Gaussian") {
1239 if (s ==
"Discrete") {
1242 if (s ==
"Triangular") {
1246 "The value for key \"" + std::string(
key_) +
1247 "\" should be \"Covariant Gaussian\", \"Discrete\"," +
1248 " or \"Triangular\".");
1259 const std::string s =
operator std::string();
1268 "\" should be \"None\" or \"Fixed\".");
1279 const std::string s =
operator std::string();
1280 if (s ==
"thermal momenta") {
1283 if (s ==
"thermal momenta quantum") {
1286 if (s ==
"peaked momenta") {
1290 "The value for key \"" + std::string(
key_) +
1291 "\" should be \"thermal momenta\", \"thermal momenta quantum\", " +
1292 "or \"peaked momenta\".");
1303 const std::string s =
operator std::string();
1304 if (s ==
"thermal momenta") {
1307 if (s ==
"thermal momenta quantum") {
1319 if (s ==
"IC_Massive") {
1323 "The value for key \"" + std::string(
key_) +
1324 "\" should be \"thermal momenta\", \"thermal momenta quantum\", " +
1325 "\"IC_ES\", \"IC_1M\", \"IC_2M\" or" +
"\"IC_Massive\".");
1336 const std::string s =
operator std::string();
1337 if (s ==
"no annihilation") {
1340 if (s ==
"resonances") {
1343 if (s ==
"two to five") {
1346 if (s ==
"strings") {
1350 "The value for key \"" + std::string(
key_) +
"\" should be " +
1351 "\"no annihilation\", \"resonances\", \"two to five\" or " +
1363 const std::string s =
operator std::string();
1364 if (s ==
"quadratic") {
1367 if (s ==
"custom") {
1370 if (s ==
"uniform") {
1374 "The value for key \"" + std::string(
key_) +
1375 "\" should be \"quadratic\", \"uniform\" or \"custom\".");
1386 const std::string s =
operator std::string();
1387 if (s ==
"mode sampling") {
1390 if (s ==
"biased BF") {
1393 if (s ==
"unbiased BF") {
1397 "The value for key \"" + std::string(
key_) +
1398 "\" should be \"mode sampling\", \"biased BF\" or \"unbiased BF\".");
1409 const std::string s =
operator std::string();
1410 if (s ==
"Geometric") {
1413 if (s ==
"Stochastic") {
1416 if (s ==
"Covariant") {
1420 "The value for key \"" + std::string(
key_) +
"\" should be " +
1421 "\"Geometric\", \"Stochastic\" " +
"or \"Covariant\".");
1432 const std::string c =
operator std::string();
1433 if (c ==
"T-matrix") {
1436 if (c ==
"resonances") {
1443 "The value for key \"" + std::string(
key_) +
"\" should be " +
1444 "\"T-matrix\", \"resonances\", " +
"or \"none\".");
1455 const std::string s =
operator std::string();
1461 std::string(
key_) +
"\" should be " +
1462 "\"On\" or \"Off\".");
1473 const std::string s =
operator std::string();
1475 if (s ==
"Exponential") {
1478 if (s ==
"Custom_Range") {
1485 "\"Exponential\" or \"Custom_Range\".");
1495 const std::string s =
operator std::string();
1496 if (s ==
"BottomUp") {
1499 if (s ==
"TopDown") {
1502 if (s ==
"TopDownMeasured") {
1506 "The value for key \"" + std::string(
key_) +
"\" should be " +
1507 "\"BottomUp\", \"TopDown\" " +
"or \"TopDownMeasured\".");
1518 const std::string s =
operator std::string();
1522 if (s ==
"Largest") {
1525 if (s ==
"Closest") {
1528 if (s ==
"LargestFromUnstable") {
1531 if (s ==
"ClosestFromUnstable") {
1535 "The value for key \"" + std::string(
key_) +
"\" should be " +
1536 "\"None\", \"Largest\", \"Closest\", \"LargestFromUnstable\", or "
1537 "\"ClosestFromUnstable\".");
1549 const std::string s =
operator std::string();
1550 if (s ==
"Constant_Tau") {
1552 }
else if (s ==
"Dynamic") {
1556 std::string(
key_) +
"\" should be " +
1557 "\"Constant_Tau\" or \"Dynamic\".");
1568 const std::string s =
operator std::string();
1575 if (s ==
"IfNotEmpty") {
1579 std::string(
key_) +
"\" should be " +
1580 "\"Yes\", \"No\" or \"IfNotEmpty\".");
1591 const std::vector<std::string> v =
operator std::vector<std::string>();
1593 for (
const auto &x : v) {
1597 }
else if (x ==
"Elastic") {
1599 }
else if (x ==
"Decay") {
1601 }
else if (x ==
"Inelastic") {
1603 }
else if (x ==
"SoftString") {
1605 }
else if (x ==
"HardString") {
1609 "The value for key \"" + std::string(
key_) +
1610 "\" should be \"All\", \"Elastic\", \"Decay\", "
1611 "\"Inelastic\", \"SoftString\", \"HardString\", "
1612 "or any combination of these.");
1674 template <
class Key,
class Value>
1675 struct isMap<std::map<Key, Value>> : std::true_type {};
1689 template <
typename T>
1694 throw InvalidKeyValue(
"Invalid value detected in configuration file:\n " +
1710 template <
typename T>
1728 template <
typename T>
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...
YAML::Node find_node_creating_it_if_not_existing(KeyLabels keys) const
Descend in and if needed modify the YAML tree from the given node using the provided keys.
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.
std::optional< YAML::Node > find_existing_node(KeyLabels keys) const
Descend in the YAML tree from the given node using the provided keys.
void enclose_into_section(KeyLabels section)
Enclose the configuration into the given section.
YAML::Node root_node_
The general_config.yaml contents - fully parsed.
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.
~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.
DileptonBremsPionFormFactor
Option to use form factors in dilepton bremsstrahlung as described in Shyam:2010vr .
@ FF2
Photon couples 40% directly to intrinsice quark structure of pion and 60% indirectly via meson.
@ FF1
Photon couples to pion only via meson.
@ Off
Don't use form factors, i.e. multiply by 1.
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.
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.
CharmRescattering
Possible charm scattering options.
@ T_Matrix
Charm interactions via T-matrix approach.
@ Resonances
Charm interactions via resonances.
@ None
Disable charm interactions.
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.
HardStringTransitionMode
Select the model used for the transition from soft to hard string excitation.
@ Custom_Range
Smooth transition within a user-defined invariant energy range.
@ Exponential
Legacy exponential splitting based on the hard string cross section.
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.
std::bitset< 11 > ReactionsBitSet
Container for the 2 to 2 reactions in the code.
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.
@ Value
Normal default with a value associated to it.
std::vector< std::string_view > KeyLabels
Descriptive alias for storing key labels, i.e.
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 if a Key has an invalid value.
Thrown for YAML parse errors.
Thrown if a required Key is taken/read but is missing.
Thrown if a Key is taken twice.
Utility type trait (general case) for the take and read public methods.