SpECTRE Documentation Coverage Report
Current view: top level - ParallelAlgorithms/Events - ChangeFixedLtsRatio.hpp Coverage Total Hit
Commit: 0d1d717af84a81fb1284a20c4013708fe85cc2f0 Lines: 6.2 % 32 2
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 <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 2.0-1