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