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, bool UsingLts> 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::conditional_t< 44 : UsingLts, 45 : tmpl::at<typename Metavariables::factory_creation::factory_classes, 46 : StepChooser<StepChooserUse::LtsStep>>, 47 : tmpl::no_such_type_>>, 48 : tmpl::no_such_type_>>; 49 : } // namespace detail 50 : 51 : template <typename Metavariables, bool UsingLts> 52 0 : using step_chooser_compute_tags = tmpl::remove_duplicates<tmpl::join< 53 : tmpl::transform<detail::all_step_choosers<Metavariables, UsingLts>, 54 : detail::get_compute_tags_or_default< 55 : tmpl::_1, tmpl::pin<tmpl::list<>>>>>>; 56 : 57 : template <typename Metavariables, bool UsingLts> 58 0 : using step_chooser_simple_tags = tmpl::remove_duplicates<tmpl::join< 59 : tmpl::transform<detail::all_step_choosers<Metavariables, UsingLts>, 60 : detail::get_simple_tags_or_default< 61 : tmpl::_1, tmpl::pin<tmpl::list<>>>>>>; 62 : } // namespace StepChoosers 63 : 64 : /// A placeholder type to indicate that all constructible step choosers should 65 : /// be used in step chooser utilities that permit a list of choosers to be 66 : /// specified. 67 1 : struct AllStepChoosers {}; 68 : 69 : /// \ingroup TimeGroup 70 : /// 71 : /// \brief StepChoosers suggest upper bounds on step sizes. See 72 : /// `TimeStepRequest` for details on how the results are used. 73 : /// 74 : /// Concrete StepChoosers should define `operator()` returning the 75 : /// desired step and taking the `last_step` and arguments specified by 76 : /// the class's `argument_tags` type alias. 77 : /// 78 : /// Derived classes must indicate whether the chooser is usable as a 79 : /// step chooser, slab chooser, or both by inheriting from StepChooser 80 : /// with the appropriate `StepChooserUse` template argument. 81 : template <typename StepChooserUse> 82 1 : class StepChooser : public virtual PUP::able { 83 : protected: 84 : /// \cond HIDDEN_SYMBOLS 85 : StepChooser() = default; 86 : StepChooser(const StepChooser&) = default; 87 : StepChooser(StepChooser&&) = default; 88 : StepChooser& operator=(const StepChooser&) = default; 89 : StepChooser& operator=(StepChooser&&) = default; 90 : /// \endcond 91 : 92 : public: 93 0 : ~StepChooser() override = default; 94 : 95 0 : WRAPPED_PUPable_abstract(StepChooser); // NOLINT 96 : 97 : /// Whether the result can differ on different elements, so 98 : /// requiring communication to synchronize the result across the 99 : /// domain. This is ignored for LTS step changing. 100 : /// 101 : /// \note As this is only used for slab-size changing, the 102 : /// `last_step` passed to the call operator is *not* considered 103 : /// local data. 104 1 : virtual bool uses_local_data() const = 0; 105 : 106 : /// Whether the result can be applied with a delay. 107 : /// 108 : /// StepChoosers setting the `.end` or `.end_hard_limit` fields of 109 : /// `TimeStepRequest` must return false here. 110 1 : virtual bool can_be_delayed() const = 0; 111 : 112 : /// The `last_step` parameter describes the step size to be 113 : /// adjusted. It may be the step size or the slab size, or may be 114 : /// infinite if the appropriate size cannot be determined. 115 : /// 116 : /// The optional template parameter `StepChoosersToUse` may be used to 117 : /// indicate a subset of the constructable step choosers to use for the 118 : /// current application of `ChangeStepSize`. Passing `AllStepChoosers` 119 : /// (default) indicates that any constructible step chooser may be used. This 120 : /// option is used when multiple components need to invoke `ChangeStepSize` 121 : /// with step choosers that may not be compatible with all components. 122 : template <typename StepChoosersToUse = AllStepChoosers, typename DbTags> 123 1 : TimeStepRequest desired_step(const double last_step, 124 : const db::DataBox<DbTags>& box) const { 125 : using factory_classes = 126 : typename std::decay_t<decltype(db::get<Parallel::Tags::Metavariables>( 127 : box))>::factory_creation::factory_classes; 128 : using step_choosers = 129 : tmpl::conditional_t<std::is_same_v<StepChoosersToUse, AllStepChoosers>, 130 : tmpl::at<factory_classes, StepChooser>, 131 : StepChoosersToUse>; 132 : const auto result = call_with_dynamic_type<TimeStepRequest, step_choosers>( 133 : this, [&last_step, &box](const auto* const chooser) { 134 : return db::apply(*chooser, box, last_step); 135 : }); 136 : ASSERT(not result.size_goal.has_value() or 137 : (*result.size_goal > 0.) == (last_step > 0.), 138 : "Step size changed sign: " << *result.size_goal); 139 : ASSERT( 140 : not result.size.has_value() or (*result.size > 0.) == (last_step > 0.), 141 : "Step size changed sign: " << *result.size); 142 : ASSERT(not result.size_hard_limit.has_value() or 143 : (*result.size_hard_limit > 0.) == (last_step > 0.), 144 : "Step size changed sign: " << *result.size_hard_limit); 145 : ASSERT(not(result.end.has_value() and can_be_delayed()), 146 : "Delayable end limits are not allowed."); 147 : ASSERT(not(result.end_hard_limit.has_value() and can_be_delayed()), 148 : "Delayable end limits are not allowed."); 149 : return result; 150 : } 151 : };