Version: SMASH-1.7
configuration.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2014-2019
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #ifndef SRC_INCLUDE_CONFIGURATION_H_
11 #define SRC_INCLUDE_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 {
314  public:
319  struct IncorrectTypeInAssignment : public std::runtime_error {
320  using std::runtime_error::runtime_error;
321  };
326  struct ParseError : public std::runtime_error {
327  using std::runtime_error::runtime_error;
328  };
329 
334  struct FileDoesNotExist : public std::runtime_error {
335  using std::runtime_error::runtime_error;
336  };
337 
345  class Value {
346  friend class Configuration;
347 
349  const YAML::Node node_;
351  const char *const key_;
352 
359  Value(const YAML::Node &n, const char *key) : node_(n), key_(key) {
360  if (!(n.IsScalar() || n.IsSequence() || n.IsMap())) {
361  std::stringstream err;
362  err << "Configuration value for \"" << key
363  << "\" is missing or invalid";
364  throw std::runtime_error(err.str());
365  }
366  }
367 
368  public:
370  Value(const Value &) = delete;
372  Value &operator=(const Value &) = delete;
373 
400  template <typename T>
401  T convert_for(const T &) const {
402  return *this;
403  }
404 
413  template <typename T>
414  operator T() const {
415  try {
416  return node_.as<T>();
417  } catch (YAML::TypedBadConversion<T> &e) {
419  "The value for key \"" + std::string(key_) +
420  "\" cannot be converted to the requested type.");
421  }
422  }
423 
429  template <typename T>
430  operator std::vector<T>() const {
431  try {
432  return node_.as<std::vector<T>>();
433  } catch (YAML::TypedBadConversion<T> &e) {
435  "One of the values in the sequence for key \"" + std::string(key_) +
436  "\" failed to convert to the requested type. E.g. [1 2] is a "
437  "sequence of one string \"1 2\" and [1, 2] is a sequence of two "
438  "integers. Often there is just a comma missing in the config "
439  "file.");
440  } catch (YAML::TypedBadConversion<std::vector<T>> &e) {
442  "The value for key \"" + std::string(key_) +
443  "\" cannot be converted to the requested type. A sequence was "
444  "expected but apparently not found.");
445  }
446  }
447 
455  template <typename T, size_t N>
456  operator std::array<T, N>() const {
457  const std::vector<T> vec = operator std::vector<T>();
458  const size_t n_read = vec.size();
459  // Alert if size does not match
460  if (n_read != N) {
461  throw IncorrectTypeInAssignment("Wrong number of values in array \"" +
462  std::string(key_) + "\". Expected " +
463  std::to_string(N) +
464  " values,"
465  " found " +
466  std::to_string(n_read) + ".");
467  }
468  std::array<T, N> arr;
469  std::copy_n(vec.begin(), N, arr.begin());
470  return arr;
471  }
472 
480  operator ReactionsBitSet() const {
481  const std::vector<std::string> v = operator std::vector<std::string>();
482  ReactionsBitSet s;
483  for (const auto &x : v) {
484  if (x == "All") {
485  s.set();
486  break;
487  } else if (x == "Elastic") {
489  } else if (x == "NN_to_NR") {
491  } else if (x == "NN_to_DR") {
493  } else if (x == "KN_to_KN") {
495  } else if (x == "KN_to_KDelta") {
497  } else if (x == "Strangeness_exchange") {
499  } else if (x == "NNbar") {
501  } else if (x == "PiDeuteron_to_NN") {
503  } else if (x == "PiDeuteron_to_pidprime") {
505  } else if (x == "NDeuteron_to_Ndprime") {
507  } else {
509  "The value for key \"" + std::string(key_) +
510  "\" should be \"All\", \"Elastic\", \"NN_to_NR\", \"NN_to_DR\","
511  "\"KN_to_KN\", \"KN_to_KDelta\", \"PiDeuteron_to_NN\", "
512  "\"PiDeuteron_to_pidprime\", \"NDeuteron_to_Ndprime\", "
513  "\"Strangeness_exchange\" or "
514  "\"NNbar\", or any combination of these.");
515  }
516  }
517  return s;
518  }
519 
527  operator std::set<ThermodynamicQuantity>() const {
528  const std::vector<std::string> v = operator std::vector<std::string>();
529  std::set<ThermodynamicQuantity> s;
530  for (const auto &x : v) {
531  if (x == "rho_eckart") {
533  } else if (x == "tmn") {
534  s.insert(ThermodynamicQuantity::Tmn);
535  } else if (x == "tmn_landau") {
537  } else if (x == "landau_velocity") {
539  } else if (x == "j_QBS") {
541  } else {
543  "The value for key \"" + std::string(key_) +
544  "\" should be \"rho_eckart\", \"tmn\""
545  ", \"tmn_landau\", \"landau_velocity\" or \"j_QBS\".");
546  }
547  }
548  return s;
549  }
550 
558  operator CalculationFrame() const {
559  const std::string s = operator std::string();
560  if (s == "center of velocity") {
562  }
563  if (s == "center of mass") {
565  }
566  if (s == "fixed target") {
568  }
570  "The value for key \"" + std::string(key_) +
571  "\" should be \"center of velocity\" or \"center of mass\" "
572  "or \"fixed target\".");
573  }
574 
582  operator FermiMotion() const {
583  const std::string s = operator std::string();
584  if (s == "off") {
585  return FermiMotion::Off;
586  }
587  if (s == "on") {
588  return FermiMotion::On;
589  }
590  if (s == "frozen") {
591  return FermiMotion::Frozen;
592  }
594  "The value for key \"" + std::string(key_) +
595  "\" should be \"off\" or \"on\" or \"frozen\".");
596  }
597 
605  operator DensityType() const {
606  const std::string s = operator std::string();
607  if (s == "hadron") {
608  return DensityType::Hadron;
609  }
610  if (s == "baryon") {
611  return DensityType::Baryon;
612  }
613  if (s == "baryonic isospin") {
614  return DensityType::BaryonicIsospin;
615  }
616  if (s == "pion") {
617  return DensityType::Pion;
618  }
619  if (s == "total isospin") {
620  return DensityType::Isospin3_tot;
621  }
622  if (s == "none") {
623  return DensityType::None;
624  }
625  throw IncorrectTypeInAssignment("The value for key \"" +
626  std::string(key_) +
627  "\" should be \"hadron\" or \"baryon\" "
628  "or \"baryonic isospin\" or \"pion\" "
629  "or \"none\".");
630  }
631 
639  operator ExpansionMode() const {
640  const std::string s = operator std::string();
641  if (s == "NoExpansion") {
643  }
644  if (s == "MasslessFRW") {
646  }
647  if (s == "MassiveFRW") {
649  }
650  if (s == "Exponential") {
652  }
654  "The value for key \"" + std::string(key_) +
655  "\" should be \"NoExpansion\", \"MasslessFRW\"," +
656  "\"MassiveFRW\" or \"Exponential\".");
657  }
658 
666  operator TimeStepMode() const {
667  const std::string s = operator std::string();
668  if (s == "None") {
669  return TimeStepMode::None;
670  }
671  if (s == "Fixed") {
672  return TimeStepMode::Fixed;
673  }
674  throw IncorrectTypeInAssignment("The value for key \"" +
675  std::string(key_) +
676  "\" should be \"None\" or \"Fixed\".");
677  }
678 
686  operator BoxInitialCondition() const {
687  const std::string s = operator std::string();
688  if (s == "thermal momenta") {
690  }
691  if (s == "peaked momenta") {
693  }
695  "The value for key \"" + std::string(key_) +
696  "\" should be \"thermal momenta\" or \"peaked momenta\".");
697  }
698 
706  operator SphereInitialCondition() const {
707  const std::string s = operator std::string();
708  if (s == "thermal momenta") {
710  }
711  if (s == "IC_ES") {
713  }
714  if (s == "IC_1M") {
716  }
717  if (s == "IC_2M") {
719  }
720  if (s == "IC_Massive") {
722  }
724  "The value for key \"" + std::string(key_) +
725  "\" should be \"thermal momenta\", \"IC_ES\", " +
726  "\"IC_1M\", \"IC_2M\" or" + "\"IC_Massive\".");
727  }
728 
736  operator NNbarTreatment() const {
737  const std::string s = operator std::string();
738  if (s == "no annihilation") {
740  }
741  if (s == "resonances") {
743  }
744  if (s == "strings") {
746  }
748  "The value for key \"" + std::string(key_) + "\" should be " +
749  "\"no annihilation\", \"detailed balance\", or \"strings\".");
750  }
751 
759  operator Sampling() const {
760  const std::string s = operator std::string();
761  if (s == "quadratic") {
762  return Sampling::Quadratic;
763  }
764  if (s == "custom") {
765  return Sampling::Custom;
766  }
767  if (s == "uniform") {
768  return Sampling::Uniform;
769  }
771  "The value for key \"" + std::string(key_) +
772  "\" should be \"quadratic\", \"uniform\" or \"custom\".");
773  }
774 
782  operator ThermalizationAlgorithm() const {
783  const std::string s = operator std::string();
784  if (s == "mode sampling") {
786  }
787  if (s == "biased BF") {
789  }
790  if (s == "unbiased BF") {
792  }
794  "The value for key \"" + std::string(key_) +
795  "\" should be \"mode sampling\", \"biased BF\" or \"unbiased BF\".");
796  }
797 
805  operator CollisionCriterion() const {
806  const std::string s = operator std::string();
807  if (s == "Geometric") {
809  }
810  if (s == "Stochastic") {
812  }
813  throw IncorrectTypeInAssignment("The value for key \"" +
814  std::string(key_) + "\" should be " +
815  "\"Geometric\" or \"Stochastic\".");
816  }
817  };
818 
824  explicit Configuration(const bf::path &path);
825 
833  explicit Configuration(const bf::path &path, const bf::path &filename);
834 
835 #ifdef BUILD_TESTS
836 
844  explicit Configuration(const char *yaml) : root_node_(YAML::Load(yaml)) {}
845 #endif
846 
848  Configuration(const Configuration &) = default;
850  Configuration &operator=(const Configuration &) = default;
851 
853  Configuration(Configuration &&) = default;
855  Configuration &operator=(Configuration &&) = default;
856 
867  void merge_yaml(const std::string &yaml);
868 
870  std::vector<std::string> list_upmost_nodes();
871 
893  Value take(std::initializer_list<const char *> keys);
894 
896  template <typename T>
897  T take(std::initializer_list<const char *> keys, T default_value) {
898  if (has_value(keys)) {
899  return take(keys);
900  }
901  return default_value;
902  }
903 
918  Value read(std::initializer_list<const char *> keys) const;
919 
921  template <typename T>
922  T read(std::initializer_list<const char *> keys, T default_value) {
923  if (has_value(keys)) {
924  return read(keys);
925  }
926  return default_value;
927  }
928 
934  void remove_all_but(const std::string &key);
935 
950  template <typename T>
952  return root_node_[std::forward<T>(key)];
953  }
954 
962  template <typename T>
963  Configuration &operator=(T &&value) {
964  root_node_ = std::forward<T>(value);
965  return *this;
966  }
967 
972  bool has_value_including_empty(
973  std::initializer_list<const char *> keys) const;
978  bool has_value(std::initializer_list<const char *> keys) const;
979 
983  std::string unused_values_report() const;
984 
990  std::string to_string() const;
991 
992  private:
999  Configuration(const YAML::Node &node) // NOLINT(runtime/explicit) : see above
1000  : root_node_(node) {}
1001 
1003  YAML::Node root_node_;
1004 };
1005 
1006 } // namespace smash
1007 
1008 #endif // SRC_INCLUDE_CONFIGURATION_H_
Configuration(const YAML::Node &node)
Creates a subobject that has its root node at the given node.
Thrown if the file does not exist.
ThermalizationAlgorithm
Defines the algorithm used for the forced thermalization.
FermiMotion
Option to use Fermi Motion.
Return type of Configuration::take that automatically determines the target type. ...
T convert_for(const T &) const
Convert the value to the type of the supplied argument.
(Default) geometric criterion.
Stochastic Criteiron.
const char *const key_
The key to be interpreted.
BoxInitialCondition
Initial condition for a particle in a box.
Value(const YAML::Node &n, const char *key)
Constructs the Value wrapper from a YAML::Node.
const YAML::Node node_
a YAML leaf node
Configuration(const char *yaml)
T take(std::initializer_list< const char * > keys, T default_value)
Interface to the SMASH configuration files.
Thrown for YAML parse errors.
NNbarTreatment
Treatment of N Nbar Annihilation.
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
Sample from uniform distribution.
SphereInitialCondition
Initial condition for a particle in a sphere.
CollisionCriterion
Criteria used to check collisions.
CalculationFrame
The calculation frame.
TimeStepMode
The time step mode.
Sample from custom, user-defined distribution.
Don&#39;t use time steps; propagate from action to action.
Configuration operator[](T &&key)
Access to the YAML::Node behind the requested keys.
Sample from areal / quadratic distribution.
Configuration & operator=(T &&value)
Assignment overwrites the value of the current YAML node.
Don&#39;t use fermi motion.
std::bitset< 10 > ReactionsBitSet
Container for the 2 to 2 reactions in the code.
Use fermi motion without potentials.
Use string fragmentation.
Use fixed time step.
Use intermediate Resonances.
ExpansionMode
Defines properties of expansion for the metric (e.g.
Sampling
Possible methods of impact parameter sampling.
Thrown when the types in the config file and C++ don&#39;t match.
YAML::Node root_node_
the general_config.yaml contents - fully parsed
constexpr int n
Neutron.
DensityType
Allows to choose which kind of density to calculate.
Definition: density.h:34
static Node encode(const T &x)
Serialization: Converts x (of any type) to a YAML::Node.
Definition: configuration.h:42
T read(std::initializer_list< const char * > keys, T default_value)
Use fermi motion in combination with potentials.
Definition: action.h:24