Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <cstddef>
7 : #include <cstdint>
8 : #include <optional>
9 :
10 : #include "DataStructures/TaggedVariant.hpp"
11 : #include "Options/Auto.hpp"
12 : #include "Options/Context.hpp"
13 : #include "Options/String.hpp"
14 : #include "Time/StepperErrorEstimate.hpp"
15 : #include "Time/StepperErrorTolerances.hpp"
16 : #include "Time/TimeStepId.hpp"
17 : #include "Time/TimeSteppers/LtsTimeStepper.hpp"
18 : #include "Utilities/Serialization/CharmPupable.hpp"
19 : #include "Utilities/TMPL.hpp"
20 :
21 : /// \cond
22 : struct ApproximateTime;
23 : class TimeDelta;
24 : namespace PUP {
25 : class er;
26 : } // namespace PUP
27 : namespace TimeSteppers {
28 : template <typename T>
29 : class BoundaryHistoryEvaluator;
30 : class ConstBoundaryHistoryTimes;
31 : template <typename T>
32 : class ConstUntypedHistory;
33 : class MutableBoundaryHistoryTimes;
34 : template <typename T>
35 : class MutableUntypedHistory;
36 : } // namespace TimeSteppers
37 : namespace gsl {
38 : template <class T>
39 : class not_null;
40 : } // namespace gsl
41 : /// \endcond
42 :
43 : namespace TimeSteppers {
44 :
45 : /*!
46 : * \ingroup TimeSteppersGroup
47 : *
48 : * An Nth order Adams-Bashforth time stepper.
49 : *
50 : * The stable step size factors for different orders are given by:
51 : *
52 : * <table class="doxtable">
53 : * <tr>
54 : * <th> %Order </th>
55 : * <th> CFL Factor </th>
56 : * </tr>
57 : * <tr>
58 : * <td> 1 </td>
59 : * <td> 1 </td>
60 : * </tr>
61 : * <tr>
62 : * <td> 2 </td>
63 : * <td> 1 / 2 </td>
64 : * </tr>
65 : * <tr>
66 : * <td> 3 </td>
67 : * <td> 3 / 11 </td>
68 : * </tr>
69 : * <tr>
70 : * <td> 4 </td>
71 : * <td> 3 / 20 </td>
72 : * </tr>
73 : * <tr>
74 : * <td> 5 </td>
75 : * <td> 45 / 551 </td>
76 : * </tr>
77 : * <tr>
78 : * <td> 6 </td>
79 : * <td> 5 / 114 </td>
80 : * </tr>
81 : * <tr>
82 : * <td> 7 </td>
83 : * <td> 945 / 40663 </td>
84 : * </tr>
85 : * <tr>
86 : * <td> 8 </td>
87 : * <td> 945 / 77432 </td>
88 : * </tr>
89 : * </table>
90 : *
91 : * \section lts Local time stepping calculation
92 : *
93 : * \f$\newcommand\tL{t^L}\newcommand\tR{t^R}\newcommand\tU{\tilde{t}\!}
94 : * \newcommand\mat{\mathbf}\f$
95 : *
96 : * Suppose the local and remote sides of the interface are evaluated
97 : * at times \f$\ldots, \tL_{-1}, \tL_0, \tL_1, \ldots\f$ and
98 : * \f$\ldots, \tR_{-1}, \tR_0, \tR_1, \ldots\f$, respectively, with
99 : * the starting location of the numbering arbitrary in each case.
100 : * Let the step we wish to calculate the effect of be the step from
101 : * \f$\tL_{m_S}\f$ to \f$\tL_{m_S+1}\f$. We call the sequence
102 : * produced from the union of the local and remote time sequences
103 : * \f$\ldots, \tU_{-1}, \tU_0, \tU_1, \ldots\f$. For example, one
104 : * possible sequence of times is:
105 : * \f{equation}
106 : * \begin{aligned}
107 : * \text{Local side:} \\ \text{Union times:} \\ \text{Remote side:}
108 : * \end{aligned}
109 : * \cdots
110 : * \begin{gathered}
111 : * \, \\ \tU_1 \\ \tR_5
112 : * \end{gathered}
113 : * \leftarrow \Delta \tU_1 \rightarrow
114 : * \begin{gathered}
115 : * \tL_4 \\ \tU_2 \\ \,
116 : * \end{gathered}
117 : * \leftarrow \Delta \tU_2 \rightarrow
118 : * \begin{gathered}
119 : * \, \\ \tU_3 \\ \tR_6
120 : * \end{gathered}
121 : * \leftarrow \Delta \tU_3 \rightarrow
122 : * \begin{gathered}
123 : * \, \\ \tU_4 \\ \tR_7
124 : * \end{gathered}
125 : * \leftarrow \Delta \tU_4 \rightarrow
126 : * \begin{gathered}
127 : * \tL_5 \\ \tU_5 \\ \,
128 : * \end{gathered}
129 : * \cdots
130 : * \f}
131 : * We call the indices of the step's start and end times in the
132 : * union time sequence \f$n_S\f$ and \f$n_E\f$, respectively. We
133 : * define \f$n^L_m\f$ to be the union-time index corresponding to
134 : * \f$\tL_m\f$ and \f$m^L_n\f$ to be the index of the last local
135 : * time not later than \f$\tU_n\f$ and similarly for the remote
136 : * side. So for the above example, \f$n^L_4 = 2\f$ and \f$m^R_2 =
137 : * 5\f$, and if we wish to compute the step from \f$\tL_4\f$ to
138 : * \f$\tL_5\f$ we would have \f$m_S = 4\f$, \f$n_S = 2\f$, and
139 : * \f$n_E = 5\f$.
140 : *
141 : * If we wish to evaluate the change over this step to \f$k\f$th
142 : * order, we can write the change in the value as a linear
143 : * combination of the values of the coupling between the elements at
144 : * unequal times:
145 : * \f{equation}
146 : * \mat{F}_{m_S} =
147 : * \mspace{-10mu}
148 : * \sum_{q^L = m_S-(k-1)}^{m_S}
149 : * \,
150 : * \sum_{q^R = m^R_{n_S}-(k-1)}^{m^R_{n_E-1}}
151 : * \mspace{-10mu}
152 : * \mat{D}_{q^Lq^R}
153 : * I_{q^Lq^R},
154 : * \f}
155 : * where \f$\mat{D}_{q^Lq^R}\f$ is the coupling function evaluated
156 : * between data from \f$\tL_{q^L}\f$ and \f$\tR_{q^R}\f$. The
157 : * coefficients can be written as the sum of three terms,
158 : * \f{equation}
159 : * I_{q^Lq^R} = I^E_{q^Lq^R} + I^R_{q^Lq^R} + I^L_{q^Lq^R},
160 : * \f}
161 : * which can be interpreted as a contribution from equal-time
162 : * evaluations and contributions related to the remote and local
163 : * evaluation times. These are given by
164 : * \f{align}
165 : * I^E_{q^Lq^R} &=
166 : * \mspace{-10mu}
167 : * \sum_{n=n_S}^{\min\left\{n_E, n^L+k\right\}-1}
168 : * \mspace{-10mu}
169 : * \tilde{\alpha}_{n,n-n^L} \Delta \tU_n
170 : * &&\text{if $\tL_{q^L} = \tR_{q^R}$, otherwise 0}
171 : * \\
172 : * I^R_{q^Lq^R} &=
173 : * \ell_{q^L - m_S + k}\!\left(
174 : * \tU_{n^R}; \tL_{m_S - (k-1)}, \ldots, \tL_{m_S}\right)
175 : * \mspace{-10mu}
176 : * \sum_{n=\max\left\{n_S, n^R\right\}}
177 : * ^{\min\left\{n_E, n^R+k\right\}-1}
178 : * \mspace{-10mu}
179 : * \tilde{\alpha}_{n,n-n^R} \Delta \tU_n
180 : * &&\text{if $\tR_{q^R}$ is not in $\{\tL_{\vphantom{|}\cdots}\}$,
181 : * otherwise 0}
182 : * \\
183 : * I^L_{q^Lq^R} &=
184 : * \mspace{-10mu}
185 : * \sum_{n=\max\left\{n_S, n^R\right\}}
186 : * ^{\min\left\{n_E, n^L+k, n^R_{q^R+k}\right\}-1}
187 : * \mspace{-10mu}
188 : * \ell_{q^R - m^R_n + k}\!\left(\tU_{n^L};
189 : * \tR_{m^R_n - (k-1)}, \ldots, \tR_{m^R_n}\right)
190 : * \tilde{\alpha}_{n,n-n^L} \Delta \tU_n
191 : * &&\text{if $\tL_{q^L}$ is not in $\{\tR_{\vphantom{|}\cdots}\}$,
192 : * otherwise 0,}
193 : * \f}
194 : * where for brevity we write \f$n^L = n^L_{q^L}\f$ and \f$n^R =
195 : * n^R_{q^R}\f$, and where \f$\ell_a(t; x_1, \ldots, x_k)\f$ a
196 : * Lagrange interpolating polynomial and \f$\tilde{\alpha}_{nj}\f$
197 : * is the \f$j\f$th coefficient for an Adams-Bashforth step over the
198 : * union times from step \f$n\f$ to step \f$n+1\f$.
199 : */
200 1 : class AdamsBashforth : public LtsTimeStepper {
201 : public:
202 0 : static constexpr const size_t minimum_order = 1;
203 0 : static constexpr const size_t maximum_order = 8;
204 :
205 0 : struct Order {
206 0 : using type = Options::Auto<size_t>;
207 0 : static constexpr Options::String help = {"Convergence order"};
208 : };
209 0 : using options = tmpl::list<Order>;
210 0 : static constexpr Options::String help = {
211 : "An Adams-Bashforth Nth order time-stepper."};
212 :
213 0 : AdamsBashforth() = default;
214 0 : explicit AdamsBashforth(const std::optional<size_t>& order,
215 : const Options::Context& context = {});
216 0 : AdamsBashforth(const AdamsBashforth&) = default;
217 0 : AdamsBashforth& operator=(const AdamsBashforth&) = default;
218 0 : AdamsBashforth(AdamsBashforth&&) = default;
219 0 : AdamsBashforth& operator=(AdamsBashforth&&) = default;
220 0 : ~AdamsBashforth() override = default;
221 :
222 1 : variants::TaggedVariant<Tags::FixedOrder, Tags::VariableOrder> order()
223 : const override;
224 :
225 1 : uint64_t number_of_substeps() const override;
226 :
227 1 : uint64_t number_of_substeps_for_error() const override;
228 :
229 1 : size_t number_of_past_steps() const override;
230 :
231 1 : double stable_step() const override;
232 :
233 1 : bool monotonic() const override;
234 :
235 1 : TimeStepId next_time_id(const TimeStepId& current_id,
236 : const TimeDelta& time_step) const override;
237 :
238 1 : TimeStepId next_time_id_for_error(const TimeStepId& current_id,
239 : const TimeDelta& time_step) const override;
240 :
241 1 : bool neighbor_data_required(
242 : const TimeStepId& next_substep_id,
243 : const TimeStepId& neighbor_data_id) const override;
244 :
245 1 : bool neighbor_data_required(
246 : double dense_output_time,
247 : const TimeStepId& neighbor_data_id) const override;
248 :
249 0 : WRAPPED_PUPable_decl_template(AdamsBashforth); // NOLINT
250 :
251 0 : explicit AdamsBashforth(CkMigrateMessage* /*unused*/) {}
252 :
253 : // clang-tidy: do not pass by non-const reference
254 0 : void pup(PUP::er& p) override; // NOLINT
255 :
256 : private:
257 0 : friend bool operator==(const AdamsBashforth& lhs, const AdamsBashforth& rhs);
258 :
259 : template <bool DenseOutput, typename T>
260 0 : std::optional<StepperErrorEstimate> update_u_common(
261 : gsl::not_null<T*> u, const ConstUntypedHistory<T>& history,
262 : const tmpl::conditional_t<DenseOutput, ApproximateTime, Time>& time,
263 : const StepperErrorTolerances& tolerances) const;
264 :
265 : template <typename T>
266 0 : std::optional<StepperErrorEstimate> update_u_impl(
267 : gsl::not_null<T*> u, const ConstUntypedHistory<T>& history,
268 : const TimeDelta& time_step,
269 : const StepperErrorTolerances& tolerances = {}) const;
270 :
271 : template <typename T>
272 0 : void clean_history_impl(const MutableUntypedHistory<T>& history) const;
273 :
274 : template <typename T>
275 0 : bool dense_update_u_impl(gsl::not_null<T*> u,
276 : const ConstUntypedHistory<T>& history,
277 : double time) const;
278 :
279 : template <typename T>
280 0 : bool can_change_step_size_impl(const TimeStepId& time_id,
281 : const ConstUntypedHistory<T>& history) const;
282 :
283 : template <typename T>
284 0 : void add_boundary_delta_impl(
285 : gsl::not_null<T*> result,
286 : const TimeSteppers::ConstBoundaryHistoryTimes& local_times,
287 : const TimeSteppers::ConstBoundaryHistoryTimes& remote_times,
288 : const TimeSteppers::BoundaryHistoryEvaluator<T>& coupling,
289 : const TimeDelta& time_step) const;
290 :
291 0 : void clean_boundary_history_impl(
292 : const TimeSteppers::MutableBoundaryHistoryTimes& local_times,
293 : const TimeSteppers::MutableBoundaryHistoryTimes& remote_times)
294 : const override;
295 :
296 : template <typename T>
297 0 : void boundary_dense_output_impl(
298 : gsl::not_null<T*> result,
299 : const TimeSteppers::ConstBoundaryHistoryTimes& local_times,
300 : const TimeSteppers::ConstBoundaryHistoryTimes& remote_times,
301 : const TimeSteppers::BoundaryHistoryEvaluator<T>& coupling,
302 : const double time) const;
303 :
304 : TIME_STEPPER_DECLARE_OVERLOADS
305 : LTS_TIME_STEPPER_DECLARE_OVERLOADS
306 :
307 0 : std::optional<size_t> order_{};
308 : };
309 :
310 0 : bool operator!=(const AdamsBashforth& lhs, const AdamsBashforth& rhs);
311 : } // namespace TimeSteppers
|