SpECTRE Documentation Coverage Report
Current view: top level - Time/ChangeSlabSize - Action.hpp Hit Total Coverage
Commit: f81419eb45f381cdf5c6c7751685b35483e19db9 Lines: 1 5 20.0 %
Date: 2025-04-20 16:13:24
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 (time_stepper.can_change_step_size(
     152             :             time_step_id, db::get<::Tags::HistoryEvolvedVariables<>>(box))) {
     153             :       change_slab_size(make_not_null(&box), new_slab_end);
     154             :     }
     155             : 
     156             :     step_requests.error_on_hard_limit(
     157             :         db::get<::Tags::TimeStep>(box).value(),
     158             :         (time_step_id.step_time() + db::get<::Tags::TimeStep>(box)).value());
     159             :     return {Parallel::AlgorithmExecution::Continue, std::nullopt};
     160             :   }
     161             : };
     162             : }  // namespace Actions

Generated by: LCOV version 1.14