Line data Source code
1 1 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : /// \file 5 : /// Defines action AdvanceTime 6 : 7 : #pragma once 8 : 9 : #include <optional> 10 : #include <tuple> 11 : 12 : #include "DataStructures/DataBox/DataBox.hpp" 13 : #include "Parallel/AlgorithmExecution.hpp" 14 : #include "Time/AdaptiveSteppingDiagnostics.hpp" 15 : #include "Time/Tags/AdaptiveSteppingDiagnostics.hpp" 16 : #include "Time/Time.hpp" 17 : #include "Time/TimeStepId.hpp" 18 : #include "Time/TimeSteppers/TimeStepper.hpp" 19 : #include "Utilities/Gsl.hpp" 20 : #include "Utilities/TaggedTuple.hpp" 21 : 22 : /// \cond 23 : namespace Parallel { 24 : template <typename Metavariables> 25 : class GlobalCache; 26 : } // namespace Parallel 27 : namespace Tags { 28 : struct IsUsingTimeSteppingErrorControl; 29 : template <typename Tag> 30 : struct Next; 31 : struct Time; 32 : struct TimeStep; 33 : struct TimeStepId; 34 : template <typename StepperInterface> 35 : struct TimeStepper; 36 : } // namespace Tags 37 : // IWYU pragma: no_forward_declare db::DataBox 38 : /// \endcond 39 : 40 : namespace Actions { 41 : /// \ingroup ActionsGroup 42 : /// \ingroup TimeGroup 43 : /// \brief Advance time one substep 44 : /// 45 : /// Replaces the time state with the `Tags::Next` values, advances the 46 : /// `Tags::Next` values, and sets `Tags::Time` to the new substep time. 47 : /// 48 : /// Uses: 49 : /// - DataBox: 50 : /// - Tags::Next<Tags::TimeStep> 51 : /// - Tags::Next<Tags::TimeStepId> 52 : /// - Tags::TimeStepper<TimeStepper> 53 : /// 54 : /// DataBox changes: 55 : /// - Tags::Next<Tags::TimeStepId> 56 : /// - Tags::Next<Tags::TimeStep> 57 : /// - Tags::Time 58 : /// - Tags::TimeStepId 59 : /// - Tags::TimeStep 60 1 : struct AdvanceTime { 61 : template <typename DbTags, typename... InboxTags, typename Metavariables, 62 : typename ArrayIndex, typename ActionList, 63 : typename ParallelComponent> 64 0 : static Parallel::iterable_action_return_t apply( 65 : db::DataBox<DbTags>& box, tuples::TaggedTuple<InboxTags...>& /*inboxes*/, 66 : const Parallel::GlobalCache<Metavariables>& /*cache*/, 67 : const ArrayIndex& /*array_index*/, ActionList /*meta*/, 68 : const ParallelComponent* const /*meta*/) { // NOLINT const 69 : bool is_using_error_control = false; 70 : if constexpr (db::tag_is_retrievable_v< 71 : Tags::IsUsingTimeSteppingErrorControl, 72 : db::DataBox<DbTags>>) { 73 : is_using_error_control = 74 : db::get<Tags::IsUsingTimeSteppingErrorControl>(box); 75 : } 76 : 77 : db::mutate<Tags::TimeStepId, Tags::Next<Tags::TimeStepId>, Tags::TimeStep, 78 : Tags::Time, Tags::Next<Tags::TimeStep>, 79 : Tags::AdaptiveSteppingDiagnostics>( 80 : [](const gsl::not_null<TimeStepId*> time_id, 81 : const gsl::not_null<TimeStepId*> next_time_id, 82 : const gsl::not_null<TimeDelta*> time_step, 83 : const gsl::not_null<double*> time, 84 : const gsl::not_null<TimeDelta*> next_time_step, 85 : const gsl::not_null<AdaptiveSteppingDiagnostics*> diags, 86 : const TimeStepper& time_stepper, const bool using_error_control) { 87 : const bool new_step = next_time_id->substep() == 0; 88 : if (time_id->slab_number() != next_time_id->slab_number()) { 89 : ++diags->number_of_slabs; 90 : // Put this here instead of unconditionally doing the next 91 : // check because on the first call time_id doesn't have a 92 : // valid slab so comparing the times will FPE. 93 : ++diags->number_of_steps; 94 : } else if (new_step) { 95 : ++diags->number_of_steps; 96 : } 97 : 98 : *time_id = *next_time_id; 99 : 100 : if (new_step) { 101 : if (time_step->fraction() != next_time_step->fraction()) { 102 : ++diags->number_of_step_fraction_changes; 103 : } 104 : 105 : *time_step = next_time_step->with_slab(time_id->step_time().slab()); 106 : *next_time_step = *time_step; 107 : } 108 : 109 : if (using_error_control) { 110 : *next_time_id = 111 : time_stepper.next_time_id_for_error(*next_time_id, *time_step); 112 : } else { 113 : *next_time_id = 114 : time_stepper.next_time_id(*next_time_id, *time_step); 115 : } 116 : *time = time_id->substep_time(); 117 : }, 118 : make_not_null(&box), db::get<Tags::TimeStepper<TimeStepper>>(box), 119 : is_using_error_control); 120 : 121 : return {Parallel::AlgorithmExecution::Continue, std::nullopt}; 122 : } 123 : }; 124 : } // namespace Actions