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