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 <memory> 9 : #include <optional> 10 : #include <string> 11 : #include <typeinfo> 12 : #include <unordered_map> 13 : #include <vector> 14 : 15 : #include "DataStructures/DataBox/DataBox.hpp" 16 : #include "Options/Auto.hpp" 17 : #include "Options/String.hpp" 18 : #include "Time/EvolutionOrdering.hpp" 19 : #include "Time/RequestsStepperErrorTolerances.hpp" 20 : #include "Time/StepChoosers/StepChooser.hpp" 21 : #include "Time/StepperErrorTolerances.hpp" 22 : #include "Time/TimeStepRequest.hpp" 23 : #include "Utilities/ErrorHandling/Assert.hpp" 24 : #include "Utilities/ErrorHandling/Error.hpp" 25 : #include "Utilities/Serialization/CharmPupable.hpp" 26 : #include "Utilities/StdHelpers.hpp" 27 : #include "Utilities/TMPL.hpp" 28 : 29 : /// \cond 30 : namespace PUP { 31 : class er; 32 : } // namespace PUP 33 : namespace Tags { 34 : struct FixedLtsRatio; 35 : struct TimeStep; 36 : } // namespace Tags 37 : namespace domain::Tags { 38 : template <size_t VolumeDim> 39 : struct Element; 40 : } // namespace domain::Tags 41 : namespace evolution::dg::Tags { 42 : template <size_t Dim> 43 : struct EqualRateRegions; 44 : } // namespace evolution::dg::Tags 45 : /// \endcond 46 : 47 0 : namespace evolution::dg::StepChoosers { 48 : /// Requests a slab size based on the desired step in regions with a 49 : /// fixed slab fraction. 50 : /// 51 : /// \note This StepChooser is not included in the 52 : /// `standard_step_choosers` list. Executables using the feature must 53 : /// include it explicitly in the `factory_creation` struct and add the 54 : /// `::Tags::FixedLtsRatio` tag to the element DataBox. 55 : template <size_t Dim> 56 1 : class FixedLtsRatio : public StepChooser<StepChooserUse::Slab>, 57 : public RequestsStepperErrorTolerances { 58 : public: 59 : /// \cond 60 : FixedLtsRatio() = default; 61 : explicit FixedLtsRatio(CkMigrateMessage* /*unused*/) {} 62 : using PUP::able::register_constructor; 63 : WRAPPED_PUPable_decl_template(FixedLtsRatio); // NOLINT 64 : /// \endcond 65 : 66 0 : struct StepChoosers { 67 0 : using type = 68 : std::vector<std::unique_ptr<::StepChooser<StepChooserUse::LtsStep>>>; 69 0 : static constexpr Options::String help{"LTS step choosers to test"}; 70 : }; 71 : 72 0 : struct Regions { 73 0 : using type = 74 : Options::Auto<std::vector<std::string>, Options::AutoLabel::All>; 75 0 : static constexpr Options::String help{"Regions to adjust based on"}; 76 : }; 77 : 78 0 : static constexpr Options::String help{ 79 : "Requests a slab size based on the desired step in regions with a fixed " 80 : "slab fraction."}; 81 0 : using options = tmpl::list<StepChoosers, Regions>; 82 : 83 0 : explicit FixedLtsRatio( 84 : std::vector<std::unique_ptr<::StepChooser<StepChooserUse::LtsStep>>> 85 : step_choosers, 86 : std::optional<std::vector<std::string>> regions); 87 : 88 0 : using argument_tags = tmpl::list<::Tags::DataBox>; 89 : 90 : template <typename DbTags> 91 0 : TimeStepRequest operator()(const db::DataBox<DbTags>& box, 92 : const double /*last_step*/) const { 93 : const auto& step_ratio = db::get<::Tags::FixedLtsRatio>(box); 94 : if (not step_ratio.has_value()) { 95 : return {}; 96 : } 97 : 98 : if (regions_.has_value()) { 99 : const auto element_id = db::get<domain::Tags::Element<Dim>>(box).id(); 100 : const auto& equal_rate_regions = 101 : db::get<Tags::EqualRateRegions<Dim>>(box); 102 : const auto& region_map = equal_rate_regions.regions(); 103 : bool active = false; 104 : for (const auto& region_name : *regions_) { 105 : const auto region_it = region_map.find(region_name); 106 : if (region_it == region_map.end()) { 107 : ERROR_NO_TRACE("Unknown region name in FixedLtsRatio: " 108 : << region_name 109 : << ". Known regions: " << keys_of(region_map)); 110 : } 111 : if (equal_rate_regions.is_in_region(region_it->second, element_id)) { 112 : active = true; 113 : // Don't break here so we check the remaining names for validity. 114 : } 115 : } 116 : if (not active) { 117 : return {}; 118 : } 119 : } 120 : 121 : const auto& current_step = db::get<::Tags::TimeStep>(box); 122 : const evolution_less<double> less{current_step.is_positive()}; 123 : 124 : std::optional<double> size_goal{}; 125 : std::optional<double> size{}; 126 : for (const auto& step_chooser : step_choosers_) { 127 : const auto step_request = 128 : step_chooser->desired_step(current_step.value(), box); 129 : 130 : if (step_request.size_goal.has_value()) { 131 : if (size_goal.has_value()) { 132 : *size_goal = std::min(*size_goal, *step_request.size_goal, less); 133 : } else { 134 : size_goal = step_request.size_goal; 135 : } 136 : } 137 : if (step_request.size.has_value()) { 138 : if (size.has_value()) { 139 : *size = std::min(*size, *step_request.size, less); 140 : } else { 141 : size = step_request.size; 142 : } 143 : } 144 : 145 : // As of writing (Oct. 2024), no StepChooserUse::LtsStep chooser 146 : // sets these. 147 : ASSERT(not(step_request.end.has_value() or 148 : step_request.size_hard_limit.has_value() or 149 : step_request.end_hard_limit.has_value()), 150 : "Unhandled field set by StepChooser. Please file a bug " 151 : "containing the options passed to FixedLtsRatio."); 152 : } 153 : 154 : if (size_goal.has_value()) { 155 : *size_goal *= *step_ratio; 156 : } 157 : if (size.has_value()) { 158 : *size *= *step_ratio; 159 : if (size_goal.has_value() and less(*size_goal, *size)) { 160 : // Not allowed to request a goal and a bigger step. 161 : size.reset(); 162 : } 163 : } 164 : 165 : return {.size_goal = size_goal, .size = size}; 166 : } 167 : 168 1 : bool uses_local_data() const override; 169 1 : bool can_be_delayed() const override; 170 1 : bool must_set_step_size() const override; 171 : 172 1 : std::unordered_map<std::type_index, StepperErrorTolerances> tolerances() 173 : const override; 174 : 175 0 : void pup(PUP::er& p) override; 176 : 177 : private: 178 : std::vector<std::unique_ptr<::StepChooser<StepChooserUse::LtsStep>>> 179 0 : step_choosers_; 180 0 : std::optional<std::vector<std::string>> regions_; 181 : }; 182 : } // namespace evolution::dg::StepChoosers