Line data Source code
1 0 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : #pragma once
5 :
6 : #include <boost/container/small_vector.hpp>
7 : #include <cstddef>
8 : #include <tuple>
9 :
10 : #include "Time/TimeStepId.hpp"
11 : #include "Time/TimeSteppers/AdamsCoefficients.hpp"
12 :
13 : /// \cond
14 : class Time;
15 : namespace TimeSteppers {
16 : template <typename T>
17 : class BoundaryHistoryEvaluator;
18 : class ConstBoundaryHistoryTimes;
19 : } // namespace TimeSteppers
20 : namespace gsl {
21 : template <class T>
22 : class not_null;
23 : } // namespace gsl
24 : /// \endcond
25 :
26 : /// Shared LTS implementation for the two Adams-based methods.
27 1 : namespace TimeSteppers::adams_lts {
28 : /// Get the time of a substep as a `Time`, assuming substeps are at
29 : /// the end of the step.
30 1 : Time exact_substep_time(const TimeStepId& id);
31 :
32 : // For order-k 2:1 stepping, in each small step, half the points will
33 : // require interpolation (k entries each) and the others will not (1
34 : // entry each). So (2 small steps) * ((k/2 interpolations) * (from k
35 : // points) + (k/2 non-interpolations)) = k (k + 1). (The small steps
36 : // round k/2 in different directions and the effect cancels out.)
37 0 : constexpr size_t lts_coefficients_static_size =
38 : adams_coefficients::maximum_order * (adams_coefficients::maximum_order + 1);
39 :
40 : /// Storage for LTS coefficients that should not allocate in typical
41 : /// cases. Each entry is a tuple of (local id, remote id,
42 : /// coefficient). The contents should be kept sorted, as some
43 : /// functions assume that.
44 1 : struct LtsCoefficients
45 : : boost::container::small_vector<std::tuple<TimeStepId, TimeStepId, double>,
46 : lts_coefficients_static_size> {
47 : using boost::container::small_vector<
48 : std::tuple<TimeStepId, TimeStepId, double>,
49 : lts_coefficients_static_size>::small_vector;
50 : };
51 :
52 0 : LtsCoefficients& operator+=(LtsCoefficients& a, const LtsCoefficients& b);
53 0 : LtsCoefficients& operator-=(LtsCoefficients& a, const LtsCoefficients& b);
54 :
55 0 : LtsCoefficients operator+(LtsCoefficients&& a, LtsCoefficients&& b);
56 0 : LtsCoefficients operator+(LtsCoefficients&& a, const LtsCoefficients& b);
57 0 : LtsCoefficients operator+(const LtsCoefficients& a, LtsCoefficients&& b);
58 0 : LtsCoefficients operator+(const LtsCoefficients& a, const LtsCoefficients& b);
59 :
60 0 : LtsCoefficients operator-(LtsCoefficients&& a, LtsCoefficients&& b);
61 0 : LtsCoefficients operator-(LtsCoefficients&& a, const LtsCoefficients& b);
62 0 : LtsCoefficients operator-(const LtsCoefficients& a, LtsCoefficients&& b);
63 0 : LtsCoefficients operator-(const LtsCoefficients& a, const LtsCoefficients& b);
64 :
65 : /// Add the LTS boundary terms for to \p result for the given set of
66 : /// coefficients.
67 : template <typename T>
68 1 : void apply_coefficients(gsl::not_null<T*> result,
69 : const LtsCoefficients& coefficients,
70 : const BoundaryHistoryEvaluator<T>& coupling);
71 :
72 : /// Type of coefficients used for an Adams scheme
73 0 : enum class SchemeType { Explicit, Implicit };
74 :
75 : /*!
76 : * Calculate the nonzero terms in an Adams LTS boundary contribution.
77 : *
78 : * The coefficients are generated for a step from \p start_time to \p
79 : * end_time. Interpolation from the elements is performed using
80 : * polynomials appropriate for the given \p local_scheme and \p
81 : * remote_scheme. The orders for the interpolations are taken from
82 : * the \p local_times and \p remote_times, adjusted by \p
83 : * local_order_offset and \p remote_order_offset, which can be either
84 : * 0 or -1. The small-step integration is performed with an implicit
85 : * method if either \p local_scheme or \p remote_scheme is implicit,
86 : * and the order is the larger of the integration orders on the two
87 : * sides, reduced by one if both sides have offset -1.
88 : *
89 : * This function returns the sum of the coefficients for the small
90 : * steps, i.e., the steps between all the times either side updates
91 : * between the time bounds. Each small step is calculated as
92 : *
93 : * \f{equation}
94 : * \Delta \tilde{y}_n = \Delta \tilde{t}_n \sum_{ij} D(y^L_{n,-i}, y^R_{n,-j})
95 : * \sum_q \tilde{\alpha}_{nq}
96 : * \ell_i(\tilde{t}_{n-q}; t^L_\cdots, \ldots)
97 : * \ell_j(\tilde{t}_{n-q}; t^R_\cdots, \ldots),
98 : * \f}
99 : *
100 : * where $y^L_{n,0}$ and $y^R_{n,0}$ are the values of the local and
101 : * remote variables at the start of the step containing small step
102 : * $n$, $y^L_{n,1}$ and $y^R_{n,1}$ are the predictor values for those
103 : * steps, and other index values count backwards in the history of
104 : * that side. The range of $i$ and choice of the control times
105 : * $t^L_\cdots$ are determined by \p local_scheme and the local order,
106 : * $j$ and $t^R_\cdots$ are determined by \p remote_scheme and the
107 : * remote order, and the Adams coefficients $\tilde{\alpha}_{nq}$
108 : * correspond to the larger of the two orders, and are implicit if
109 : * either set of interpolation coefficients is.
110 : *
111 : * When called for dense output, the arguments must represent a
112 : * single small step, i.e., the step cannot cross any of the control
113 : * times. Any additional terms can be generated by a second call
114 : * treating the remainder of the step as non-dense.
115 : *
116 : * \tparam TimeType The type `Time` for a step aligned with the
117 : * control times or `ApproximateTime` for dense output.
118 : */
119 : template <typename TimeType>
120 1 : LtsCoefficients lts_coefficients(
121 : const ConstBoundaryHistoryTimes& local_times,
122 : const ConstBoundaryHistoryTimes& remote_times, const Time& start_time,
123 : const TimeType& end_time, SchemeType local_scheme, SchemeType remote_scheme,
124 : int local_order_offset, int remote_order_offset);
125 : } // namespace TimeSteppers::adams_lts
|