Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <cstddef>
7 : #include <cstdint>
8 : #include <map>
9 : #include <optional>
10 : #include <vector>
11 :
12 : #include "DataStructures/DataBox/DataBox.hpp"
13 : #include "Parallel/AlgorithmExecution.hpp"
14 : #include "Time/ChangeSlabSize/ChangeSlabSize.hpp"
15 : #include "Time/ChangeSlabSize/Tags.hpp"
16 : #include "Time/Tags/HistoryEvolvedVariables.hpp"
17 : #include "Time/Tags/MinimumTimeStep.hpp"
18 : #include "Time/TimeStepRequestProcessor.hpp"
19 : #include "Time/TimeSteppers/TimeStepper.hpp"
20 : #include "Utilities/Algorithm.hpp"
21 : #include "Utilities/ErrorHandling/Assert.hpp"
22 : #include "Utilities/Numeric.hpp"
23 : #include "Utilities/TMPL.hpp"
24 :
25 : /// \cond
26 : namespace Parallel {
27 : template <typename Metavariables>
28 : class GlobalCache;
29 : } // namespace Parallel
30 : namespace Tags {
31 : struct TimeStep;
32 : struct TimeStepId;
33 : template <typename StepperInterface>
34 : struct TimeStepper;
35 : } // namespace Tags
36 : namespace tuples {
37 : template <class... Tags>
38 : class TaggedTuple;
39 : } // namespace tuples
40 : /// \endcond
41 :
42 : namespace Actions {
43 : /// \ingroup ActionsGroup
44 : /// \ingroup TimeGroup
45 : /// Adjust the slab size based on previous executions of
46 : /// Events::ChangeSlabSize
47 : ///
48 : /// Uses:
49 : /// - DataBox:
50 : /// - Tags::HistoryEvolvedVariables
51 : /// - Tags::TimeStep
52 : /// - Tags::TimeStepId
53 : /// - Tags::TimeStepper<TimeStepper>
54 : ///
55 : /// DataBox changes:
56 : /// - Adds: nothing
57 : /// - Removes: nothing
58 : /// - Modifies:
59 : /// - Tags::Next<Tags::TimeStepId>
60 : /// - Tags::TimeStep
61 : /// - Tags::TimeStepId
62 1 : struct ChangeSlabSize {
63 0 : using const_global_cache_tags = tmpl::list<::Tags::MinimumTimeStep>;
64 0 : using simple_tags =
65 : tmpl::list<::Tags::ChangeSlabSize::NewSlabSize,
66 : ::Tags::ChangeSlabSize::NumberOfExpectedMessages>;
67 :
68 : template <typename DbTags, typename... InboxTags, typename Metavariables,
69 : typename ArrayIndex, typename ActionList,
70 : typename ParallelComponent>
71 0 : static Parallel::iterable_action_return_t apply(
72 : db::DataBox<DbTags>& box, tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
73 : const Parallel::GlobalCache<Metavariables>& /*cache*/,
74 : const ArrayIndex& /*array_index*/, const ActionList /*meta*/,
75 : const ParallelComponent* const /*meta*/) {
76 : const auto& time_step_id = db::get<::Tags::TimeStepId>(box);
77 : if (not time_step_id.is_at_slab_boundary()) {
78 : return {Parallel::AlgorithmExecution::Continue, std::nullopt};
79 : }
80 :
81 : TimeStepRequestProcessor step_requests(time_step_id.time_runs_forward());
82 :
83 : const auto slab_number = time_step_id.slab_number();
84 : const auto& expected_messages_map =
85 : db::get<::Tags::ChangeSlabSize::NumberOfExpectedMessages>(box);
86 : if (not expected_messages_map.empty() and
87 : expected_messages_map.begin()->first == slab_number) {
88 : const size_t expected_messages = expected_messages_map.begin()->second;
89 : ASSERT(expected_messages > 0,
90 : "Should only create map entries when sending messages.");
91 :
92 : const auto& slab_size_messages =
93 : db::get<::Tags::ChangeSlabSize::NewSlabSize>(box);
94 : if (slab_size_messages.empty()) {
95 : return {Parallel::AlgorithmExecution::Retry, std::nullopt};
96 : }
97 : const int64_t first_received_change_slab =
98 : slab_size_messages.begin()->first;
99 :
100 : ASSERT(first_received_change_slab >= slab_number,
101 : "Received data for a change at slab " << first_received_change_slab
102 : << " but it is already slab " << slab_number);
103 : if (first_received_change_slab != slab_number) {
104 : return {Parallel::AlgorithmExecution::Retry, std::nullopt};
105 : }
106 :
107 : const auto& received_changes = slab_size_messages.begin()->second;
108 : ASSERT(expected_messages >= received_changes.size(),
109 : "Received " << received_changes.size()
110 : << " size change messages at slab " << slab_number
111 : << ", but only expected " << expected_messages);
112 : if (received_changes.size() != expected_messages) {
113 : return {Parallel::AlgorithmExecution::Retry, std::nullopt};
114 : }
115 :
116 : // We have all the data we need.
117 :
118 : step_requests =
119 : alg::accumulate(slab_size_messages.begin()->second, step_requests);
120 :
121 : db::mutate<::Tags::ChangeSlabSize::NumberOfExpectedMessages,
122 : ::Tags::ChangeSlabSize::NewSlabSize>(
123 : [](const gsl::not_null<std::map<int64_t, size_t>*> expected,
124 : const gsl::not_null<
125 : std::map<int64_t, std::vector<TimeStepRequestProcessor>>*>
126 : sizes) {
127 : expected->erase(expected->begin());
128 : sizes->erase(sizes->begin());
129 : },
130 : make_not_null(&box));
131 : }
132 : const double new_slab_end = step_requests.step_end(
133 : time_step_id.step_time().value(),
134 : db::get<::Tags::ChangeSlabSize::SlabSizeGoal>(box));
135 :
136 : if (const auto new_goal = step_requests.new_step_size_goal();
137 : new_goal.has_value()) {
138 : db::mutate<::Tags::ChangeSlabSize::SlabSizeGoal>(
139 : [&](const gsl::not_null<double*> slab_size_goal) {
140 : *slab_size_goal = *new_goal;
141 : },
142 : make_not_null(&box));
143 : }
144 :
145 : const TimeStepper& time_stepper =
146 : db::get<::Tags::TimeStepper<TimeStepper>>(box);
147 :
148 : // Sometimes time steppers need to run with a fixed step size.
149 : // This is generally at the start of an evolution when the history
150 : // is in an unusual state.
151 : if (tmpl::as_pack<::Tags::get_all_history_tags<DbTags>>(
152 : [&]<typename... HistoryTags>(tmpl::type_<HistoryTags>... /*meta*/) {
153 : return (... and time_stepper.can_change_step_size(
154 : time_step_id, db::get<HistoryTags>(box)));
155 : })) {
156 : change_slab_size(make_not_null(&box), new_slab_end);
157 : }
158 :
159 : step_requests.error_on_hard_limit(
160 : db::get<::Tags::TimeStep>(box).value(),
161 : (time_step_id.step_time() + db::get<::Tags::TimeStep>(box)).value());
162 : return {Parallel::AlgorithmExecution::Continue, std::nullopt};
163 : }
164 : };
165 : } // namespace Actions
|