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 : #include <type_traits>
8 :
9 : #include "DataStructures/DataBox/PrefixHelpers.hpp"
10 : #include "DataStructures/MathWrapper.hpp"
11 : #include "Time/BoundaryHistory.hpp"
12 : #include "Time/TimeSteppers/TimeStepper.hpp"
13 : #include "Utilities/GenerateInstantiations.hpp"
14 : #include "Utilities/Gsl.hpp"
15 : #include "Utilities/Serialization/CharmPupable.hpp"
16 :
17 : /// \cond
18 : class TimeDelta;
19 : class TimeStepId;
20 : /// \endcond
21 :
22 : /// \cond
23 : #define LTS_TIME_STEPPER_WRAPPED_TYPE(data) BOOST_PP_TUPLE_ELEM(0, data)
24 : #define LTS_TIME_STEPPER_DERIVED_CLASS(data) BOOST_PP_TUPLE_ELEM(1, data)
25 : #define LTS_TIME_STEPPER_DERIVED_CLASS_TEMPLATE(data) \
26 : BOOST_PP_TUPLE_ELEM(2, data)
27 : /// \endcond
28 :
29 : /// \ingroup TimeSteppersGroup
30 : ///
31 : /// Base class for TimeSteppers with local time-stepping support,
32 : /// derived from TimeStepper.
33 : ///
34 : /// Several of the member functions of this class are templated and
35 : /// perform type erasure before forwarding their arguments to the
36 : /// derived classes. This is implemented using the macros \ref
37 : /// LTS_TIME_STEPPER_DECLARE_OVERLOADS, which must be placed in a
38 : /// private section of the class body, and
39 : /// LTS_TIME_STEPPER_DEFINE_OVERLOADS(derived_class), which must be
40 : /// placed in the cpp file.
41 1 : class LtsTimeStepper : public virtual TimeStepper {
42 : public:
43 0 : static constexpr bool local_time_stepping = true;
44 0 : using provided_time_stepper_interfaces =
45 : tmpl::list<LtsTimeStepper, TimeStepper>;
46 :
47 0 : WRAPPED_PUPable_abstract(LtsTimeStepper); // NOLINT
48 :
49 : // These two are defined as separate type aliases to keep the
50 : // doxygen page width somewhat under control.
51 : template <typename LocalVars, typename RemoteVars, typename Coupling>
52 0 : using BoundaryHistoryType = TimeSteppers::BoundaryHistory<
53 : LocalVars, RemoteVars,
54 : math_wrapper_type<
55 : std::invoke_result_t<const Coupling&, LocalVars, RemoteVars>>>;
56 :
57 : /// Return type of boundary-related functions. The coupling returns
58 : /// the derivative of the variables, but this is multiplied by the
59 : /// time step so the return type should not have `dt` prefixes.
60 : template <typename LocalVars, typename RemoteVars, typename Coupling>
61 1 : using BoundaryReturn = db::unprefix_variables<
62 : std::invoke_result_t<const Coupling&, LocalVars, RemoteVars>>;
63 :
64 : /// \cond
65 : #define LTS_TIME_STEPPER_DECLARE_VIRTUALS_IMPL(_, data) \
66 : virtual void add_boundary_delta_forward( \
67 : gsl::not_null<LTS_TIME_STEPPER_WRAPPED_TYPE(data)*> result, \
68 : const TimeSteppers::ConstBoundaryHistoryTimes& local_times, \
69 : const TimeSteppers::ConstBoundaryHistoryTimes& remote_times, \
70 : const TimeSteppers::BoundaryHistoryEvaluator< \
71 : LTS_TIME_STEPPER_WRAPPED_TYPE(data)>& coupling, \
72 : const TimeDelta& time_step) const = 0; \
73 : virtual void boundary_dense_output_forward( \
74 : gsl::not_null<LTS_TIME_STEPPER_WRAPPED_TYPE(data)*> result, \
75 : const TimeSteppers::ConstBoundaryHistoryTimes& local_times, \
76 : const TimeSteppers::ConstBoundaryHistoryTimes& remote_times, \
77 : const TimeSteppers::BoundaryHistoryEvaluator< \
78 : LTS_TIME_STEPPER_WRAPPED_TYPE(data)>& coupling, \
79 : double time) const = 0;
80 :
81 : GENERATE_INSTANTIATIONS(LTS_TIME_STEPPER_DECLARE_VIRTUALS_IMPL,
82 : (MATH_WRAPPER_TYPES))
83 : #undef LTS_TIME_STEPPER_DECLARE_VIRTUALS_IMPL
84 : /// \endcond
85 :
86 : /// \brief Check whether a neighbor record is needed for boundary
87 : /// output.
88 : ///
89 : /// In order to perform boundary output, all records from the
90 : /// neighbor with `TimeStepId`s for which this method returns true
91 : /// should have been added to the history. Versions are provided
92 : /// for a substep and for dense output.
93 : /// @{
94 1 : virtual bool neighbor_data_required(
95 : const TimeStepId& next_substep_id,
96 : const TimeStepId& neighbor_data_id) const = 0;
97 :
98 1 : virtual bool neighbor_data_required(
99 : double dense_output_time, const TimeStepId& neighbor_data_id) const = 0;
100 : /// @}
101 :
102 : /// \brief Compute the change in a boundary quantity due to the
103 : /// coupling on the interface.
104 : ///
105 : /// The coupling function `coupling` should take the local and
106 : /// remote flux data and compute the derivative of the boundary
107 : /// quantity. These values may be used to form a linear combination
108 : /// internally, so the result should have appropriate mathematical
109 : /// operators defined to allow that.
110 : ///
111 : /// Derived classes must implement this as a function with signature
112 : ///
113 : /// ```
114 : /// template <typename T>
115 : /// void add_boundary_delta_impl(
116 : /// gsl::not_null<T*> result,
117 : /// const TimeSteppers::ConstBoundaryHistoryTimes& local_times,
118 : /// const TimeSteppers::ConstBoundaryHistoryTimes& remote_times,
119 : /// const TimeSteppers::BoundaryHistoryEvaluator<T>& coupling,
120 : /// const TimeDelta& time_step) const;
121 : /// ```
122 : ///
123 : /// \note
124 : /// Unlike the `update_u` methods, which overwrite the `result`
125 : /// argument, this function adds the result to the existing value.
126 : template <typename LocalVars, typename RemoteVars, typename Coupling>
127 1 : void add_boundary_delta(
128 : const gsl::not_null<BoundaryReturn<LocalVars, RemoteVars, Coupling>*>
129 : result,
130 : const BoundaryHistoryType<LocalVars, RemoteVars, Coupling>& history,
131 : const TimeDelta& time_step, const Coupling& coupling) const {
132 : return add_boundary_delta_forward(&*make_math_wrapper(result),
133 : history.local(), history.remote(),
134 : history.evaluator(coupling), time_step);
135 : }
136 :
137 : /// Remove old entries from the history.
138 : ///
139 : /// This should be called after update_u and dense output.
140 : /// Afterward, the history will generally require a new local entry
141 : /// to be added before it can be used by the TimeStepper.
142 : ///
143 : /// Derived classes must implement this as a function with signature
144 : ///
145 : /// ```
146 : /// void clean_boundary_history_impl(
147 : /// const TimeSteppers::MutableBoundaryHistoryTimes& local_times,
148 : /// const TimeSteppers::MutableBoundaryHistoryTimes& remote_times)
149 : /// const override;
150 : /// ```
151 : template <typename LocalVars, typename RemoteVars, typename CouplingResult>
152 1 : void clean_boundary_history(
153 : const gsl::not_null<
154 : TimeSteppers::BoundaryHistory<LocalVars, RemoteVars, CouplingResult>*>
155 : history) const {
156 : return clean_boundary_history_impl(history->local(), history->remote());
157 : }
158 :
159 : /// Derived classes must implement this as a function with signature
160 : ///
161 : /// ```
162 : /// template <typename T>
163 : /// void boundary_dense_output_impl(
164 : /// gsl::not_null<T*> result,
165 : /// const TimeSteppers::ConstBoundaryHistoryTimes& local_times,
166 : /// const TimeSteppers::ConstBoundaryHistoryTimes& remote_times,
167 : /// const TimeSteppers::BoundaryHistoryEvaluator<T>& coupling,
168 : /// double time) const;
169 : /// ```
170 : template <typename LocalVars, typename RemoteVars, typename Coupling>
171 1 : void boundary_dense_output(
172 : const gsl::not_null<BoundaryReturn<LocalVars, RemoteVars, Coupling>*>
173 : result,
174 : const BoundaryHistoryType<LocalVars, RemoteVars, Coupling>& history,
175 : const double time, const Coupling& coupling) const {
176 : return boundary_dense_output_forward(&*make_math_wrapper(result),
177 : history.local(), history.remote(),
178 : history.evaluator(coupling), time);
179 : }
180 :
181 : private:
182 0 : virtual void clean_boundary_history_impl(
183 : const TimeSteppers::MutableBoundaryHistoryTimes& local_times,
184 : const TimeSteppers::MutableBoundaryHistoryTimes& remote_times) const = 0;
185 : };
186 :
187 : /// \cond
188 : #define LTS_TIME_STEPPER_DECLARE_OVERLOADS_IMPL(_, data) \
189 : void add_boundary_delta_forward( \
190 : gsl::not_null<LTS_TIME_STEPPER_WRAPPED_TYPE(data)*> result, \
191 : const TimeSteppers::ConstBoundaryHistoryTimes& local_times, \
192 : const TimeSteppers::ConstBoundaryHistoryTimes& remote_times, \
193 : const TimeSteppers::BoundaryHistoryEvaluator< \
194 : LTS_TIME_STEPPER_WRAPPED_TYPE(data)>& coupling, \
195 : const TimeDelta& time_step) const override; \
196 : void boundary_dense_output_forward( \
197 : gsl::not_null<LTS_TIME_STEPPER_WRAPPED_TYPE(data)*> result, \
198 : const TimeSteppers::ConstBoundaryHistoryTimes& local_times, \
199 : const TimeSteppers::ConstBoundaryHistoryTimes& remote_times, \
200 : const TimeSteppers::BoundaryHistoryEvaluator< \
201 : LTS_TIME_STEPPER_WRAPPED_TYPE(data)>& coupling, \
202 : double time) const override;
203 :
204 : #define LTS_TIME_STEPPER_DEFINE_OVERLOADS_IMPL(_, data) \
205 : LTS_TIME_STEPPER_DERIVED_CLASS_TEMPLATE(data) \
206 : void LTS_TIME_STEPPER_DERIVED_CLASS(data)::add_boundary_delta_forward( \
207 : const gsl::not_null<LTS_TIME_STEPPER_WRAPPED_TYPE(data)*> result, \
208 : const TimeSteppers::ConstBoundaryHistoryTimes& local_times, \
209 : const TimeSteppers::ConstBoundaryHistoryTimes& remote_times, \
210 : const TimeSteppers::BoundaryHistoryEvaluator< \
211 : LTS_TIME_STEPPER_WRAPPED_TYPE(data)>& coupling, \
212 : const TimeDelta& time_step) const { \
213 : return add_boundary_delta_impl(result, local_times, remote_times, \
214 : coupling, time_step); \
215 : } \
216 : LTS_TIME_STEPPER_DERIVED_CLASS_TEMPLATE(data) \
217 : void LTS_TIME_STEPPER_DERIVED_CLASS(data)::boundary_dense_output_forward( \
218 : const gsl::not_null<LTS_TIME_STEPPER_WRAPPED_TYPE(data)*> result, \
219 : const TimeSteppers::ConstBoundaryHistoryTimes& local_times, \
220 : const TimeSteppers::ConstBoundaryHistoryTimes& remote_times, \
221 : const TimeSteppers::BoundaryHistoryEvaluator< \
222 : LTS_TIME_STEPPER_WRAPPED_TYPE(data)>& coupling, \
223 : const double time) const { \
224 : return boundary_dense_output_impl(result, local_times, remote_times, \
225 : coupling, time); \
226 : }
227 : /// \endcond
228 :
229 : /// \ingroup TimeSteppersGroup
230 : /// Macro declaring overloaded detail methods in classes derived from
231 : /// TimeStepper. Must be placed in a private section of the class
232 : /// body.
233 1 : #define LTS_TIME_STEPPER_DECLARE_OVERLOADS \
234 : GENERATE_INSTANTIATIONS(LTS_TIME_STEPPER_DECLARE_OVERLOADS_IMPL, \
235 : (MATH_WRAPPER_TYPES))
236 :
237 : /// \ingroup TimeSteppersGroup
238 : /// Macro defining overloaded detail methods in classes derived from
239 : /// TimeStepper. Must be placed in the cpp file for the derived
240 : /// class.
241 : /// @{
242 1 : #define LTS_TIME_STEPPER_DEFINE_OVERLOADS(derived_class) \
243 : GENERATE_INSTANTIATIONS(LTS_TIME_STEPPER_DEFINE_OVERLOADS_IMPL, \
244 : (MATH_WRAPPER_TYPES), (derived_class), ())
245 : #define LTS_TIME_STEPPER_DEFINE_OVERLOADS_TEMPLATED(derived_class, \
246 1 : template_args) \
247 : GENERATE_INSTANTIATIONS(LTS_TIME_STEPPER_DEFINE_OVERLOADS_IMPL, \
248 : (MATH_WRAPPER_TYPES), (derived_class), \
249 : (template <template_args>))
250 : /// @}
|