Version: SMASH-3.1
smash::anonymous_namespace{configuration.cc} Namespace Reference

Classes

struct  IsStdMap
 A utility type to be specialized to check if a type is a std::map . More...
 
struct  IsStdMap< std::map< MapKey, MapValue > >
 A specialization of IsStdMap<T> for cases where the boolean value should be set to true. More...
 

Functions

void descend_one_existing_level (std::optional< YAML::Node > &node, std::string_view key)
 Reset the passed in node to that one at the provided key, which is expected to exist in the node. More...
 
YAML::Node remove_empty_maps (YAML::Node root)
 Remove all empty maps of a YAML::Node. More...
 
YAML::Node operator|= (YAML::Node a, const YAML::Node &b)
 Merge two YAML::Nodes. More...
 
std::string join_quoted (std::initializer_list< const char * > keys)
 Build a string with a list of keys as specified in the code. More...
 
void fill_list_of_labels_per_key_in_yaml_tree (const YAML::Node &root_node, std::vector< KeyLabels > &list, KeyLabels &new_list_entry)
 Implementation of the algorithm to translate a YAML tree into lists of labels, each identifying a key from the YAML root node. More...
 
auto get_list_of_labels_per_key_in_yaml_tree (const YAML::Node &root_node)
 Create a list of lists of key labels present in the passed YAML node considered to be the root one of a YAML tree. More...
 
auto collect_input_keys_taken_as_maps ()
 Extract from the InputKeys database the labels of keys that have a std::map as type. More...
 
void adjust_list_of_labels_dealing_with_keys_taken_as_maps (std::vector< KeyLabels > &list_of_input_key_labels)
 Remove last labels of keys that are taken as maps in SMASH and remove duplicates from the resulting list. More...
 
Configuration::Is validate_key (const KeyLabels &labels)
 Given some YAML labels (assumed to be in order from the top section), it is checked whether any valid SMASH key with the same key exists. More...
 
void accumulate_validation (Configuration::Is &result_so_far, Configuration::Is new_value)
 Utility function to accumulate validation results of keys. More...
 

Function Documentation

◆ descend_one_existing_level()

void smash::anonymous_namespace{configuration.cc}::descend_one_existing_level ( std::optional< YAML::Node > &  node,
std::string_view  key 
)

Reset the passed in node to that one at the provided key, which is expected to exist in the node.

If this is not the case, the node is set to std::nullopt.

Parameters
[in,out]nodeAn optional node to be reset.
[in]keyThe key expected to exist in the given node.

Definition at line 38 of file configuration.cc.

39  {
40  if (node) {
41  for (const auto &section : node.value()) {
42  /* Two remarks:
43  1) The Node::operator[] creates an undefined node in the YAML tree if
44  the node corresponding to the passed key does not exist and hence
45  in this function, which descend one level which is expected to
46  exist, we need to use it only if we are sure the node exists.
47  2) Node::reset does what you might expect Node::operator= to do. But
48  operator= assigns a value to the node and so
49  node = node[key]
50  would lead to a further modification of the data structure and
51  this function would not be simply traversal. Note that node and
52  root_node_ point to the same memory and modification to the first
53  would affect the second, too. */
54  if (section.first.Scalar() == key) {
55  node.value().reset(node.value()[key]);
56  return;
57  }
58  }
59  node = std::nullopt;
60  }
61 }

◆ remove_empty_maps()

YAML::Node smash::anonymous_namespace{configuration.cc}::remove_empty_maps ( YAML::Node  root)

Remove all empty maps of a YAML::Node.

Parameters
[in]rootYAML::Node that contains empty maps.
Returns
YAML::Node from above without empty maps.

Definition at line 69 of file configuration.cc.

69  {
70  if (root.IsMap()) {
71  std::vector<std::string> to_remove(root.size());
72  for (auto n : root) {
73  remove_empty_maps(n.second);
74  // If the node is an empty sequence, we do NOT remove it!
75  if (n.second.IsMap() && n.second.size() == 0) {
76  to_remove.emplace_back(n.first.Scalar());
77  }
78  }
79  for (const auto &key : to_remove) {
80  root.remove(key);
81  }
82  }
83  return root;
84 }
YAML::Node remove_empty_maps(YAML::Node root)
Remove all empty maps of a YAML::Node.
constexpr int n
Neutron.

◆ operator|=()

