RegisterEvents.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <cstddef>
7 #include <optional>
8 #include <unordered_map>
9 
11 #include "IO/Observer/Actions/ObserverRegistration.hpp"
12 #include "IO/Observer/ArrayComponentId.hpp"
13 #include "IO/Observer/ObserverComponent.hpp"
14 #include "IO/Observer/Tags.hpp"
15 #include "IO/Observer/TypeOfObservation.hpp"
16 #include "Parallel/GlobalCache.hpp"
17 #include "Parallel/Invoke.hpp"
19 #include "Utilities/Gsl.hpp"
20 #include "Utilities/TMPL.hpp"
21 #include "Utilities/TaggedTuple.hpp"
22 #include "Utilities/TypeTraits/CreateHasTypeAlias.hpp"
23 
24 namespace observers {
25 namespace detail {
26 CREATE_HAS_TYPE_ALIAS(observation_registration_tags)
27 CREATE_HAS_TYPE_ALIAS_V(observation_registration_tags)
28 } // namespace detail
29 
30 /*!
31  * \brief Retrieves the observation type and key from an event, if it is an
32  * event that needs to register with the observers.
33  *
34  * The event must define an `observation_registration_tags` type alias that is a
35  * `tmpl::list<>` of all the tags from the DataBox needed to construct the
36  * `ObservationKey`, and a `get_observation_type_and_key_for_registration`
37  * member function if it is to be registered automatically.
38  */
39 template <typename EventRegistrars, typename DbTagsList>
42 get_registration_observation_type_and_key(
43  const Event<EventRegistrars>& event,
44  const db::DataBox<DbTagsList>& box) noexcept {
47  result{};
48  bool already_registered = false;
49  tmpl::for_each<typename Event<EventRegistrars>::creatable_classes>(
50  [&already_registered, &box, &event, &result](auto event_type_v) noexcept {
51  using EventType = typename decltype(event_type_v)::type;
52  if constexpr (detail::has_observation_registration_tags_v<EventType>) {
53  // We require that each event for which
54  // `has_observation_registration_tags_v` is true be downcastable to
55  // only *one* event type. This is checked by the `already_registered`
56  // bool and the error message below. We need to downcast because we do
57  // not want to impose that every event be registerable with the
58  // IO/observer components. `dynamic_cast` returns a `nullptr` in the
59  // case that the downcast failed, which we check for to see if we can
60  // call the `get_observation_type_and_key_for_registration` function.
61  const auto* const derived_class_ptr =
62  dynamic_cast<const EventType*>(&event);
63  if (derived_class_ptr != nullptr) {
64  if (already_registered) {
65  ERROR(
66  "Already registered the event by casting down to a "
67  "different Event derived class. This means you have an "
68  "Event where A inherits from B and both A and B define "
69  "get_observation_type_and_id_for_registration. This "
70  "behavior is not supported. Please make a separate Event.");
71  }
72  already_registered = true;
73  result =
74  db::apply<typename EventType::observation_registration_tags>(
75  [&derived_class_ptr](const auto&... args) noexcept {
76  return derived_class_ptr
77  ->get_observation_type_and_key_for_registration(
78  args...);
79  },
80  box);
81  }
82  }
83  });
84  return result;
85 }
86 
87 namespace Actions {
88 /*!
89  * \brief Registers this element of a parallel component with the local
90  * `Observer` parallel component for each triggered observation.
91  *
92  * \details This tells the `Observer` to expect data from this component, as
93  * well as whether each observation is a Reduction or Volume observation.
94  * Should be added to the phase dependent action list of the components that
95  * contribute data for volume and reduction observations.
96  */
98  template <typename DbTagList, typename... InboxTags, typename Metavariables,
99  typename ArrayIndex, typename ActionList,
100  typename ParallelComponent>
101  static std::tuple<db::DataBox<DbTagList>&&> apply(
102  db::DataBox<DbTagList>& box,
103  const tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
105  const ArrayIndex& array_index, const ActionList /*meta*/,
106  const ParallelComponent* const /*meta*/) noexcept {
107  auto& observer =
108  *Parallel::get_parallel_component<observers::Observer<Metavariables>>(
109  cache)
110  .ckLocalBranch();
111  std::vector<
113  type_of_observation_and_observation_key_pairs;
114 
115  const auto& triggers_and_events =
116  db::get<::Tags::EventsAndTriggersBase>(box);
117  for (const auto& trigger_and_events :
118  triggers_and_events.events_and_triggers()) {
119  for (const auto& event : trigger_and_events.second) {
120  if (auto obs_type_and_obs_key =
121  get_registration_observation_type_and_key(*event, box);
122  obs_type_and_obs_key.has_value()) {
123  type_of_observation_and_observation_key_pairs.push_back(
124  *obs_type_and_obs_key);
125  }
126  }
127  }
128 
129  for (const auto& [type_of_observation, observation_key] :
130  type_of_observation_and_observation_key_pairs) {
131  Parallel::simple_action<RegisterContributorWithObserver>(
132  observer, observation_key,
136  type_of_observation);
137  }
138  return {std::move(box)};
139  }
140 };
141 } // namespace Actions
142 } // namespace observers
observers::Actions::RegisterEventsWithObservers
Registers this element of a parallel component with the local Observer parallel component for each tr...
Definition: RegisterEvents.hpp:97
Parallel::GlobalCache
Definition: ElementReceiveInterpPoints.hpp:15
Tags.hpp
std::pair
GlobalCache.hpp
std::vector
std::tuple
ERROR
#define ERROR(m)
prints an error message to the standard error stream and aborts the program.
Definition: Error.hpp:36
CREATE_HAS_TYPE_ALIAS
#define CREATE_HAS_TYPE_ALIAS(ALIAS_NAME)
Generate a type trait to check if a class has a type alias with a particular name,...
Definition: CreateHasTypeAlias.hpp:27
std::add_pointer_t
Event
Definition: Event.hpp:30
DataBox.hpp
cstddef
tuples::TaggedTuple
An associative container that is indexed by structs.
Definition: TaggedTuple.hpp:271
Gsl.hpp
optional
observers::ArrayComponentId
An ID type that identifies both the parallel component and the index in the parallel component.
Definition: ArrayComponentId.hpp:27
Parallel::ArrayIndex
The array index used for indexing Chare Arrays, mostly an implementation detail.
Definition: ArrayIndex.hpp:27
unordered_map
TMPL.hpp