SpECTRE Documentation Coverage Report
Current view: top level - Time/ChangeSlabSize - Action.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 20.0 % 5 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              : #include <cstdint>
       8              : #include <map>
       9              : #include <optional>
      10              : #include <vector>
      11              : 
      12              : #include "DataStructures/DataBox/DataBox.hpp"
      13              : #include "Parallel/AlgorithmExecution.hpp"
      14              : #include "Time/ChangeSlabSize/ChangeSlabSize.hpp"
      15              : #include "Time/ChangeSlabSize/Tags.hpp"
      16              : #include "Time/Tags/HistoryEvolvedVariables.hpp"
      17              : #include "Time/Tags/MinimumTimeStep.hpp"
      18              : #include "Time/TimeStepRequestProcessor.hpp"
      19              : #include "Time/TimeSteppers/TimeStepper.hpp"
      20              : #include "Utilities/Algorithm.hpp"
      21              : #include "Utilities/ErrorHandling/Assert.hpp"
      22              : #include "Utilities/Numeric.hpp"
      23              : #include "Utilities/TMPL.hpp"
      24              : 
      25              : /// \cond
      26              : namespace Parallel {
      27              : template <typename Metavariables>
      28              : class GlobalCache;
      29              : }  // namespace Parallel
      30              : namespace Tags {
      31              : struct TimeStep;
      32              : struct TimeStepId;
      33              : template <typename StepperInterface>
      34              : struct TimeStepper;
      35              : }  // namespace Tags
      36              : namespace tuples {
      37              : template <class... Tags>
      38              : class TaggedTuple;
      39              : }  // namespace tuples
      40              : /// \endcond
      41              : 
      42              : namespace Actions {
      43              : /// \ingroup ActionsGroup
      44              : /// \ingroup TimeGroup
      45              : /// Adjust the slab size based on previous executions of
      46              : /// Events::ChangeSlabSize
      47              : ///
      48              : /// Uses:
      49              : /// - DataBox:
      50              : ///   - Tags::HistoryEvolvedVariables
      51              : ///   - Tags::TimeStep
      52              : ///   - Tags::TimeStepId
      53              : ///   - Tags::TimeStepper<TimeStepper>
      54              : ///
      55              : /// DataBox changes:
      56              : /// - Adds: nothing
      57              : /// - Removes: nothing
      58              : /// - Modifies:
      59              : ///   - Tags::Next<Tags::TimeStepId>
      60              : ///   - Tags::TimeStep
      61              : ///   - Tags::TimeStepId
      62            1 : struct ChangeSlabSize {
      63            0 :   using const_global_cache_tags = tmpl::list<::Tags::MinimumTimeStep>;
      64            0 :   using simple_tags =
      65              :       tmpl::list<::Tags::ChangeSlabSize::NewSlabSize,
      66              :                  ::Tags::ChangeSlabSize::NumberOfExpectedMessages>;
      67              : 
      68              :   template <typename DbTags, typename... InboxTags, typename Metavariables,
      69              :             typename ArrayIndex, typename ActionList,
      70              :             typename ParallelComponent>
      71            0 :   static Parallel::iterable_action_return_t apply(
      72              :       db::DataBox<DbTags>& box, tuples::TaggedTuple<InboxTags...>& /*inboxes*/,
      73              :       const Parallel::GlobalCache<Metavariables>& /*cache*/,
      74              :       const ArrayIndex& /*array_index*/, const ActionList /*meta*/,
      75              :       const ParallelComponent* const /*meta*/) {
      76              :     const auto& time_step_id = db::get<::Tags::TimeStepId>(box);
      77              :     if (not time_step_id.is_at_slab_boundary()) {
      78              :       return {Parallel::AlgorithmExecution::Continue, std::nullopt};
      79              :     }
      80              : 
      81              :     TimeStepRequestProcessor step_requests(time_step_id.time_runs_forward());
      82              : 
      83              :     const auto slab_number = time_step_id.slab_number();
      84              :     const auto& expected_messages_map =
      85              :         db::get<::Tags::ChangeSlabSize::NumberOfExpectedMessages>(box);
      86              :     if (not expected_messages_map.empty() and
      87              :         expected_messages_map.begin()->first == slab_number) {
      88              :       const size_t expected_messages = expected_messages_map.begin()->second;
      89              :       ASSERT(expected_messages > 0,
      90              :              "Should only create map entries when sending messages.");
      91              : 
      92              :       const auto& slab_size_messages =
      93              :           db::get<::Tags::ChangeSlabSize::NewSlabSize>(box);
      94              :       if (slab_size_messages.empty()) {
      95              :         return {Parallel::AlgorithmExecution::Retry, std::nullopt};
      96              :       }
      97              :       const int64_t first_received_change_slab =
      98              :           slab_size_messages.begin()->first;
      99              : 
     100              :       ASSERT(first_received_change_slab >= slab_number,
     101              :              "Received data for a change at slab " << first_received_change_slab
     102              :              << " but it is already slab " << slab_number);
     103              :       if (first_received_change_slab != slab_number) {
     104              :         return {Parallel::AlgorithmExecution::Retry, std::nullopt};
     105              :       }
     106              : 
     107              :       const auto& received_changes = slab_size_messages.begin()->second;
     108              :       ASSERT(expected_messages >= received_changes.size(),
     109              :              "Received " << received_changes.size()
     110              :                          << " size change messages at slab " << slab_number
     111              :                          << ", but only expected " << expected_messages);
     112              :       if (received_changes.size() != expected_messages) {
     113              :         return {Parallel::AlgorithmExecution::Retry, std::nullopt};
     114              :       }
     115              : 
     116              :       // We have all the data we need.
     117              : 
     118              :       step_requests =
     119              :           alg::accumulate(slab_size_messages.begin()->second, step_requests);
     120              : 
     121              :       db::mutate<::Tags::ChangeSlabSize::NumberOfExpectedMessages,
     122              :                  ::Tags::ChangeSlabSize::NewSlabSize>(
     123              :           [](const gsl::not_null<std::map<int64_t, size_t>*> expected,
     124              :              const gsl::not_null<
     125              :                  std::map<int64_t, std::vector<TimeStepRequestProcessor>>*>
     126              :                  sizes) {
     127              :             expected->erase(expected->begin());
     128              :             sizes->erase(sizes->begin());
     129              :           },
     130              :           make_not_null(&box));
     131              :     }
     132              :     const double new_slab_end = step_requests.step_end(
     133              :         time_step_id.step_time().value(),
     134              :         db::get<::Tags::ChangeSlabSize::SlabSizeGoal>(box));
     135              : 
     136              :     if (const auto new_goal = step_requests.new_step_size_goal();
     137              :         new_goal.has_value()) {
     138              :       db::mutate<::Tags::ChangeSlabSize::SlabSizeGoal>(
     139              :           [&](const gsl::not_null<double*> slab_size_goal) {
     140              :             *slab_size_goal = *new_goal;
     141              :           },
     142              :           make_not_null(&box));
     143              :     }
     144              : 
     145              :     const TimeStepper& time_stepper =
     146              :         db::get<::Tags::TimeStepper<TimeStepper>>(box);
     147              : 
     148              :     // Sometimes time steppers need to run with a fixed step size.
     149              :     // This is generally at the start of an evolution when the history
     150              :     // is in an unusual state.
     151              :     if (tmpl::as_pack<::Tags::get_all_history_tags<DbTags>>(
     152              :             [&]<typename... HistoryTags>(tmpl::type_<HistoryTags>... /*meta*/) {
     153              :               return (... and time_stepper.can_change_step_size(
     154              :                                   time_step_id, db::get<HistoryTags>(box)));
     155              :             })) {
     156              :       change_slab_size(make_not_null(&box), new_slab_end);
     157              :     }
     158              : 
     159              :     step_requests.error_on_hard_limit(
     160              :         db::get<::Tags::TimeStep>(box).value(),
     161              :         (time_step_id.step_time() + db::get<::Tags::TimeStep>(box)).value());
     162              :     return {Parallel::AlgorithmExecution::Continue, std::nullopt};
     163              :   }
     164              : };
     165              : }  // namespace Actions
        

Generated by: LCOV version 2.0-1