SpECTRE Documentation Coverage Report
Current view: top level - Time/ChangeSlabSize - ChangeSlabSize.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 50.0 % 2 1
Test Date: 2026-10-22 17:29:42
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 <cstddef>
       7              : 
       8              : #include "DataStructures/DataBox/DataBox.hpp"
       9              : #include "Time/AdaptiveSteppingDiagnostics.hpp"
      10              : #include "Time/Slab.hpp"
      11              : #include "Time/Tags/HistoryEvolvedVariables.hpp"
      12              : #include "Time/Time.hpp"
      13              : #include "Time/TimeStepId.hpp"
      14              : #include "Utilities/ErrorHandling/Assert.hpp"
      15              : #include "Utilities/Gsl.hpp"
      16              : #include "Utilities/TMPL.hpp"
      17              : 
      18              : /// \cond
      19              : namespace Tags {
      20              : struct AdaptiveSteppingDiagnostics;
      21              : struct MinimumTimeStep;
      22              : template <typename Tag>
      23              : struct Next;
      24              : struct TimeStep;
      25              : struct TimeStepId;
      26              : template <typename StepperInterface>
      27              : struct TimeStepper;
      28              : }  // namespace Tags
      29              : class TimeStepper;
      30              : namespace evolution::dg::Tags {
      31              : template <size_t Dim>
      32              : struct MortarNextTemporalId;
      33              : }  // namespace evolution::dg::Tags
      34              : /// \endcond
      35              : 
      36              : /// \ingroup TimeGroup
      37              : /// Change the slab size, updating all quantities in the DataBox
      38              : /// depending on it.
      39              : ///
      40              : /// The end of the slab (in the appropriate direction for the
      41              : /// evolution's flow of time) will be set to \p new_slab_end.  The
      42              : /// time step is set to the same fraction of the new slab as it was of
      43              : /// the old.
      44              : template <typename DbTags>
      45            1 : void change_slab_size(const gsl::not_null<db::DataBox<DbTags>*> box,
      46              :                       const double new_slab_end) {
      47              :   const TimeStepId& old_time_step_id = db::get<Tags::TimeStepId>(*box);
      48              : 
      49              :   ASSERT(old_time_step_id.is_at_slab_boundary(),
      50              :          "Cannot change slab size in middle of slab: " << old_time_step_id);
      51              : 
      52              :   const Slab old_slab = old_time_step_id.step_time().slab();
      53              :   const double old_slab_end = old_time_step_id.time_runs_forward()
      54              :                                   ? old_slab.end().value()
      55              :                                   : old_slab.start().value();
      56              : 
      57              :   if (new_slab_end == old_slab_end) {
      58              :     return;
      59              :   }
      60              : 
      61              :   const TimeDelta& old_time_step = db::get<Tags::TimeStep>(*box);
      62              : 
      63              :   const Slab new_slab = old_time_step_id.time_runs_forward()
      64              :                             ? Slab(old_slab.start().value(), new_slab_end)
      65              :                             : Slab(new_slab_end, old_slab.end().value());
      66              :   // We are at a slab boundary, so the substep is 0.
      67              :   const TimeStepId new_time_step_id(
      68              :       old_time_step_id.time_runs_forward(), old_time_step_id.slab_number(),
      69              :       old_time_step_id.step_time().with_slab(new_slab));
      70              :   const auto new_time_step = old_time_step.with_slab(new_slab);
      71              : 
      72              :   if (std::abs(new_time_step.value()) <
      73              :       db::get<::Tags::MinimumTimeStep>(*box)) {
      74              :     ERROR_NO_TRACE(
      75              :         "Chosen step size "
      76              :         << new_time_step.value() << " is smaller than the MinimumTimeStep of "
      77              :         << db::get<::Tags::MinimumTimeStep>(*box)
      78              :         << " while changing the slab size to " << new_slab.duration().value()
      79              :         << ".\n"
      80              :            "\n"
      81              :            "This can indicate a flaw in the step chooser, the grid, or a "
      82              :            "simulation instability that an error-based stepper is naively "
      83              :            "attempting to resolve. A possible issue is an aliasing-driven "
      84              :            "instability that could be cured by more aggressive filtering if "
      85              :            "you are using DG.");
      86              :   }
      87              : 
      88              :   const auto new_next_time_step_id =
      89              :       db::get<Tags::TimeStepper<TimeStepper>>(*box).next_time_id(
      90              :           new_time_step_id, new_time_step);
      91              : 
      92              :   // For DG evolutions, we need to correct the slab size stored in
      93              :   // MortarNextTemporalId.  This function should work for non-DG
      94              :   // evolution and should not depend on the DG headers, so we get all
      95              :   // the types from the DataBox.
      96              :   tmpl::for_each<tmpl::range<size_t, 1, 4>>(
      97              :       [&]<size_t Dim>(tmpl::type_<tmpl::size_t<Dim>> /*meta*/) {
      98              :         using mortar_next_temporal_id_tag =
      99              :             evolution::dg::Tags::MortarNextTemporalId<Dim>;
     100              :         if constexpr (db::tag_is_retrievable_v<mortar_next_temporal_id_tag,
     101              :                                                db::DataBox<DbTags>>) {
     102              :           db::mutate_apply<tmpl::list<mortar_next_temporal_id_tag>,
     103              :                            tmpl::list<::Tags::Next<::Tags::TimeStepId>>>(
     104              :               [&new_next_time_step_id, &new_time_step_id, &old_time_step_id](
     105              :                   const auto mortar_next_temporal_ids,
     106              :                   const TimeStepId& old_next_time_step_id) {
     107              :                 for (auto& [mortar_id, temporal_id] :
     108              :                      *mortar_next_temporal_ids) {
     109              :                   if (temporal_id == old_time_step_id) {
     110              :                     temporal_id = new_time_step_id;
     111              :                   } else {
     112              :                     ASSERT(temporal_id == old_next_time_step_id,
     113              :                            "Don't know how to translate "
     114              :                                << temporal_id << " to new slab.  Only know "
     115              :                                << old_time_step_id << " and "
     116              :                                << old_next_time_step_id);
     117              :                     temporal_id = new_next_time_step_id;
     118              :                   }
     119              :                 }
     120              :               },
     121              :               box);
     122              :         }
     123              :       });
     124              : 
     125              :   db::mutate_apply<
     126              :       tmpl::push_front<Tags::get_all_history_tags<DbTags>,
     127              :                        ::Tags::Next<::Tags::TimeStepId>, ::Tags::TimeStep,
     128              :                        ::Tags::TimeStepId, ::Tags::AdaptiveSteppingDiagnostics>,
     129              :       tmpl::list<>>(
     130              :       [&new_next_time_step_id, &new_time_step, &new_time_step_id](
     131              :           const gsl::not_null<TimeStepId*> next_time_step_id,
     132              :           const gsl::not_null<TimeDelta*> time_step,
     133              :           const gsl::not_null<TimeStepId*> local_time_step_id,
     134              :           const gsl::not_null<AdaptiveSteppingDiagnostics*> diags,
     135              :           const auto... histories) {
     136              :         const auto update_history = [&](const auto history) {
     137              :           if (not history->empty() and
     138              :               history->back().time_step_id == *local_time_step_id) {
     139              :             ASSERT(history->at_step_start(),
     140              :                    "Cannot change step size with substep data.");
     141              :             history->back().time_step_id = new_time_step_id;
     142              :           }
     143              :           return 0;
     144              :         };
     145              :         expand_pack(update_history(histories)...);
     146              : 
     147              :         *next_time_step_id = new_next_time_step_id;
     148              :         *time_step = new_time_step;
     149              :         *local_time_step_id = new_time_step_id;
     150              :         ++diags->number_of_slab_size_changes;
     151              :       },
     152              :       box);
     153              : }
        

Generated by: LCOV version 2.0-1