SpECTRE Documentation Coverage Report
Current view: top level - Time/ChangeSlabSize - Event.hpp Hit Total Coverage
Commit: 965048f86d23c819715b3af1ca3f880c8145d4bb Lines: 2 25 8.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 <algorithm>
       7             : #include <cstddef>
       8             : #include <cstdint>
       9             : #include <limits>
      10             : #include <memory>
      11             : #include <pup.h>
      12             : #include <pup_stl.h>
      13             : #include <utility>
      14             : #include <vector>
      15             : 
      16             : #include "DataStructures/DataBox/DataBox.hpp"
      17             : #include "Options/String.hpp"
      18             : #include "Parallel/GlobalCache.hpp"
      19             : #include "Parallel/Reduction.hpp"
      20             : #include "ParallelAlgorithms/EventsAndTriggers/Event.hpp"
      21             : #include "Time/ChangeSlabSize/Tags.hpp"
      22             : #include "Time/StepChoosers/StepChooser.hpp"
      23             : #include "Time/TimeStepId.hpp"
      24             : #include "Utilities/Functional.hpp"
      25             : #include "Utilities/Serialization/CharmPupable.hpp"
      26             : #include "Utilities/TMPL.hpp"
      27             : 
      28             : /// \cond
      29             : namespace Tags {
      30             : struct DataBox;
      31             : struct TimeStepId;
      32             : }  // namespace Tags
      33             : /// \endcond
      34             : 
      35             : namespace Events {
      36             : namespace ChangeSlabSize_detail {
      37             : struct StoreNewSlabSize {
      38             :   template <typename ParallelComponent, typename DbTags, typename Metavariables,
      39             :             typename ArrayIndex>
      40             :   static void apply(db::DataBox<DbTags>& box,
      41             :                     Parallel::GlobalCache<Metavariables>& /*cache*/,
      42             :                     const ArrayIndex& /*array_index*/,
      43             :                     const int64_t slab_number, const double slab_size) {
      44             :     db::mutate<::Tags::ChangeSlabSize::NewSlabSize>(
      45             :         [&](const gsl::not_null<
      46             :             std::map<int64_t, std::unordered_multiset<double>>*>
      47             :                 sizes) { (*sizes)[slab_number].insert(slab_size); },
      48             :         make_not_null(&box));
      49             :   }
      50             : };
      51             : }  // namespace ChangeSlabSize_detail
      52             : 
      53             : /// \ingroup TimeGroup
      54             : /// %Trigger a slab size change.
      55             : ///
      56             : /// The new size will be the minimum suggested by any of the provided
      57             : /// step choosers on any element.  This requires a global reduction,
      58             : /// so it is possible to delay the change until a later slab to avoid
      59             : /// a global synchronization.  The actual change is carried out by
      60             : /// Actions::ChangeSlabSize.
      61             : ///
      62             : /// When running with global time-stepping, the slab size and step
      63             : /// size are the same, so this adjusts the step size used by the time
      64             : /// integration.  With local time-stepping this controls the interval
      65             : /// between times when the sequences of steps on all elements are
      66             : /// forced to align.
      67           1 : class ChangeSlabSize : public Event {
      68           0 :   using ReductionData = Parallel::ReductionData<
      69             :       Parallel::ReductionDatum<int64_t, funcl::AssertEqual<>>,
      70             :       Parallel::ReductionDatum<double, funcl::Min<>>>;
      71             : 
      72             :  public:
      73             :   /// \cond
      74             :   explicit ChangeSlabSize(CkMigrateMessage* /*unused*/) {}
      75             :   using PUP::able::register_constructor;
      76             :   WRAPPED_PUPable_decl_template(ChangeSlabSize);  // NOLINT
      77             :   /// \endcond
      78             : 
      79           0 :   struct StepChoosers {
      80           0 :     static constexpr Options::String help = "Limits on slab size";
      81           0 :     using type =
      82             :         std::vector<std::unique_ptr<StepChooser<StepChooserUse::Slab>>>;
      83           0 :     static size_t lower_bound_on_size() { return 1; }
      84             :   };
      85             : 
      86           0 :   struct DelayChange {
      87           0 :     static constexpr Options::String help = "Slabs to wait before changing";
      88           0 :     using type = uint64_t;
      89             :   };
      90             : 
      91           0 :   using options = tmpl::list<StepChoosers, DelayChange>;
      92           0 :   static constexpr Options::String help =
      93             :       "Trigger a slab size change chosen by the provided step choosers.\n"
      94             :       "The actual changing of the slab size can be delayed until a later\n"
      95             :       "slab to improve parallelization.";
      96             : 
      97           0 :   ChangeSlabSize() = default;
      98           0 :   ChangeSlabSize(std::vector<std::unique_ptr<StepChooser<StepChooserUse::Slab>>>
      99             :                      step_choosers,
     100             :                  const uint64_t delay_change)
     101             :       : step_choosers_(std::move(step_choosers)), delay_change_(delay_change) {}
     102             : 
     103           0 :   using compute_tags_for_observation_box = tmpl::list<>;
     104             : 
     105             :   // Need a const version of the full box for the step choosers, but
     106             :   // can't get a const version while mutating other tags, so request a
     107             :   // mutable version.
     108           0 :   using return_tags = tmpl::list<::Tags::DataBox>;
     109           0 :   using argument_tags = tmpl::list<::Tags::TimeStepId>;
     110             : 
     111             :   template <typename DbTags, typename Metavariables, typename ArrayIndex,
     112             :             typename ParallelComponent>
     113           0 :   void operator()(const gsl::not_null<db::DataBox<DbTags>*> box,
     114             :                   const TimeStepId& time_step_id,
     115             :                   Parallel::GlobalCache<Metavariables>& cache,
     116             :                   const ArrayIndex& array_index,
     117             :                   const ParallelComponent* const /*meta*/,
     118             :                   const ObservationValue& /*observation_value*/) const {
     119             :     const auto next_changable_slab = time_step_id.is_at_slab_boundary()
     120             :                                          ? time_step_id.slab_number()
     121             :                                          : time_step_id.slab_number() + 1;
     122             :     const auto slab_to_change =
     123             :         next_changable_slab + static_cast<int64_t>(delay_change_);
     124             : 
     125             :     double desired_slab_size = std::numeric_limits<double>::infinity();
     126             :     bool synchronization_required = false;
     127             :     for (const auto& step_chooser : step_choosers_) {
     128             :       desired_slab_size = std::min(
     129             :           desired_slab_size,
     130             :           step_chooser
     131             :               ->desired_step(time_step_id.step_time().slab().duration().value(),
     132             :                              *box)
     133             :               .first);
     134             :       // We must synchronize if any step chooser requires it, not just
     135             :       // the limiting one, because choosers requiring synchronization
     136             :       // can be limiting on some processors and not others.
     137             :       if (not synchronization_required) {
     138             :         synchronization_required = step_chooser->uses_local_data();
     139             :       }
     140             :     }
     141             : 
     142             :     db::mutate<::Tags::ChangeSlabSize::NumberOfExpectedMessages>(
     143             :         [&](const gsl::not_null<std::map<int64_t, size_t>*> expected) {
     144             :           ++(*expected)[slab_to_change];
     145             :         },
     146             :         box);
     147             : 
     148             :     const auto& component_proxy =
     149             :         Parallel::get_parallel_component<ParallelComponent>(cache);
     150             :     const auto& self_proxy = component_proxy[array_index];
     151             :     if (synchronization_required) {
     152             :       Parallel::contribute_to_reduction<
     153             :           ChangeSlabSize_detail::StoreNewSlabSize>(
     154             :           ReductionData(slab_to_change, desired_slab_size), self_proxy,
     155             :           component_proxy);
     156             :     } else {
     157             :       db::mutate<::Tags::ChangeSlabSize::NewSlabSize>(
     158             :           [&](const gsl::not_null<
     159             :               std::map<int64_t, std::unordered_multiset<double>>*>
     160             :                   sizes) {
     161             :             (*sizes)[slab_to_change].insert(desired_slab_size);
     162             :           },
     163             :           box);
     164             :     }
     165             :   }
     166             : 
     167           0 :   using is_ready_argument_tags = tmpl::list<>;
     168             : 
     169             :   template <typename Metavariables, typename ArrayIndex, typename Component>
     170           0 :   bool is_ready(Parallel::GlobalCache<Metavariables>& /*cache*/,
     171             :                 const ArrayIndex& /*array_index*/,
     172             :                 const Component* const /*meta*/) const {
     173             :     return true;
     174             :   }
     175             : 
     176           1 :   bool needs_evolved_variables() const override {
     177             :     // This depends on the chosen StepChoosers, but they don't have a
     178             :     // way to report this information so we just return true to be
     179             :     // safe.
     180             :     return true;
     181             :   }
     182             : 
     183             :   template <typename F>
     184           0 :   void for_each_step_chooser(F&& f) const {
     185             :     for (const auto& step_chooser : step_choosers_) {
     186             :       f(*step_chooser);
     187             :     }
     188             :   }
     189             : 
     190             :   // NOLINTNEXTLINE(google-runtime-references)
     191           0 :   void pup(PUP::er& p) override {
     192             :     Event::pup(p);
     193             :     p | step_choosers_;
     194             :     p | delay_change_;
     195             :   }
     196             : 
     197             :  private:
     198             :   std::vector<std::unique_ptr<StepChooser<StepChooserUse::Slab>>>
     199           0 :       step_choosers_;
     200           0 :   uint64_t delay_change_ = std::numeric_limits<uint64_t>::max();
     201             : };
     202             : }  // namespace Events

Generated by: LCOV version 1.14