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 : };
|