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