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 deserialize<type>( 79 : serialize<type>(phase_control_and_triggers).data()); 80 : } 81 : }; 82 : } // namespace Tags 83 : 84 0 : namespace TagsAndCombines { 85 : /// A tag for indicating that a halt was called by a trigger associated with 86 : /// `PhaseChange`s. 87 : /// 88 : /// This is needed to disambiguate different quiescence conditions in the main 89 : /// chare. It is automatically included in 90 : /// `PhaseControl::get_phase_change_tags`, so shouldn't be explicitly included 91 : /// in the `phase_change_tags_and_combines` in derived classes of 92 : /// `PhaseChange`. 93 1 : struct UsePhaseChangeArbitration { 94 0 : using type = bool; 95 0 : using combine_method = funcl::Or<>; 96 0 : using main_combine_method = combine_method; 97 : }; 98 : } // namespace TagsAndCombines 99 : 100 : namespace detail { 101 : template <typename Metavariables, typename = std::void_t<>> 102 : struct phase_change_derived_classes { 103 : using type = tmpl::list<>; 104 : }; 105 : 106 : template <typename Metavariables> 107 : struct phase_change_derived_classes< 108 : Metavariables, 109 : std::void_t<typename Metavariables::factory_creation::factory_classes>> { 110 : private: 111 : using factory_entry = 112 : tmpl::at<typename Metavariables::factory_creation::factory_classes, 113 : PhaseChange>; 114 : 115 : public: 116 : using type = 117 : tmpl::conditional_t<std::is_same_v<factory_entry, tmpl::no_such_type_>, 118 : tmpl::list<>, factory_entry>; 119 : }; 120 : 121 : template <typename PhaseChangeDerived> 122 : struct get_phase_change_tags_and_combines { 123 : using type = typename PhaseChangeDerived::phase_change_tags_and_combines; 124 : }; 125 : } // namespace detail 126 : 127 : /// Metafunction for determining the merged collection of tags in 128 : /// `phase_change_tags_and_combines`s from all `PhaseChange` derived 129 : /// classes in `Metavariables::factory_creation` 130 : template <typename Metavariables> 131 1 : using get_phase_change_tags = tmpl::push_back< 132 : tmpl::flatten<tmpl::transform< 133 : typename detail::phase_change_derived_classes<Metavariables>::type, 134 : detail::get_phase_change_tags_and_combines<tmpl::_1>>>, 135 : TagsAndCombines::UsePhaseChangeArbitration, Parallel::Tags::ExitCode>; 136 : } // namespace PhaseControl