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 <type_traits>
8 : #include <utility>
9 : #include <vector>
10 :
11 : #include "Options/String.hpp"
12 : #include "Parallel/ExitCode.hpp"
13 : #include "Parallel/PhaseControl/PhaseChange.hpp"
14 : #include "ParallelAlgorithms/EventsAndTriggers/Trigger.hpp"
15 : #include "Utilities/Serialization/Serialize.hpp"
16 : #include "Utilities/TMPL.hpp"
17 :
18 : namespace PhaseControl {
19 :
20 : /// Option-creatable pair of a trigger and associated phase change objects.
21 1 : struct TriggerAndPhaseChanges {
22 0 : struct Trigger {
23 0 : using type = std::unique_ptr<::Trigger>;
24 0 : static constexpr Options::String help =
25 : "Determines when the phase changes are evaluated.";
26 : };
27 0 : struct PhaseChanges {
28 0 : using type = std::vector<std::unique_ptr<::PhaseChange>>;
29 0 : static constexpr Options::String help =
30 : "These phase changes are evaluated when the Trigger fires.";
31 : };
32 0 : static constexpr Options::String help =
33 : "Phase changes that are evaluated when the Trigger fires.";
34 0 : using options = tmpl::list<Trigger, PhaseChanges>;
35 :
36 0 : TriggerAndPhaseChanges();
37 0 : TriggerAndPhaseChanges(
38 : std::unique_ptr<::Trigger> trigger_in,
39 : std::vector<std::unique_ptr<::PhaseChange>> phase_changes_in);
40 0 : void pup(PUP::er& p);
41 0 : std::unique_ptr<::Trigger> trigger{};
42 0 : std::vector<std::unique_ptr<::PhaseChange>> phase_changes{};
43 : };
44 :
45 0 : namespace OptionTags {
46 : /// Option tag for the collection of triggers that indicate synchronization
47 : /// points at which phase changes should be considered, and the associated
48 : /// `PhaseChange` objects for making the phase change decisions.
49 : ///
50 : /// When the phase control is arbitrated on the main chare, the `PhaseChange`
51 : /// objects will be queried for their phase request in order of appearance in
52 : /// the nested list (i.e. first all of the `PhaseChange`s associated with the
53 : /// first trigger, in order, then those associated with the second trigger,
54 : /// etc.). The order therefore determines the order of resolution of
55 : /// simultaneous requests.
56 1 : struct PhaseChangeAndTriggers {
57 0 : static constexpr Options::String help{
58 : "A collection of pairs of triggers and collections of phase change "
59 : "objects to determine runtime phase control-flow decisions. The order of "
60 : "the phase change objects determines the order of the requests processed "
61 : "by the Main chare during phase change arbitration."};
62 :
63 0 : using type = std::vector<TriggerAndPhaseChanges>;
64 : };
65 : } // namespace OptionTags
66 :
67 : namespace Tags {
68 : /// Tag for the collection of triggers that indicate synchronization points at
69 : /// which phase changes should be considered, and the associated `PhaseChange`
70 : /// objects for making the phase change decisions.
71 1 : struct PhaseChangeAndTriggers : db::SimpleTag {
72 0 : using type = std::vector<TriggerAndPhaseChanges>;
73 :
74 0 : using option_tags = tmpl::list<OptionTags::PhaseChangeAndTriggers>;
75 0 : static constexpr bool is_overlayable = true;
76 0 : static constexpr bool pass_metavariables = false;
77 0 : static type create_from_options(const type& phase_control_and_triggers) {
78 : return serialize_and_deserialize<type>(phase_control_and_triggers);
79 : }
80 : };
81 : } // namespace Tags
82 :
83 0 : namespace TagsAndCombines {
84 : /// A tag for indicating that a halt was called by a trigger associated with
85 : /// `PhaseChange`s.
86 : ///
87 : /// This is needed to disambiguate different quiescence conditions in the main
88 : /// chare. It is automatically included in
89 : /// `PhaseControl::get_phase_change_tags`, so shouldn't be explicitly included
90 : /// in the `phase_change_tags_and_combines` in derived classes of
91 : /// `PhaseChange`.
92 1 : struct UsePhaseChangeArbitration {
93 0 : using type = bool;
94 0 : using combine_method = funcl::Or<>;
95 0 : using main_combine_method = combine_method;
96 : };
97 : } // namespace TagsAndCombines
98 :
99 : namespace detail {
100 : template <typename Metavariables, typename = std::void_t<>>
101 : struct phase_change_derived_classes {
102 : using type = tmpl::list<>;
103 : };
104 :
105 : template <typename Metavariables>
106 : struct phase_change_derived_classes<
107 : Metavariables,
108 : std::void_t<typename Metavariables::factory_creation::factory_classes>> {
109 : private:
110 : using factory_entry =
111 : tmpl::at<typename Metavariables::factory_creation::factory_classes,
112 : PhaseChange>;
113 :
114 : public:
115 : using type =
116 : tmpl::conditional_t<std::is_same_v<factory_entry, tmpl::no_such_type_>,
117 : tmpl::list<>, factory_entry>;
118 : };
119 :
120 : template <typename PhaseChangeDerived>
121 : struct get_phase_change_tags_and_combines {
122 : using type = typename PhaseChangeDerived::phase_change_tags_and_combines;
123 : };
124 : } // namespace detail
125 :
126 : /// Metafunction for determining the merged collection of tags in
127 : /// `phase_change_tags_and_combines`s from all `PhaseChange` derived
128 : /// classes in `Metavariables::factory_creation`
129 : template <typename Metavariables>
130 1 : using get_phase_change_tags = tmpl::push_back<
131 : tmpl::flatten<tmpl::transform<
132 : typename detail::phase_change_derived_classes<Metavariables>::type,
133 : detail::get_phase_change_tags_and_combines<tmpl::_1>>>,
134 : TagsAndCombines::UsePhaseChangeArbitration, Parallel::Tags::ExitCode>;
135 : } // namespace PhaseControl
|