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