SpECTRE Documentation Coverage Report
Current view: top level - ParallelAlgorithms/Events - ChangeFixedLtsRatio.hpp Hit Total Coverage
Commit: c3e43f8d41800b0ecefb9d1393f1de1d5a280c8f Lines: 2 32 6.2 %
Date: 2026-07-24 22:09:25
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 <cmath>
       7             : #include <cstddef>
       8             : #include <cstdint>
       9             : #include <limits>
      10             : #include <map>
      11             : #include <memory>
      12             : #include <optional>
      13             : #include <pup.h>
      14             : #include <pup_stl.h>
      15             : #include <string>
      16             : #include <typeindex>
      17             : #include <unordered_map>
      18             : #include <utility>
      19             : #include <vector>
      20             : 
      21             : #include "DataStructures/DataBox/DataBox.hpp"
      22             : #include "Evolution/DiscontinuousGalerkin/EqualRateLts/EqualRateRegions.hpp"
      23             : #include "Options/Auto.hpp"
      24             : #include "Options/Context.hpp"
      25             : #include "Options/ParseError.hpp"
      26             : #include "Options/String.hpp"
      27             : #include "Parallel/ArrayCollection/IsDgElementCollection.hpp"
      28             : #include "Parallel/GlobalCache.hpp"
      29             : #include "Parallel/Reduction.hpp"
      30             : #include "ParallelAlgorithms/EventsAndTriggers/Event.hpp"
      31             : #include "Time/CollectStepperErrorTolerances.hpp"
      32             : #include "Time/RequestsStepperErrorTolerances.hpp"
      33             : #include "Time/StepChoosers/StepChooser.hpp"
      34             : #include "Time/StepperErrorTolerances.hpp"
      35             : #include "Time/TimeStepRequestProcessor.hpp"
      36             : #include "Utilities/ErrorHandling/Assert.hpp"
      37             : #include "Utilities/ErrorHandling/Error.hpp"
      38             : #include "Utilities/Functional.hpp"
      39             : #include "Utilities/Gsl.hpp"
      40             : #include "Utilities/PrettyType.hpp"
      41             : #include "Utilities/Serialization/CharmPupable.hpp"
      42             : #include "Utilities/Serialization/PupStlCpp17.hpp"
      43             : #include "Utilities/TMPL.hpp"
      44             : 
      45             : /// \cond
      46             : namespace Parallel::Tags {
      47             : template <typename ParallelComponent, typename SectionIdTag>
      48             : struct Section;
      49             : }  // namespace Parallel::Tags
      50             : namespace Tags {
      51             : struct DataBox;
      52             : struct StepNumberWithinSlab;
      53             : struct TimeStep;
      54             : struct TimeStepId;
      55             : }  // namespace Tags
      56             : namespace domain::Tags {
      57             : template <size_t VolumeDim>
      58             : struct Element;
      59             : }  // namespace domain::Tags
      60             : namespace evolution::dg::Tags {
      61             : struct EqualRateRegionId;
      62             : template <size_t Dim>
      63             : struct EqualRateRegions;
      64             : }  // namespace evolution::dg::Tags
      65             : namespace evolution::dg::Tags::ChangeFixedLtsRatio {
      66             : struct NewStepSize;
      67             : struct NumberOfExpectedMessages;
      68             : }  //  namespace evolution::dg::Tags::ChangeFixedLtsRatio
      69             : /// \endcond
      70             : 
      71           0 : namespace dg::Events {
      72             : namespace ChangeFixedLtsRatio_detail {
      73             : template <size_t Dim>
      74             : struct StoreNewStep {
      75             :   using StepId = std::pair<int64_t, uint64_t>;
      76             : 
      77             :   template <typename ParallelComponent, typename DbTags, typename Metavariables,
      78             :             typename ArrayIndex>
      79             :   static void apply(db::DataBox<DbTags>& box,
      80             :                     Parallel::GlobalCache<Metavariables>& /*cache*/,
      81             :                     const ArrayIndex& /*array_index*/,
      82             :                     const evolution::dg::EqualRateRegionId& region,
      83             :                     const StepId& step_to_change, const double new_step_size) {
      84             :     const auto& equal_rate_regions =
      85             :         db::get<evolution::dg::Tags::EqualRateRegions<Dim>>(box);
      86             :     const auto& element = db::get<domain::Tags::Element<Dim>>(box);
      87             :     if (equal_rate_regions.is_in_region(region, element.id())) {
      88             :       db::mutate<evolution::dg::Tags::ChangeFixedLtsRatio::NewStepSize>(
      89             :           [&](const gsl::not_null<std::map<StepId, std::vector<double>>*>
      90             :                   step_sizes) {
      91             :             (*step_sizes)[step_to_change].push_back(new_step_size);
      92             :           },
      93             :           make_not_null(&box));
      94             :     }
      95             :   }
      96             : };
      97             : }  // namespace ChangeFixedLtsRatio_detail
      98             : 
      99             : template <size_t Dim, typename StepChoosersToUse = AllStepChoosers>
     100           0 : class ChangeFixedLtsRatio : public Event,
     101             :                             public RequestsStepperErrorTolerances {
     102           0 :   using StepId = std::pair<int64_t, uint64_t>;
     103             : 
     104           0 :   using ReductionData = Parallel::ReductionData<
     105             :       Parallel::ReductionDatum<evolution::dg::EqualRateRegionId,
     106             :                                funcl::AssertEqual<>>,
     107             :       Parallel::ReductionDatum<StepId, funcl::AssertEqual<>>,
     108             :       Parallel::ReductionDatum<double, funcl::Min<>>>;
     109             : 
     110             :  public:
     111           0 :   ChangeFixedLtsRatio() = default;
     112             : 
     113             :   /// \cond
     114             :   explicit ChangeFixedLtsRatio(CkMigrateMessage* /*unused*/) {}
     115             :   using PUP::able::register_constructor;
     116             :   WRAPPED_PUPable_decl_template(ChangeFixedLtsRatio);  // NOLINT
     117             :   /// \endcond
     118             : 
     119           0 :   struct StepChoosers {
     120           0 :     static constexpr Options::String help = "Limits on step size";
     121           0 :     using type =
     122             :         std::vector<std::unique_ptr<StepChooser<StepChooserUse::LtsStep>>>;
     123           0 :     static size_t lower_bound_on_size() { return 1; }
     124             :   };
     125             : 
     126           0 :   struct DelayChange {
     127           0 :     static constexpr Options::String help = "Steps to wait before changing";
     128           0 :     using type = uint64_t;
     129             :   };
     130             : 
     131           0 :   struct Regions {
     132           0 :     using type =
     133             :         Options::Auto<std::vector<std::string>, Options::AutoLabel::All>;
     134           0 :     static constexpr Options::String help{
     135             :         "Regions to adjust.  Adjustments for each region are independent."};
     136             :   };
     137             : 
     138           0 :   using options = tmpl::list<StepChoosers, DelayChange, Regions>;
     139           0 :   static constexpr Options::String help =
     140             :       "Change the number of steps per slab in regions with synchronized steps.";
     141             : 
     142           0 :   ChangeFixedLtsRatio(
     143             :       std::vector<std::unique_ptr<StepChooser<StepChooserUse::LtsStep>>>
     144             :           step_choosers,
     145             :       const uint64_t delay_change,
     146             :       std::optional<std::vector<std::string>> regions,
     147             :       const Options::Context& context = {})
     148             :       : step_choosers_(std::move(step_choosers)),
     149             :         delay_change_(delay_change),
     150             :         regions_(std::move(regions)) {
     151             :     if (delay_change != 0) {
     152             :       for (const auto& chooser : step_choosers_) {
     153             :         if (not chooser->can_be_delayed()) {
     154             :           // The runtime name might not be exactly the same as the one
     155             :           // used by the factory, but hopefully it's close enough that
     156             :           // the user can figure it out.
     157             :           PARSE_ERROR(context,
     158             :                       "The " << pretty_type::get_runtime_type_name(*chooser)
     159             :                              << " StepChooser cannot be applied with a delay.");
     160             :         }
     161             :       }
     162             :     }
     163             :   }
     164             : 
     165           0 :   using compute_tags_for_observation_box = tmpl::list<>;
     166             : 
     167             :   // Need a const version of the full box for the step choosers, but
     168             :   // can't get a const version while mutating other tags, so request a
     169             :   // mutable version.
     170           0 :   using return_tags = tmpl::list<::Tags::DataBox>;
     171           0 :   using argument_tags = tmpl::list<>;
     172             : 
     173             :   template <typename DbTags, typename Metavariables, typename ArrayIndex,
     174             :             typename ParallelComponent>
     175           0 :   void operator()(const gsl::not_null<db::DataBox<DbTags>*> box,
     176             :                   Parallel::GlobalCache<Metavariables>& cache,
     177             :                   const ArrayIndex& array_index,
     178             :                   const ParallelComponent* const /*meta*/,
     179             :                   const ObservationValue& /*observation_value*/) const {
     180             :     const auto& time_step_id = db::get<::Tags::TimeStepId>(*box);
     181             :     if (time_step_id.substep() != 0) {
     182             :       ERROR("Changing step ratio on a substep not implemented.");
     183             :     }
     184             : 
     185             :     auto& section = db::get_mutable_reference<Parallel::Tags::Section<
     186             :         ParallelComponent, evolution::dg::Tags::EqualRateRegionId>>(box);
     187             : 
     188             :     if (not section.has_value()) {
     189             :       return;
     190             :     }
     191             : 
     192             :     if (regions_.has_value()) {
     193             :       const auto& equal_rate_regions =
     194             :           db::get<evolution::dg::Tags::EqualRateRegions<Dim>>(*box);
     195             :       const auto& region_map = equal_rate_regions.regions();
     196             :       bool active = false;
     197             :       // Iterate over the regions instead of looking up our region's
     198             :       // name so we catch typos in the input file option.
     199             :       for (const auto& region_name : *regions_) {
     200             :         const auto region_it = region_map.find(region_name);
     201             :         if (region_it == region_map.end()) {
     202             :           ERROR_NO_TRACE("Unknown region name in ChangeFixedLtsRatio: "
     203             :                          << region_name
     204             :                          << ".  Known regions: " << keys_of(region_map));
     205             :         }
     206             :         if (region_it->second == section->id()) {
     207             :           active = true;
     208             :           // Don't break here so we check the remaining names for validity.
     209             :         }
     210             :       }
     211             :       if (not active) {
     212             :         return;
     213             :       }
     214             :     }
     215             : 
     216             :     const double current_step = db::get<::Tags::TimeStep>(*box).value();
     217             : 
     218             :     TimeStepRequestProcessor step_requests(time_step_id.time_runs_forward());
     219             :     bool synchronization_required = false;
     220             :     for (const auto& step_chooser : step_choosers_) {
     221             :       step_requests.process(
     222             :           step_chooser->template desired_step<StepChoosersToUse>(current_step,
     223             :                                                                  *box));
     224             :       // We must synchronize if any step chooser requires it, not just
     225             :       // the limiting one, because choosers requiring synchronization
     226             :       // can be limiting on some processors and not others.
     227             :       if (not synchronization_required) {
     228             :         synchronization_required = step_chooser->uses_local_data();
     229             :       }
     230             :     }
     231             : 
     232             :     const double desired_step_size = std::abs(step_requests.step_size(
     233             :         time_step_id.step_time().value(), current_step));
     234             : 
     235             :     // The processing action will consider anything past the end of
     236             :     // the slab as at the start of the next slab.  The delay could be
     237             :     // off by a bit because of that, but we don't have to worry about
     238             :     // figuring out when the slab will end.
     239             :     const StepId step_to_change{
     240             :         time_step_id.slab_number(),
     241             :         db::get<::Tags::StepNumberWithinSlab>(*box) + delay_change_};
     242             : 
     243             :     db::mutate<
     244             :         evolution::dg::Tags::ChangeFixedLtsRatio::NumberOfExpectedMessages>(
     245             :         [&](const gsl::not_null<std::map<StepId, size_t>*> expected) {
     246             :           ++(*expected)[step_to_change];
     247             :         },
     248             :         box);
     249             : 
     250             :     if constexpr (Parallel::is_dg_element_collection_v<ParallelComponent>) {
     251             :       (void)cache, (void)array_index;
     252             :       ERROR("Reductions not implemented for DgElementCollection.");
     253             :     } else {
     254             :       if (synchronization_required) {
     255             :         const auto& component_proxy =
     256             :             Parallel::get_parallel_component<ParallelComponent>(cache);
     257             :         const auto& self_proxy = component_proxy[array_index];
     258             :         // As usual, Charm section stuff doesn't work very well, so we
     259             :         // can't send the result to just the section.
     260             :         Parallel::contribute_to_reduction<
     261             :             ChangeFixedLtsRatio_detail::StoreNewStep<Dim>>(
     262             :             ReductionData(section->id(), step_to_change, desired_step_size),
     263             :             self_proxy, component_proxy, make_not_null(&*section));
     264             :       } else {
     265             :         db::mutate<evolution::dg::Tags::ChangeFixedLtsRatio::NewStepSize>(
     266             :             [&](const gsl::not_null<std::map<StepId, std::vector<double>>*>
     267             :                     step_sizes) {
     268             :               (*step_sizes)[step_to_change].push_back(desired_step_size);
     269             :             },
     270             :             box);
     271             :       }
     272             :     }
     273             :   }
     274             : 
     275           0 :   using is_ready_argument_tags = tmpl::list<>;
     276             : 
     277             :   template <typename Metavariables, typename ArrayIndex, typename Component>
     278           0 :   bool is_ready(Parallel::GlobalCache<Metavariables>& /*cache*/,
     279             :                 const ArrayIndex& /*array_index*/,
     280             :                 const Component* const /*meta*/) const {
     281             :     return true;
     282             :   }
     283             : 
     284           1 :   bool needs_evolved_variables() const override {
     285             :     // This depends on the chosen StepChoosers, but they don't have a
     286             :     // way to report this information so we just return true to be
     287             :     // safe.
     288             :     return true;
     289             :   }
     290             : 
     291           0 :   void pup(PUP::er& p) override {
     292             :     p | step_choosers_;
     293             :     p | delay_change_;
     294             :     p | regions_;
     295             :   }
     296             : 
     297           1 :   std::unordered_map<std::type_index, StepperErrorTolerances> tolerances()
     298             :       const override {
     299             :     std::unordered_map<std::type_index, StepperErrorTolerances> tolerances{};
     300             :     for (const auto& step_chooser : step_choosers_) {
     301             :       collect_stepper_error_tolerances(&tolerances, *step_chooser);
     302             :     }
     303             :     return tolerances;
     304             :   }
     305             : 
     306             :  private:
     307             :   std::vector<std::unique_ptr<StepChooser<StepChooserUse::LtsStep>>>
     308           0 :       step_choosers_;
     309           0 :   uint64_t delay_change_ = std::numeric_limits<uint64_t>::max();
     310           0 :   std::optional<std::vector<std::string>> regions_{};
     311             : };
     312             : 
     313             : template <size_t Dim, typename StepChoosersToUse>
     314             : // NOLINTNEXTLINE
     315           0 : PUP::able::PUP_ID ChangeFixedLtsRatio<Dim, StepChoosersToUse>::my_PUP_ID = 0;
     316             : }  // namespace dg::Events

Generated by: LCOV version 1.14