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

Generated by: LCOV version 1.14