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 : };
|