SpECTRE Documentation Coverage Report
Current view: top level - Time/Actions - ChangeStepSize.hpp Hit Total Coverage
Commit: 35a1e98cd3e4fdea528eb8100f99c2f707894fda Lines: 2 4 50.0 %
Date: 2024-04-19 00:10:48
Legend: Lines: hit not hit

          Line data    Source code
       1           0 : // Distributed under the MIT License.
       2             : // See LICENSE.txt for details.
       3             : 
       4             : #pragma once
       5             : 
       6             : #include <limits>
       7             : #include <optional>
       8             : #include <tuple>
       9             : 
      10             : #include "DataStructures/DataBox/DataBox.hpp"
      11             : #include "DataStructures/DataBox/Prefixes.hpp"  // IWYU pragma: keep  // for Tags::Next
      12             : #include "Parallel/AlgorithmExecution.hpp"
      13             : #include "Time/Actions/UpdateU.hpp"
      14             : #include "Time/AdaptiveSteppingDiagnostics.hpp"
      15             : #include "Time/ChooseLtsStepSize.hpp"
      16             : #include "Time/Tags/AdaptiveSteppingDiagnostics.hpp"
      17             : #include "Time/Tags/HistoryEvolvedVariables.hpp"
      18             : #include "Time/TimeSteppers/LtsTimeStepper.hpp"
      19             : #include "Utilities/Gsl.hpp"
      20             : #include "Utilities/TMPL.hpp"
      21             : #include "Utilities/TaggedTuple.hpp"
      22             : 
      23             : /// \cond
      24             : struct AllStepChoosers;
      25             : class TimeDelta;
      26             : class TimeStepId;
      27             : namespace Parallel {
      28             : template <typename Metavariables>
      29             : class GlobalCache;
      30             : }  // namespace Parallel
      31             : namespace StepChooserUse {
      32             : struct LtsStep;
      33             : }  // namespace StepChooserUse
      34             : namespace Tags {
      35             : template <typename Tag>
      36             : struct Next;
      37             : struct StepChoosers;
      38             : struct TimeStep;
      39             : struct TimeStepId;
      40             : template <typename StepperInterface>
      41             : struct TimeStepper;
      42             : }  // namespace Tags
      43             : // IWYU pragma: no_forward_declare db::DataBox
      44             : /// \endcond
      45             : 
      46             : /// \brief Adjust the step size for local time stepping, returning true if the
      47             : /// step just completed is accepted, and false if it is rejected.
      48             : ///
      49             : /// \details The optional template parameter `StepChoosersToUse` may be used to
      50             : /// indicate a subset of the constructable step choosers to use for the current
      51             : /// application of `ChangeStepSize`. Passing `AllStepChoosers` (default)
      52             : /// indicates that any constructible step chooser may be used. This option is
      53             : /// used when multiple components need to invoke `ChangeStepSize` with step
      54             : /// choosers that may not be compatible with all components.
      55             : template <typename StepChoosersToUse = AllStepChoosers, typename DbTags>
      56           1 : bool change_step_size(const gsl::not_null<db::DataBox<DbTags>*> box) {
      57             :   const LtsTimeStepper& time_stepper =
      58             :       db::get<Tags::TimeStepper<LtsTimeStepper>>(*box);
      59             :   const auto& step_choosers = db::get<Tags::StepChoosers>(*box);
      60             : 
      61             :   const auto& time_step_id = db::get<Tags::TimeStepId>(*box);
      62             :   using history_tags = ::Tags::get_all_history_tags<DbTags>;
      63             :   bool can_change_step_size = true;
      64             :   tmpl::for_each<history_tags>([&box, &can_change_step_size, &time_stepper,
      65             :                                 &time_step_id](auto tag_v) {
      66             :     if (not can_change_step_size) {
      67             :       return;
      68             :     }
      69             :     using tag = typename decltype(tag_v)::type;
      70             :     const auto& history = db::get<tag>(*box);
      71             :     can_change_step_size =
      72             :         time_stepper.can_change_step_size(time_step_id, history);
      73             :   });
      74             :   if (not can_change_step_size) {
      75             :     return true;
      76             :   }
      77             : 
      78             :   const auto& current_step = db::get<Tags::TimeStep>(*box);
      79             : 
      80             :   const double last_step_size = std::abs(db::get<Tags::TimeStep>(*box).value());
      81             : 
      82             :   // The step choosers return the magnitude of the desired step, so
      83             :   // we always want the minimum requirement, but we have to negate
      84             :   // the final answer if time is running backwards.
      85             :   double desired_step = std::numeric_limits<double>::infinity();
      86             :   bool step_accepted = true;
      87             :   for (const auto& step_chooser : step_choosers) {
      88             :     const auto [step_choice, step_choice_accepted] =
      89             :         step_chooser->template desired_step<StepChoosersToUse>(
      90             :             last_step_size, *box);
      91             :     desired_step = std::min(desired_step, step_choice);
      92             :     step_accepted = step_accepted and step_choice_accepted;
      93             :   }
      94             :   if (not current_step.is_positive()) {
      95             :     desired_step = -desired_step;
      96             :   }
      97             : 
      98             :   if (abs(desired_step / current_step.slab().duration().value()) < 1.0e-9) {
      99             :     ERROR(
     100             :         "Chosen step is extremely small; this can indicate a flaw in the a "
     101             :         "step chooser, the grid, or a simualtion instability that an "
     102             :         "error-based stepper is naively attempting to resolve. It is unlikely "
     103             :         "that the simulation can proceed");
     104             :   }
     105             : 
     106             :   const auto& next_time_id = db::get<Tags::Next<Tags::TimeStepId>>(*box);
     107             :   const auto new_step =
     108             :       choose_lts_step_size(next_time_id.step_time(), desired_step);
     109             :   db::mutate<Tags::Next<Tags::TimeStep>>(
     110             :       [&new_step](const gsl::not_null<TimeDelta*> next_step) {
     111             :         *next_step = new_step;
     112             :       },
     113             :       box);
     114             :   // if step accepted, just proceed. Otherwise, change Time::Next and jump
     115             :   // back to the first instance of `UpdateU`.
     116             :   if (step_accepted) {
     117             :     return true;
     118             :   } else {
     119             :     db::mutate<Tags::Next<Tags::TimeStepId>, Tags::TimeStep>(
     120             :         [&time_stepper, &desired_step, &time_step_id](
     121             :             const gsl::not_null<TimeStepId*> local_next_time_id,
     122             :             const gsl::not_null<TimeDelta*> time_step) {
     123             :           *time_step =
     124             :               choose_lts_step_size(time_step_id.step_time(), desired_step);
     125             :           *local_next_time_id =
     126             :               time_stepper.next_time_id(time_step_id, *time_step);
     127             :         },
     128             :         box);
     129             :     return false;
     130             :   }
     131             : }
     132             : 
     133             : namespace Actions {
     134             : /// \ingroup ActionsGroup
     135             : /// \ingroup TimeGroup
     136             : /// \brief Adjust the step size for local time stepping
     137             : ///
     138             : /// \details The optional template parameter `StepChoosersToUse` may be used to
     139             : /// indicate a subset of the constructable step choosers to use for the current
     140             : /// application of `ChangeStepSize`. Passing `AllStepChoosers` (default)
     141             : /// indicates that any constructible step chooser may be used. This option is
     142             : /// used when multiple components need to invoke `ChangeStepSize` with step
     143             : /// choosers that may not be compatible with all components.
     144             : ///
     145             : /// Uses:
     146             : /// - DataBox:
     147             : ///   - Tags::StepChoosers
     148             : ///   - Tags::HistoryEvolvedVariables
     149             : ///   - Tags::TimeStep
     150             : ///   - Tags::TimeStepId
     151             : ///   - Tags::TimeStepper<LtsTimeStepper>
     152             : ///
     153             : /// DataBox changes:
     154             : /// - Adds: nothing
     155             : /// - Removes: nothing
     156             : /// - Modifies: Tags::Next<Tags::TimeStepId>, Tags::TimeStep
     157             : template <typename StepChoosersToUse = AllStepChoosers>
     158           1 : struct ChangeStepSize {
     159             :   template <typename DbTags, typename... InboxTags, typename Metavariables,
     160             :             typename ArrayIndex, typename ActionList,
     161             :             typename ParallelComponent>
     162           0 :   static Parallel::iterable_action_return_t apply(
     163             :       db::DataBox<DbTags>& box, tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
     164             :       const Parallel::GlobalCache<Metavariables>& /*cache*/,
     165             :       const ArrayIndex& /*array_index*/, const ActionList /*meta*/,
     166             :       const ParallelComponent* const /*meta*/) {
     167             :     static_assert(
     168             :         tmpl::any<ActionList, tt::is_a<Actions::UpdateU, tmpl::_1>>::value,
     169             :         "The ChangeStepSize action requires that you also use the UpdateU "
     170             :         "action to permit step-unwinding. If you are stepping within "
     171             :         "an action that is not UpdateU, consider using the take_step function "
     172             :         "to handle both stepping and step-choosing instead of the "
     173             :         "ChangeStepSize action.");
     174             :     const bool step_successful =
     175             :         change_step_size<StepChoosersToUse>(make_not_null(&box));
     176             :     // We should update
     177             :     // AdaptiveSteppingDiagnostics::number_of_step_fraction_changes,
     178             :     // but with the inter-action step unwinding it's hard to tell
     179             :     // whether that happened.  Most executables use take_step instead
     180             :     // of this action, anyway.
     181             :     if (step_successful) {
     182             :       return {Parallel::AlgorithmExecution::Continue, std::nullopt};
     183             :     } else {
     184             :       db::mutate<Tags::AdaptiveSteppingDiagnostics>(
     185             :           [](const gsl::not_null<AdaptiveSteppingDiagnostics*> diags) {
     186             :             ++diags->number_of_step_rejections;
     187             :           },
     188             :           make_not_null(&box));
     189             :       return {Parallel::AlgorithmExecution::Continue,
     190             :               tmpl::index_if<ActionList,
     191             :                              tt::is_a<Actions::UpdateU, tmpl::_1>>::value};
     192             :     }
     193             :   }
     194             : };
     195             : }  // namespace Actions

Generated by: LCOV version 1.14