Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <memory>
7 : #include <optional>
8 : #include <pup.h>
9 : #include <vector>
10 :
11 : #include "DataStructures/DataBox/DataBox.hpp"
12 : #include "DataStructures/DataBox/ObservationBox.hpp"
13 : #include "Options/Options.hpp"
14 : #include "Options/String.hpp"
15 : #include "ParallelAlgorithms/EventsAndTriggers/Event.hpp"
16 : #include "ParallelAlgorithms/EventsAndTriggers/Trigger.hpp"
17 : #include "Utilities/Gsl.hpp"
18 : #include "Utilities/TMPL.hpp"
19 :
20 : /// \cond
21 : namespace Parallel {
22 : template <typename Metavariables>
23 : class GlobalCache;
24 : } // namespace Parallel
25 : namespace db {
26 : template <typename TagsList>
27 : class DataBox;
28 : } // namespace db
29 : /// \endcond
30 :
31 : /// \ingroup EventsAndTriggersGroup
32 : /// Class that checks triggers and runs events
33 1 : class EventsAndTriggers {
34 : private:
35 : template <typename Event>
36 0 : struct get_tags {
37 0 : using type = typename Event::compute_tags_for_observation_box;
38 : };
39 :
40 : public:
41 0 : struct TriggerAndEvents {
42 0 : struct Trigger {
43 0 : using type = std::unique_ptr<::Trigger>;
44 0 : static constexpr Options::String help = "Determines when the Events run.";
45 : };
46 0 : struct Events {
47 0 : using type = std::vector<std::unique_ptr<::Event>>;
48 0 : static constexpr Options::String help =
49 : "These events run when the Trigger fires.";
50 : };
51 0 : static constexpr Options::String help =
52 : "Events that run when the Trigger fires.";
53 0 : using options = tmpl::list<Trigger, Events>;
54 0 : TriggerAndEvents();
55 0 : TriggerAndEvents(std::unique_ptr<::Trigger> trigger_in,
56 : std::vector<std::unique_ptr<::Event>> events_in);
57 0 : void pup(PUP::er& p);
58 0 : std::unique_ptr<::Trigger> trigger;
59 0 : std::vector<std::unique_ptr<::Event>> events;
60 : };
61 :
62 0 : using Storage = std::vector<TriggerAndEvents>;
63 :
64 0 : EventsAndTriggers();
65 0 : explicit EventsAndTriggers(Storage events_and_triggers);
66 :
67 : /// Check the triggers and run the associated events.
68 : ///
69 : /// By default the trigger check just calls the `is_triggered`
70 : /// method, but the last argument can be passed to override this.
71 : /// It must be a functor taking a `const Trigger&` and returning
72 : /// `bool`.
73 : template <typename DbTags, typename Metavariables, typename ArrayIndex,
74 : typename Component, typename CheckTrigger = std::nullptr_t>
75 1 : void run_events(const gsl::not_null<db::DataBox<DbTags>*> box,
76 : Parallel::GlobalCache<Metavariables>& cache,
77 : const ArrayIndex& array_index, const Component* component,
78 : const Event::ObservationValue& observation_value,
79 : const CheckTrigger& check_trigger = nullptr) const {
80 : using compute_tags = tmpl::remove_duplicates<tmpl::filter<
81 : tmpl::flatten<tmpl::transform<
82 : tmpl::at<typename Metavariables::factory_creation::factory_classes,
83 : Event>,
84 : get_tags<tmpl::_1>>>,
85 : db::is_compute_tag<tmpl::_1>>>;
86 : std::optional<decltype(make_observation_box<compute_tags>(box))>
87 : observation_box{};
88 : for (const auto& trigger_and_events : events_and_triggers_) {
89 : const auto& trigger = trigger_and_events.trigger;
90 : const auto& events = trigger_and_events.events;
91 : const bool is_triggered = [&]() {
92 : if constexpr (std::is_same_v<std::decay_t<CheckTrigger>,
93 : std::nullptr_t>) {
94 : return trigger->is_triggered(*box);
95 : } else {
96 : return check_trigger(std::as_const(*trigger));
97 : }
98 : }();
99 : if (is_triggered) {
100 : if (not observation_box.has_value()) {
101 : observation_box = make_observation_box<compute_tags>(box);
102 : }
103 : for (const auto& event : events) {
104 : event->run(make_not_null(&observation_box.value()), cache,
105 : array_index, component, observation_value);
106 : }
107 : }
108 : }
109 : }
110 :
111 : // NOLINTNEXTLINE(google-runtime-references)
112 0 : void pup(PUP::er& p);
113 :
114 : template <typename F>
115 0 : void for_each_event(F&& f) const {
116 : for (const auto& trigger_and_events : events_and_triggers_) {
117 : for (const auto& event : trigger_and_events.events) {
118 : f(*event);
119 : }
120 : }
121 : }
122 :
123 : private:
124 : // The unique pointer contents *must* be treated as const everywhere
125 : // in order to make the const global cache behave sanely. They are
126 : // only non-const to make pup work.
127 0 : Storage events_and_triggers_;
128 : };
129 :
130 : template <>
131 0 : struct Options::create_from_yaml<EventsAndTriggers> {
132 0 : using type = EventsAndTriggers;
133 : template <typename Metavariables>
134 0 : static type create(const Options::Option& options) {
135 : return type(options.parse_as<typename type::Storage, Metavariables>());
136 : }
137 : };
|