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