Line data Source code
1 0 : // Distributed under the MIT License. 2 : // See LICENSE.txt for details. 3 : 4 : #pragma once 5 : 6 : #include <pup.h> 7 : 8 : #include "DataStructures/DataBox/DataBox.hpp" 9 : #include "DataStructures/DataBox/MetavariablesTag.hpp" 10 : #include "Time/TimeStepRequest.hpp" 11 : #include "Utilities/CallWithDynamicType.hpp" 12 : #include "Utilities/ErrorHandling/Assert.hpp" 13 : #include "Utilities/Serialization/CharmPupable.hpp" 14 : #include "Utilities/TMPL.hpp" 15 : #include "Utilities/TypeTraits/CreateGetTypeAliasOrDefault.hpp" 16 : 17 : /// The intended use for a step chooser. This is used to control the 18 : /// classes via factories. 19 1 : namespace StepChooserUse { 20 : struct Slab; 21 : struct LtsStep; 22 : } // namespace StepChooserUse 23 : 24 : /// \cond 25 : template <typename StepChooserUse> 26 : class StepChooser; 27 : /// \endcond 28 : 29 : /// \ingroup TimeGroup 30 : /// 31 : /// Holds all the StepChoosers 32 : namespace StepChoosers { 33 : 34 : namespace detail { 35 : CREATE_GET_TYPE_ALIAS_OR_DEFAULT(compute_tags) 36 : CREATE_GET_TYPE_ALIAS_OR_DEFAULT(simple_tags) 37 : 38 : template <typename Metavariables> 39 : using all_step_choosers = tmpl::join<tmpl::remove< 40 : tmpl::list< 41 : tmpl::at<typename Metavariables::factory_creation::factory_classes, 42 : StepChooser<StepChooserUse::Slab>>, 43 : tmpl::at<typename Metavariables::factory_creation::factory_classes, 44 : StepChooser<StepChooserUse::LtsStep>>>, 45 : tmpl::no_such_type_>>; 46 : } // namespace detail 47 : 48 : template <typename Metavariables> 49 0 : using step_chooser_compute_tags = tmpl::remove_duplicates< 50 : tmpl::join<tmpl::transform<detail::all_step_choosers<Metavariables>, 51 : detail::get_compute_tags_or_default< 52 : tmpl::_1, tmpl::pin<tmpl::list<>>>>>>; 53 : 54 : template <typename Metavariables> 55 0 : using step_chooser_simple_tags = tmpl::remove_duplicates< 56 : tmpl::join<tmpl::transform<detail::all_step_choosers<Metavariables>, 57 : detail::get_simple_tags_or_default< 58 : tmpl::_1, tmpl::pin<tmpl::list<>>>>>>; 59 : } // namespace StepChoosers 60 : 61 : /// A placeholder type to indicate that all constructible step choosers should 62 : /// be used in step chooser utilities that permit a list of choosers to be 63 : /// specified. 64 1 : struct AllStepChoosers {}; 65 : 66 : /// \ingroup TimeGroup 67 : /// 68 : /// \brief StepChoosers suggest upper bounds on step sizes. See 69 : /// `TimeStepRequest` for details on how the results are used. 70 : /// 71 : /// Concrete StepChoosers should define `operator()` returning the 72 : /// desired step and taking the `last_step` and arguments specified by 73 : /// the class's `argument_tags` type alias. 74 : /// 75 : /// Derived classes must indicate whether the chooser is usable as a 76 : /// step chooser, slab chooser, or both by inheriting from StepChooser 77 : /// with the appropriate `StepChooserUse` template argument. 78 : template <typename StepChooserUse> 79 1 : class StepChooser : public virtual PUP::able { 80 : protected: 81 : /// \cond HIDDEN_SYMBOLS 82 : StepChooser() = default; 83 : StepChooser(const StepChooser&) = default; 84 : StepChooser(StepChooser&&) = default; 85 : StepChooser& operator=(const StepChooser&) = default; 86 : StepChooser& operator=(StepChooser&&) = default; 87 : /// \endcond 88 : 89 : public: 90 0 : ~StepChooser() override = default; 91 : 92 0 : WRAPPED_PUPable_abstract(StepChooser); // NOLINT 93 : 94 : /// Whether the result can differ on different elements, so 95 : /// requiring communication to synchronize the result across the 96 : /// domain. This is ignored for LTS step changing. 97 : /// 98 : /// \note As this is only used for slab-size changing, the 99 : /// `last_step` passed to the call operator is *not* considered 100 : /// local data. 101 1 : virtual bool uses_local_data() const = 0; 102 : 103 : /// Whether the result can be applied with a delay. 104 : /// 105 : /// StepChoosers setting the `.end` or `.end_hard_limit` fields of 106 : /// `TimeStepRequest` must return false here. 107 1 : virtual bool can_be_delayed() const = 0; 108 : 109 : /// Whether the StepChooser's output only makes sense for setting 110 : /// the step size, as opposed to using it to set the slab size in an 111 : /// LTS evolution. 112 : /// 113 : /// This is generally true for StepChoosers that explicitly use past 114 : /// step sizes to compute their suggestion and false for others. 115 1 : virtual bool must_set_step_size() const = 0; 116 : 117 : /// The `last_step` parameter describes the step size to be 118 : /// adjusted. It may be the step size or the slab size, or may be 119 : /// infinite if the appropriate size cannot be determined. 120 : /// 121 : /// The optional template parameter `StepChoosersToUse` may be used to 122 : /// indicate a subset of the constructable step choosers to use for the 123 : /// current application of `ChangeStepSize`. Passing `AllStepChoosers` 124 : /// (default) indicates that any constructible step chooser may be used. This 125 : /// option is used when multiple components need to invoke `ChangeStepSize` 126 : /// with step choosers that may not be compatible with all components. 127 : template <typename StepChoosersToUse = AllStepChoosers, typename DbTags> 128 1 : TimeStepRequest desired_step(const double last_step, 129 : const db::DataBox<DbTags>& box) const { 130 : using factory_classes = 131 : typename std::decay_t<decltype(db::get<Parallel::Tags::Metavariables>( 132 : box))>::factory_creation::factory_classes; 133 : using step_choosers = 134 : tmpl::conditional_t<std::is_same_v<StepChoosersToUse, AllStepChoosers>, 135 : tmpl::at<factory_classes, StepChooser>, 136 : StepChoosersToUse>; 137 : const auto result = call_with_dynamic_type<TimeStepRequest, step_choosers>( 138 : this, [&last_step, &box](const auto* const chooser) { 139 : return db::apply(*chooser, box, last_step); 140 : }); 141 : ASSERT(not result.size_goal.has_value() or 142 : (*result.size_goal > 0.) == (last_step > 0.), 143 : "Step size changed sign: " << *result.size_goal); 144 : ASSERT( 145 : not result.size.has_value() or (*result.size > 0.) == (last_step > 0.), 146 : "Step size changed sign: " << *result.size); 147 : ASSERT(not result.size_hard_limit.has_value() or 148 : (*result.size_hard_limit > 0.) == (last_step > 0.), 149 : "Step size changed sign: " << *result.size_hard_limit); 150 : ASSERT(not(result.end.has_value() and can_be_delayed()), 151 : "Delayable end limits are not allowed."); 152 : ASSERT(not(result.end_hard_limit.has_value() and can_be_delayed()), 153 : "Delayable end limits are not allowed."); 154 : return result; 155 : } 156 : };