Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <algorithm> 7 : #include <memory> 8 : #include <optional> 9 : #include <pup.h> 10 : #include <vector> 11 : 12 : #include "Options/Options.hpp" 13 : #include "Options/ParseOptions.hpp" 14 : #include "Options/String.hpp" 15 : #include "ParallelAlgorithms/EventsAndDenseTriggers/DenseTrigger.hpp" 16 : #include "Time/EvolutionOrdering.hpp" 17 : #include "Time/TimeStepId.hpp" 18 : #include "Utilities/Algorithm.hpp" 19 : #include "Utilities/Gsl.hpp" 20 : #include "Utilities/Serialization/CharmPupable.hpp" 21 : #include "Utilities/TMPL.hpp" 22 : 23 : /// \cond 24 : namespace Parallel { 25 : template <typename Metavariables> 26 : class GlobalCache; 27 : } // namespace Parallel 28 : namespace Tags { 29 : struct DataBox; 30 : struct TimeStepId; 31 : } // namespace Tags 32 : namespace db { 33 : template <typename TagsList> 34 : class DataBox; 35 : } // namespace db 36 : /// \endcond 37 : 38 : namespace DenseTriggers { 39 : /// \ingroup EventsAndTriggersGroup 40 : /// Trigger when any of a collection of DenseTriggers triggers. 41 1 : class Or : public DenseTrigger { 42 : public: 43 : /// \cond 44 : Or() = default; 45 : explicit Or(CkMigrateMessage* const msg) : DenseTrigger(msg) {} 46 : using PUP::able::register_constructor; 47 : WRAPPED_PUPable_decl_template(Or); // NOLINT 48 : /// \endcond 49 : 50 0 : static constexpr Options::String help = 51 : "Trigger when any of a collection of triggers triggers."; 52 : 53 0 : explicit Or(std::vector<std::unique_ptr<DenseTrigger>> triggers); 54 : 55 0 : using is_triggered_return_tags = tmpl::list<Tags::DataBox>; 56 0 : using is_triggered_argument_tags = tmpl::list<>; 57 : 58 : template <typename Metavariables, typename ArrayIndex, typename Component, 59 : typename DbTags> 60 0 : std::optional<bool> is_triggered( 61 : Parallel::GlobalCache<Metavariables>& cache, 62 : const ArrayIndex& array_index, const Component* component, 63 : const gsl::not_null<db::DataBox<DbTags>*> box) const { 64 : bool is_ready = true; 65 : for (const auto& trigger : triggers_) { 66 : const auto sub_result = 67 : trigger->is_triggered(box, cache, array_index, component); 68 : if (sub_result.has_value()) { 69 : if (*sub_result) { 70 : // No need to wait for all the other triggers to be ready. 71 : return true; 72 : } 73 : } else { 74 : is_ready = false; 75 : } 76 : } 77 : return is_ready ? std::optional{false} : std::nullopt; 78 : } 79 : 80 0 : using next_check_time_return_tags = tmpl::list<Tags::DataBox>; 81 0 : using next_check_time_argument_tags = tmpl::list<Tags::TimeStepId>; 82 : 83 : template <typename Metavariables, typename ArrayIndex, typename Component, 84 : typename DbTags> 85 0 : std::optional<double> next_check_time( 86 : Parallel::GlobalCache<Metavariables>& cache, 87 : const ArrayIndex& array_index, const Component* component, 88 : const gsl::not_null<db::DataBox<DbTags>*>& box, 89 : const TimeStepId& time_step_id) const { 90 : const evolution_less<double> before{time_step_id.time_runs_forward()}; 91 : double result = before.infinity(); 92 : for (const auto& trigger : triggers_) { 93 : const auto sub_result = 94 : trigger->next_check_time(box, cache, array_index, component); 95 : if (not sub_result.has_value()) { 96 : return std::nullopt; 97 : } 98 : result = std::min(*sub_result, result, before); 99 : } 100 : return result; 101 : } 102 : 103 : // NOLINTNEXTLINE(google-runtime-references) 104 0 : void pup(PUP::er& p) override; 105 : 106 : private: 107 0 : std::vector<std::unique_ptr<DenseTrigger>> triggers_{}; 108 : }; 109 : } // namespace DenseTriggers 110 : 111 : template <> 112 0 : struct Options::create_from_yaml<DenseTriggers::Or> { 113 : template <typename Metavariables> 114 0 : static DenseTriggers::Or create(const Option& options) { 115 : return DenseTriggers::Or( 116 : options.parse_as<std::vector<std::unique_ptr<DenseTrigger>>, 117 : Metavariables>()); 118 : } 119 : };