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::Next<::Tags::TimeStep>, ::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<TimeDelta*> next_time_step, 84 : const gsl::not_null<TimeStepId*> local_time_step_id) { 85 : *next_time_step_id = new_next_time_step_id; 86 : *time_step = new_step; 87 : *next_time_step = new_step; 88 : *local_time_step_id = inbox_time_step_id; 89 : }, 90 : make_not_null(&box)); 91 : } 92 : return {Parallel::AlgorithmExecution::Continue, std::nullopt}; 93 : } 94 : }; 95 : } // namespace CurvedScalarWave::Worldtube::Actions