Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <optional> 7 : #include <pup.h> 8 : #include <string> 9 : #include <type_traits> 10 : #include <utility> 11 : 12 : #include "Evolution/Systems/GeneralizedHarmonic/Bbh/CompletionCriteria.hpp" 13 : #include "Options/String.hpp" 14 : #include "Parallel/GlobalCache.hpp" 15 : #include "Parallel/Phase.hpp" 16 : #include "Parallel/PhaseControl/ContributeToPhaseChangeReduction.hpp" 17 : #include "Parallel/PhaseControl/PhaseChange.hpp" 18 : #include "Utilities/ErrorHandling/Error.hpp" 19 : #include "Utilities/Functional.hpp" 20 : #include "Utilities/Serialization/CharmPupable.hpp" 21 : #include "Utilities/TMPL.hpp" 22 : #include "Utilities/TaggedTuple.hpp" 23 : 24 0 : namespace gh::bbh::phase_control { 25 0 : namespace Tags { 26 : /// Storage in the phase-change decision tuple for whether the 27 : /// BBH completion path has requested completion. 28 1 : struct CheckpointRequested { 29 0 : using type = bool; 30 0 : using combine_method = funcl::Or<>; 31 0 : using main_combine_method = funcl::Or<>; 32 : }; 33 : 34 : /// Storage in the phase-change decision tuple for jumping from 35 : /// `WriteCheckpoint` to `Exit`. 36 1 : struct ExitAfterWriteCheckpoint { 37 0 : using type = bool; 38 : 39 0 : struct combine_method { 40 0 : bool operator()(const bool /*first*/, const bool /*second*/) { 41 : ERROR( 42 : "ExitAfterWriteCheckpoint should only be modified during " 43 : "phase-change arbitration on Main."); 44 : } 45 : }; 46 : 47 0 : using main_combine_method = combine_method; 48 : }; 49 : } // namespace Tags 50 : 51 : /*! 52 : * \brief If BBH completion has been requested, jump from `Evolve` to 53 : * `WriteCheckpoint`, then immediately to `Exit`. 54 : * 55 : * \details The `WriteCheckpoint` phase executes checkpoint actions, typically 56 : * including final volume data writes, as specified by 57 : * `EventsAndTriggersAtCheckpoints`. 58 : */ 59 1 : struct CheckpointAndExitIfComplete : public PhaseChange { 60 : /// \cond 61 : CheckpointAndExitIfComplete() = default; 62 : explicit CheckpointAndExitIfComplete(CkMigrateMessage* /*unused*/) {} 63 : using PUP::able::register_constructor; 64 : WRAPPED_PUPable_decl_template(CheckpointAndExitIfComplete); // NOLINT 65 : /// \endcond 66 : 67 0 : static std::string name() { return "BbhCheckpointAndExitIfComplete"; } 68 0 : using options = tmpl::list<>; 69 0 : static constexpr Options::String help{ 70 : "When BBH completion has been requested, jump from Evolve to " 71 : "WriteCheckpoint so all elements write final volume data at a " 72 : "synchronized time, then jump to Exit."}; 73 : 74 0 : using argument_tags = tmpl::list<gh::bbh::Tags::ElementCompletionRequested>; 75 0 : using return_tags = tmpl::list<>; 76 : 77 0 : using phase_change_tags_and_combines = 78 : tmpl::list<Tags::CheckpointRequested, Tags::ExitAfterWriteCheckpoint>; 79 : 80 : template <typename Metavariables> 81 0 : using participating_components = typename Metavariables::component_list; 82 : 83 : template <typename... DecisionTags> 84 0 : void initialize_phase_data_impl( 85 : const gsl::not_null<tuples::TaggedTuple<DecisionTags...>*> 86 : phase_change_decision_data) const { 87 : tuples::get<Tags::CheckpointRequested>(*phase_change_decision_data) = false; 88 : tuples::get<Tags::ExitAfterWriteCheckpoint>(*phase_change_decision_data) = 89 : false; 90 : } 91 : 92 : template <typename ParallelComponent, typename ArrayIndex, 93 : typename Metavariables> 94 0 : void contribute_phase_data_impl(const bool element_completion_requested, 95 : Parallel::GlobalCache<Metavariables>& cache, 96 : const ArrayIndex& array_index) const { 97 : if constexpr (std::is_same_v<typename ParallelComponent::chare_type, 98 : Parallel::Algorithms::Array>) { 99 : Parallel::contribute_to_phase_change_reduction<ParallelComponent>( 100 : tuples::TaggedTuple<Tags::CheckpointRequested>{ 101 : element_completion_requested}, 102 : cache, array_index); 103 : } else { 104 : Parallel::contribute_to_phase_change_reduction<ParallelComponent>( 105 : tuples::TaggedTuple<Tags::CheckpointRequested>{ 106 : element_completion_requested}, 107 : cache); 108 : } 109 : } 110 : 111 : template <typename... DecisionTags, typename Metavariables> 112 : std::optional<std::pair<Parallel::Phase, PhaseControl::ArbitrationStrategy>> 113 0 : arbitrate_phase_change_impl( 114 : const gsl::not_null<tuples::TaggedTuple<DecisionTags...>*> 115 : phase_change_decision_data, 116 : const Parallel::Phase current_phase, 117 : const Parallel::GlobalCache<Metavariables>& /*cache*/) const { 118 : auto& checkpoint_requested = 119 : tuples::get<Tags::CheckpointRequested>(*phase_change_decision_data); 120 : auto& exit_after_write_checkpoint = 121 : tuples::get<Tags::ExitAfterWriteCheckpoint>( 122 : *phase_change_decision_data); 123 : 124 : if (current_phase == Parallel::Phase::WriteCheckpoint and 125 : exit_after_write_checkpoint) { 126 : exit_after_write_checkpoint = false; 127 : return std::make_pair( 128 : Parallel::Phase::Exit, 129 : PhaseControl::ArbitrationStrategy::RunPhaseImmediately); 130 : } 131 : 132 : if (current_phase == Parallel::Phase::Evolve and checkpoint_requested) { 133 : checkpoint_requested = false; 134 : exit_after_write_checkpoint = true; 135 : return std::make_pair( 136 : Parallel::Phase::WriteCheckpoint, 137 : PhaseControl::ArbitrationStrategy::RunPhaseImmediately); 138 : } 139 : 140 : checkpoint_requested = false; 141 : return std::nullopt; 142 : } 143 : 144 : // NOLINTNEXTLINE(google-runtime-references) 145 0 : void pup(PUP::er& p) override; 146 : }; 147 : } // namespace gh::bbh::phase_control