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