YAML::Node smash::anonymous_namespace{configuration.cc}::operator|= ( YAML::Node  a,
const YAML::Node &  b 
)

Merge two YAML::Nodes.

Parameters
[in]aYAML::Node into which b is merged.
[in]bYAML::Node that is merged into a.
Returns
YAML::Node which is the merge of a and b.

Definition at line 93 of file configuration.cc.

93  {
94  if (b.IsMap()) {
95  for (auto n0 : b) {
96  a[n0.first.Scalar()] |= n0.second;
97  }
98  } else {
99  a = b;
100  }
101  return a;
102 }

◆ join_quoted()

std::string smash::anonymous_namespace{configuration.cc}::join_quoted ( std::initializer_list< const char * >  keys)

Build a string with a list of keys as specified in the code.

Parameters
keysThe list of keys.
Returns
A std::string with the desired result.

Definition at line 110 of file configuration.cc.

110  {
111  return std::accumulate(keys.begin(), keys.end(), std::string{"{"},
112  [](const std::string &ss, const std::string &s) {
113  return ss + ((ss.size() == 1) ? "\"" : ", \"") + s +
114  "\"";
115  }) +
116  "}";
117 }

◆ fill_list_of_labels_per_key_in_yaml_tree()

void smash::anonymous_namespace{configuration.cc}::fill_list_of_labels_per_key_in_yaml_tree ( const YAML::Node &  root_node,
std::vector< KeyLabels > &  list,
KeyLabels new_list_entry 
)

Implementation of the algorithm to translate a YAML tree into lists of labels, each identifying a key from the YAML root node.

Since the level of nesting sections in a YAML input file is arbitrary, this is a typical task to be solved using recursion. The main idea here is to take advantage of YAML functionality and in particular of the possibility to iterate over trees and test for nature of a node (is it a Map or not?). Roughly speaking, from the tree top-level all upmost nodes are extracted and for each of them, recursively, the same procedure is done over and over again if they are maps. If a non-map node is found, i.e. a key value is found, then recursion ends and a new entry is added to list .

Parameters
[in]root_nodeThe root YAML node to extract from.
[in,out]listThe list of lists of labels to be filled.
[in,out]new_list_entryNew list of labels in process to be filled during recursion.

Definition at line 370 of file configuration.cc.

372  {
373  // Here sub_node is an iterator value, i.e. a key/value pair of nodes,
374  // not a single YAML node (that's how YAML library works)
375  for (const auto &sub_node : root_node) {
376  new_list_entry.push_back(sub_node.first.as<std::string>());
377  if (sub_node.second.IsMap())
378  fill_list_of_labels_per_key_in_yaml_tree(sub_node.second, list,
379  new_list_entry);
380  else
381  list.push_back(new_list_entry);
382  new_list_entry.pop_back();
383  }
384 }
void fill_list_of_labels_per_key_in_yaml_tree(const YAML::Node &root_node, std::vector< KeyLabels > &list, KeyLabels &new_list_entry)
Implementation of the algorithm to translate a YAML tree into lists of labels, each identifying a key...

◆ get_list_of_labels_per_key_in_yaml_tree()

auto smash::anonymous_namespace{configuration.cc}::get_list_of_labels_per_key_in_yaml_tree ( const YAML::Node &  root_node)

Create a list of lists of key labels present in the passed YAML node considered to be the root one of a YAML tree.

Given a YAML::Node, for each key having a value, all labels to reach the given key from the passed node are collected and a std::vector containing them is built and inserted into the given list. This function is calling the actual implementation preparing auxiliary needed variables.

Parameters
[in]root_nodeThe root node of the YAML tree to be considered.
Returns
A std::vector<KeyLabels> containing the desired information.

Definition at line 399 of file configuration.cc.

399  {
400  std::vector<KeyLabels> list{};
401  KeyLabels aux{};
402  fill_list_of_labels_per_key_in_yaml_tree(root_node, list, aux);
403  return list;
404 }
std::vector< std::string > KeyLabels
Descriptive alias for storing key labels, i.e.
Definition: input_keys.h:39

◆ collect_input_keys_taken_as_maps()

auto smash::anonymous_namespace{configuration.cc}::collect_input_keys_taken_as_maps ( )

Extract from the InputKeys database the labels of keys that have a std::map as type.

Returns
A list of key labels.

Definition at line 443 of file configuration.cc.

