Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <array> 7 : #include <cstddef> 8 : #include <memory> 9 : #include <optional> 10 : #include <string> 11 : #include <tuple> 12 : #include <unordered_map> 13 : #include <utility> 14 : 15 : #include "DataStructures/DataBox/DataBox.hpp" 16 : #include "Domain/FunctionsOfTime/FunctionOfTime.hpp" 17 : #include "Parallel/AlgorithmExecution.hpp" 18 : #include "Parallel/Callback.hpp" 19 : #include "Parallel/GlobalCache.hpp" 20 : #include "Utilities/Algorithm.hpp" 21 : #include "Utilities/ErrorHandling/Assert.hpp" 22 : #include "Utilities/StdHelpers.hpp" 23 : 24 : /// \cond 25 : namespace Tags { 26 : struct Time; 27 : } // namespace Tags 28 : namespace domain::Tags { 29 : struct FunctionsOfTime; 30 : } // namespace domain::Tags 31 : namespace tuples { 32 : template <class... Tags> 33 : class TaggedTuple; 34 : } // namespace tuples 35 : /// \endcond 36 : 37 : namespace domain { 38 : /// \ingroup ComputationalDomainGroup 39 : /// Check that functions of time are up-to-date. 40 : /// 41 : /// Check that functions of time in \p CacheTag with names in \p 42 : /// functions_to_check are ready at time \p time. If no names are 43 : /// listed in \p functions_to_check, checks all functions in \p 44 : /// CacheTag. If any function is not ready, schedules a 45 : /// `Parallel::PerformAlgorithmCallback` with the GlobalCache. 46 : template <typename CacheTag, typename Metavariables, typename ArrayIndex, 47 : typename Component, size_t N = 0> 48 1 : bool functions_of_time_are_ready( 49 : Parallel::GlobalCache<Metavariables>& cache, const ArrayIndex& array_index, 50 : const Component* /*meta*/, const double time, 51 : const std::array<std::string, N>& functions_to_check = 52 : std::array<std::string, 0>{}) { 53 : const auto& proxy = 54 : ::Parallel::get_parallel_component<Component>(cache)[array_index]; 55 : 56 : return Parallel::mutable_cache_item_is_ready<CacheTag>( 57 : cache, [&functions_to_check, &proxy, 58 : &time](const std::unordered_map< 59 : std::string, 60 : std::unique_ptr<domain::FunctionsOfTime::FunctionOfTime>>& 61 : functions_of_time) { 62 : using ::operator<<; 63 : ASSERT(alg::all_of( 64 : functions_to_check, 65 : [&functions_of_time](const std::string& function_to_check) { 66 : return functions_of_time.count(function_to_check) == 1; 67 : }), 68 : "Not all functions to check (" 69 : << functions_to_check << ") are in the global cache (" 70 : << keys_of(functions_of_time) << ")"); 71 : for (const auto& [name, f_of_t] : functions_of_time) { 72 : if ((not functions_to_check.empty()) and 73 : alg::find(functions_to_check, name) == functions_to_check.end()) { 74 : continue; 75 : } 76 : const double expiration_time = f_of_t->time_bounds()[1]; 77 : if (time > expiration_time) { 78 : return std::unique_ptr<Parallel::Callback>( 79 : new Parallel::PerformAlgorithmCallback(proxy)); 80 : } 81 : } 82 : return std::unique_ptr<Parallel::Callback>{}; 83 : }); 84 : } 85 : 86 0 : namespace Actions { 87 : /// \ingroup ComputationalDomainGroup 88 : /// Check that functions of time are up-to-date. 89 : /// 90 : /// Wait for all functions of time in `domain::Tags::FunctionsOfTime` 91 : /// to be ready at `::Tags::Time`. This ensures that the coordinates 92 : /// can be safely accessed in later actions without first verifying 93 : /// the state of the time-dependent maps. 94 1 : struct CheckFunctionsOfTimeAreReady { 95 : template <typename DbTags, typename... InboxTags, typename Metavariables, 96 : typename ArrayIndex, typename ActionList, 97 : typename ParallelComponent> 98 0 : static Parallel::iterable_action_return_t apply( 99 : db::DataBox<DbTags>& box, tuples::TaggedTuple<InboxTags...>& /*inboxes*/, 100 : Parallel::GlobalCache<Metavariables>& cache, 101 : const ArrayIndex& array_index, ActionList /*meta*/, 102 : const ParallelComponent* component) { 103 : const bool ready = 104 : functions_of_time_are_ready<domain::Tags::FunctionsOfTime>( 105 : cache, array_index, component, db::get<::Tags::Time>(box)); 106 : return {ready ? Parallel::AlgorithmExecution::Continue 107 : : Parallel::AlgorithmExecution::Retry, 108 : std::nullopt}; 109 : } 110 : }; 111 : } // namespace Actions 112 : 113 : /// \ingroup ComputationalDomainGroup Dense-output postprocessor to 114 : /// check that functions of time are up-to-date. 115 : /// 116 : /// Check that all functions of time in 117 : /// `domain::Tags::FunctionsOfTime` are ready at `::Tags::Time`. This 118 : /// ensures that the coordinates can be safely accessed in later 119 : /// actions without first verifying the state of the time-dependent 120 : /// maps. This postprocessor does not actually modify anything. 121 1 : struct CheckFunctionsOfTimeAreReadyPostprocessor { 122 0 : using return_tags = tmpl::list<>; 123 0 : using argument_tags = tmpl::list<>; 124 0 : static void apply() {} 125 : 126 : template <typename DbTagsList, typename... InboxTags, typename Metavariables, 127 : typename ArrayIndex, typename ParallelComponent> 128 0 : static bool is_ready( 129 : const gsl::not_null<db::DataBox<DbTagsList>*> box, 130 : const gsl::not_null<tuples::TaggedTuple<InboxTags...>*> /*inboxes*/, 131 : Parallel::GlobalCache<Metavariables>& cache, 132 : const ArrayIndex& array_index, const ParallelComponent* component) { 133 : return functions_of_time_are_ready<domain::Tags::FunctionsOfTime>( 134 : cache, array_index, component, db::get<::Tags::Time>(*box)); 135 : } 136 : }; 137 : } // namespace domain