Line data Source code
1 1 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : /// \file 5 : /// Defines action UpdateU 6 : 7 : #pragma once 8 : 9 : #include <optional> 10 : #include <tuple> 11 : #include <utility> 12 : 13 : #include "DataStructures/DataBox/DataBox.hpp" 14 : #include "DataStructures/DataBox/Prefixes.hpp" 15 : #include "Parallel/AlgorithmExecution.hpp" 16 : #include "Time/SelfStart.hpp" 17 : #include "Time/StepperErrorTolerances.hpp" 18 : #include "Time/Tags/HistoryEvolvedVariables.hpp" 19 : #include "Time/Tags/StepperErrors.hpp" 20 : #include "Time/Time.hpp" 21 : #include "Time/TimeSteppers/TimeStepper.hpp" 22 : #include "Utilities/Gsl.hpp" 23 : #include "Utilities/TMPL.hpp" 24 : #include "Utilities/TaggedTuple.hpp" 25 : #include "Utilities/TypeTraits/IsA.hpp" 26 : 27 : /// \cond 28 : namespace Parallel { 29 : template <typename Metavariables> 30 : class GlobalCache; 31 : } // namespace Parallel 32 : namespace Tags { 33 : struct IsUsingTimeSteppingErrorControl; 34 : template <typename Tag> 35 : struct StepperErrorTolerances; 36 : struct TimeStep; 37 : struct TimeStepId; 38 : template <typename StepperInterface> 39 : struct TimeStepper; 40 : } // namespace Tags 41 : /// \endcond 42 : 43 : namespace update_u_detail { 44 : template <typename System, typename VariablesTag, typename DbTags> 45 : void update_one_variables(const gsl::not_null<db::DataBox<DbTags>*> box) { 46 : using history_tag = Tags::HistoryEvolvedVariables<VariablesTag>; 47 : bool is_using_error_control = false; 48 : if constexpr (db::tag_is_retrievable_v<Tags::IsUsingTimeSteppingErrorControl, 49 : db::DataBox<DbTags>>) { 50 : is_using_error_control = 51 : db::get<Tags::IsUsingTimeSteppingErrorControl>(*box); 52 : } 53 : if (is_using_error_control) { 54 : using error_tag = ::Tags::StepperErrors<VariablesTag>; 55 : if constexpr (tmpl::list_contains_v<DbTags, error_tag>) { 56 : db::mutate<VariablesTag, error_tag>( 57 : [&](const gsl::not_null<typename VariablesTag::type*> vars, 58 : const gsl::not_null<typename error_tag::type*> errors, 59 : const typename history_tag::type& history, 60 : const ::TimeDelta& time_step, const TimeStepper& time_stepper, 61 : const std::optional<StepperErrorTolerances>& tolerances) { 62 : const auto error = 63 : time_stepper.update_u(vars, history, time_step, tolerances); 64 : if (error.has_value()) { 65 : // Save the previous errors, but not if this is a retry 66 : // of the same step. 67 : if ((*errors)[1]->step_time != error->step_time) { 68 : (*errors)[0] = (*errors)[1]; 69 : } 70 : (*errors)[1].emplace(*error); 71 : } 72 : }, 73 : box, db::get<history_tag>(*box), db::get<Tags::TimeStep>(*box), 74 : db::get<Tags::TimeStepper<TimeStepper>>(*box), 75 : db::get<Tags::StepperErrorTolerances<VariablesTag>>(*box)); 76 : } else { 77 : ERROR( 78 : "Cannot update the stepper error measure -- " 79 : "`::Tags::StepperErrors<VariablesTag>` is not present in the box."); 80 : } 81 : } else { 82 : db::mutate<VariablesTag>( 83 : [](const gsl::not_null<typename VariablesTag::type*> vars, 84 : const typename history_tag::type& history, 85 : const ::TimeDelta& time_step, const TimeStepper& time_stepper) { 86 : time_stepper.update_u(vars, history, time_step); 87 : }, 88 : box, db::get<history_tag>(*box), db::get<Tags::TimeStep>(*box), 89 : db::get<Tags::TimeStepper<TimeStepper>>(*box)); 90 : } 91 : } 92 : } // namespace update_u_detail 93 : 94 : /// Perform variable updates for one substep for a substep method, or one step 95 : /// for an LMM method. 96 : /// 97 : /// \note This is a free function version of `Actions::UpdateU`. This free 98 : /// function alternative permits the inclusion of the time step procedure in 99 : /// the middle of another action. 100 : template <typename System, typename DbTags> 101 1 : void update_u(const gsl::not_null<db::DataBox<DbTags>*> box) { 102 : if (::SelfStart::step_unused(db::get<Tags::TimeStepId>(*box), 103 : db::get<Tags::Next<Tags::TimeStepId>>(*box))) { 104 : return; 105 : } 106 : 107 : if constexpr (tt::is_a_v<tmpl::list, typename System::variables_tag>) { 108 : // The system has multiple evolved variables, probably because 109 : // there is a mixture of real and complex values or similar. Step 110 : // all of them. 111 : tmpl::for_each<typename System::variables_tag>([&](auto tag) { 112 : update_u_detail::update_one_variables<System, 113 : tmpl::type_from<decltype(tag)>>( 114 : box); 115 : }); 116 : } else { 117 : update_u_detail::update_one_variables<System, 118 : typename System::variables_tag>(box); 119 : } 120 : } 121 : 122 : namespace Actions { 123 : /// \ingroup ActionsGroup 124 : /// \ingroup TimeGroup 125 : /// \brief Perform variable updates for one substep 126 : /// 127 : /// Uses: 128 : /// - DataBox: 129 : /// - system::variables_tag 130 : /// - Tags::HistoryEvolvedVariables<variables_tag> 131 : /// - Tags::TimeStep 132 : /// - Tags::TimeStepper<TimeStepper> 133 : /// - Tags::IsUsingTimeSteppingErrorControl 134 : /// 135 : /// DataBox changes: 136 : /// - Adds: nothing 137 : /// - Removes: nothing 138 : /// - Modifies: 139 : /// - variables_tag 140 : template <typename System> 141 1 : struct UpdateU { 142 : template <typename DbTags, typename... InboxTags, typename Metavariables, 143 : typename ArrayIndex, typename ActionList, 144 : typename ParallelComponent> 145 0 : static Parallel::iterable_action_return_t apply( 146 : db::DataBox<DbTags>& box, tuples::TaggedTuple<InboxTags...>& /*inboxes*/, 147 : const Parallel::GlobalCache<Metavariables>& /*cache*/, 148 : const ArrayIndex& /*array_index*/, ActionList /*meta*/, 149 : const ParallelComponent* const /*meta*/) { // NOLINT const 150 : update_u<System>(make_not_null(&box)); 151 : return {Parallel::AlgorithmExecution::Continue, std::nullopt}; 152 : } 153 : }; 154 : } // namespace Actions