443  {
444  std::vector<KeyLabels> labels_of_keys_taken_as_map{};
445  for (const auto &keys_variant : smash::InputKeys::list) {
446  std::visit(
447  [&labels_of_keys_taken_as_map](auto &&var) {
448  /*
449  * The following if checks if the SMASH input key has a map as value
450  * and it deserves some explanation about the type extraction:
451  *
452  * - arg -> object of type: std::cref(const Key<T>)
453  * - arg.get() -> object of type: const Key<T>&
454  * - decltype(arg.get()) -> type: const Key<T>&
455  * - std::decay_t<decltype(arg.get())>::type -> type: Key<T>
456  * - std::decay_t<decltype(arg.get())>::type::value -> type: T
457  */
458  if constexpr (IsStdMap<typename std::decay_t<
459  decltype(var.get())>::type>::value)
460  labels_of_keys_taken_as_map.push_back(var.get().labels());
461  },
462  keys_variant);
463  }
464  return labels_of_keys_taken_as_map;
465 }
static const std::vector< key_references_variant > list
List of references to all existing SMASH keys.
Definition: input_keys.h:5244

◆ adjust_list_of_labels_dealing_with_keys_taken_as_maps()

void smash::anonymous_namespace{configuration.cc}::adjust_list_of_labels_dealing_with_keys_taken_as_maps ( std::vector< KeyLabels > &  list_of_input_key_labels)

Remove last labels of keys that are taken as maps in SMASH and remove duplicates from the resulting list.

The keys that are taken as maps in SMASH are here collected using the database InputKeys and the list of keys contained in the configuration must be adjusted by hand. This is a corner case, since YAML nodes that are maps are by definition sections and cannot be distinguished from keys "with a map value" in the recursive process to create the list of key labels.

Parameters
[in,out]list_of_input_key_labelsThe list of key labels to adjust.

Definition at line 479 of file configuration.cc.

480  {
481  const std::vector<KeyLabels> labels_of_keys_taken_as_map =
483  for (const auto &labels : labels_of_keys_taken_as_map) {
484  std::for_each(list_of_input_key_labels.begin(),
485  list_of_input_key_labels.end(),
486  [&labels](KeyLabels &labels_of_input_key) {
487  if (std::equal(labels.begin(), labels.end(),
488  labels_of_input_key.begin(),
489  labels_of_input_key.begin() + labels.size()))
490  labels_of_input_key = labels;
491  });
492  }
493  // The identical keys in list are now next to each other and we do
494  // not need/want to sort the list before calling std::unique.
495  list_of_input_key_labels.erase(std::unique(list_of_input_key_labels.begin(),
496  list_of_input_key_labels.end()),
497  list_of_input_key_labels.end());
498 }
auto collect_input_keys_taken_as_maps()
Extract from the InputKeys database the labels of keys that have a std::map as type.
UnaryFunction for_each(Container &&c, UnaryFunction &&f)
Convenience wrapper for std::for_each that operates on a complete container.
Definition: algorithms.h:96

◆ validate_key()

Configuration::Is smash::anonymous_namespace{configuration.cc}::validate_key ( const KeyLabels labels)

Given some YAML labels (assumed to be in order from the top section), it is checked whether any valid SMASH key with the same key exists.

All possible checks are done in a way such that the user is informed about

  • if the key has never been valid;
  • if the key was valid in the past but it has been removed;
  • if the key is valid but deprecated.
Parameters
[in]labelsThe series of labels identifying the key.
Returns
Configuration::Is::Valid if the key is valid;
Configuration::Is::Deprecated if the key is Deprecated and
Configuration::Is::Invalid if the key is invalid.

Definition at line 515 of file configuration.cc.

