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 <memory>
8 :
9 : #include "DataStructures/DataBox/DataBox.hpp"
10 : #include "DataStructures/DataBox/Prefixes.hpp"
11 : #include "Evolution/Systems/CurvedScalarWave/Worldtube/Inboxes.hpp"
12 : #include "Evolution/Systems/CurvedScalarWave/Worldtube/Tags.hpp"
13 : #include "Parallel/AlgorithmExecution.hpp"
14 : #include "Parallel/GlobalCache.hpp"
15 : #include "ParallelAlgorithms/EventsAndTriggers/Tags.hpp"
16 : #include "Time/TimeStepId.hpp"
17 : #include "Utilities/Gsl.hpp"
18 : #include "Utilities/TMPL.hpp"
19 :
20 : /// \cond
21 : namespace Tags {
22 : struct TimeStep;
23 : struct TimeStepId;
24 : template <typename StepperInterface>
25 : struct TimeStepper;
26 : } // namespace Tags
27 : class TimeStepper;
28 : /// \endcond
29 :
30 : namespace CurvedScalarWave::Worldtube::Actions {
31 :
32 : /*!
33 : * \brief Waits for the data from all neighboring elements and changes the slab
34 : * size if a change in the global time step is detected.
35 : * \details We check the slab size of the time step id sent by the elements. If
36 : * this is different from the slab size currently used by the worldtube
37 : * singleton, we assume a global slab size change has occurred in the elements
38 : * and adjust the worldtube slab size accordingly.
39 : */
40 1 : struct ChangeSlabSize {
41 0 : static constexpr size_t Dim = 3;
42 0 : using inbox_tags = tmpl::list<
43 : ::CurvedScalarWave::Worldtube::Tags::SphericalHarmonicsInbox<Dim>>;
44 :
45 : template <typename DbTagsList, typename... InboxTags, typename Metavariables,
46 : typename ArrayIndex, typename ActionList,
47 : typename ParallelComponent>
48 0 : static Parallel::iterable_action_return_t apply(
49 : db::DataBox<DbTagsList>& box, tuples::TaggedTuple<InboxTags...>& inboxes,
50 : const Parallel::GlobalCache<Metavariables>& /*cache*/,
51 : const ArrayIndex& /*array_index*/, ActionList /*meta*/,
52 : const ParallelComponent* const /*meta*/) {
53 : const auto& time_step_id = db::get<::Tags::TimeStepId>(box);
54 : const auto& inbox =
55 : tuples::get<Tags::SphericalHarmonicsInbox<Dim>>(inboxes);
56 : if (inbox.empty()) {
57 : return {Parallel::AlgorithmExecution::Retry, std::nullopt};
58 : }
59 : ASSERT(inbox.size() == 1,
60 : "Received data from two different time step ids.");
61 : const auto inbox_time_step_id = inbox.begin()->first;
62 : const auto& inbox_slab = inbox_time_step_id.step_time().slab();
63 : // we received data from a time step id with a different slab size,
64 : // indicating a change in the global time step.
65 : if (inbox_time_step_id.step_time().slab() !=
66 : time_step_id.step_time().slab()) {
67 : ASSERT(inbox_slab.start() == time_step_id.step_time().slab().start(),
68 : "The new slab should start at the same time as the old one.");
69 : // time_step_id comparison does NOT compare slabs.
70 : ASSERT(
71 : inbox_time_step_id == time_step_id,
72 : "Detected change in global time step id but the new time step id is "
73 : "different.");
74 : const auto new_step = inbox_slab.duration();
75 : const auto new_next_time_step_id =
76 : db::get<::Tags::TimeStepper<TimeStepper>>(box).next_time_id(
77 : inbox_time_step_id, new_step);
78 : db::mutate<::Tags::Next<::Tags::TimeStepId>, ::Tags::TimeStep,
79 : ::Tags::TimeStepId>(
80 : [&new_next_time_step_id, &new_step, &inbox_time_step_id](
81 : const gsl::not_null<TimeStepId*> next_time_step_id,
82 : const gsl::not_null<TimeDelta*> time_step,
83 : const gsl::not_null<TimeStepId*> local_time_step_id) {
84 : *next_time_step_id = new_next_time_step_id;
85 : *time_step = new_step;
86 : *local_time_step_id = inbox_time_step_id;
87 : },
88 : make_not_null(&box));
89 : }
90 : return {Parallel::AlgorithmExecution::Continue, std::nullopt};
91 : }
92 : };
93 : } // namespace CurvedScalarWave::Worldtube::Actions
|