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