515  {
516  auto key_ref_var_it = std::find_if(
518  [&labels](auto key) {
519  return std::visit(
520  [&labels](auto &&arg) { return arg.get().has_same_labels(labels); },
521  key);
522  });
523  if (key_ref_var_it == smash::InputKeys::list.end()) {
524  logg[LConfiguration].error("Key ", smash::quote(smash::join(labels, ": ")),
525  " is not a valid SMASH input key.");
526  return Configuration::Is::Invalid;
527  }
528 
529  smash::InputKeys::key_references_variant found_variant = *key_ref_var_it;
530  const auto key_labels =
531  std::visit([](auto &&var) { return static_cast<std::string>(var.get()); },
532  found_variant);
533 
534  if (std::visit([](auto &&var) { return !var.get().is_allowed(); },
535  found_variant)) {
536  const auto v_removal = std::visit(
537  [](auto &&var) { return var.get().removed_in(); }, found_variant);
538  logg[LConfiguration].error("Key ", key_labels,
539  " has been removed in version ", v_removal,
540  " and it is not valid anymore.");
541  return Configuration::Is::Invalid;
542  }
543  if (std::visit([](auto &&var) { return var.get().is_deprecated(); },
544  found_variant)) {
545  const auto v_deprecation = std::visit(
546  [](auto &&var) { return var.get().deprecated_in(); }, found_variant);
547  logg[LConfiguration].warn(
548  "Key ", key_labels, " has been deprecated in version ", v_deprecation);
549  return Configuration::Is::Deprecated;
550  } else {
551  logg[LConfiguration].debug("Key ", key_labels, " is valid!");
552  return Configuration::Is::Valid;
553  }
554 }
std::array< einhard::Logger<>, std::tuple_size< LogArea::AreaTuple >::value > logg
An array that stores all pre-configured Logger objects.
Definition: logging.cc:39
std::string quote(const std::string &s)
Add quotes around string.
static constexpr int LConfiguration
std::string join(const std::vector< std::string > &v, const std::string &delim)
Join strings using delimiter.
std::variant< std::reference_wrapper< const Key< bool > >, std::reference_wrapper< const Key< int > >, std::reference_wrapper< const Key< double > >, std::reference_wrapper< const Key< std::string > >, std::reference_wrapper< const Key< std::array< int, 3 > >>, std::reference_wrapper< const Key< std::array< double, 2 > >>, std::reference_wrapper< const Key< std::array< double, 3 > >>, std::reference_wrapper< const Key< std::pair< double, double > >>, std::reference_wrapper< const Key< std::vector< double > >>, std::reference_wrapper< const Key< std::vector< std::string > >>, std::reference_wrapper< const Key< std::set< ThermodynamicQuantity > >>, std::reference_wrapper< const Key< std::map< PdgCode, int > >>, std::reference_wrapper< const Key< std::map< std::string, std::string > >>, std::reference_wrapper< const Key< einhard::LogLevel > >, std::reference_wrapper< const Key< BoxInitialCondition > >, std::reference_wrapper< const Key< CalculationFrame > >, std::reference_wrapper< const Key< CollisionCriterion > >, std::reference_wrapper< const Key< DensityType > >, std::reference_wrapper< const Key< DerivativesMode > >, std::reference_wrapper< const Key< ExpansionMode > >, std::reference_wrapper< const Key< FermiMotion > >, std::reference_wrapper< const Key< FieldDerivativesMode > >, std::reference_wrapper< const Key< MultiParticleReactionsBitSet > >, std::reference_wrapper< const Key< NNbarTreatment > >, std::reference_wrapper< const Key< OutputOnlyFinal > >, std::reference_wrapper< const Key< PdgCode > >, std::reference_wrapper< const Key< PseudoResonance > >, std::reference_wrapper< const Key< ReactionsBitSet > >, std::reference_wrapper< const Key< RestFrameDensityDerivativesMode > >, std::reference_wrapper< const Key< Sampling > >, std::reference_wrapper< const Key< SmearingMode > >, std::reference_wrapper< const Key< SphereInitialCondition > >, std::reference_wrapper< const Key< ThermalizationAlgorithm > >, std::reference_wrapper< const Key< TimeStepMode > >, std::reference_wrapper< const Key< TotalCrossSectionStrategy > >> key_references_variant
Alias for the type to be used in the list of keys.
Definition: input_keys.h:5241

◆ accumulate_validation()

void smash::anonymous_namespace{configuration.cc}::accumulate_validation ( Configuration::Is result_so_far,
Configuration::Is  new_value 
)

Utility function to accumulate validation results of keys.

This is basically the logic needed to make a full validation of a configuration, considered that we have three possible states. It extend the logical AND between two boolean values.

Parameters
[in,out]result_so_farStatus of the configuration so far to be combined with the new key state.
[in]new_valueNew key state to be considered.

Definition at line 567 of file configuration.cc.

568  {
569  switch (result_so_far) {
570  case Configuration::Is::Invalid:
571  break;
572  case Configuration::Is::Deprecated:
573  if (new_value != Configuration::Is::Valid) {
574  result_so_far = new_value;
575  }
576  break;
577  case Configuration::Is::Valid:
578  result_so_far = new_value;
579  break;
580  }
581 }