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