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 AdamsScheme 73 0 : enum class SchemeType { Explicit, Implicit }; 74 : 75 0 : struct AdamsScheme { 76 0 : SchemeType type; 77 0 : size_t order; 78 : }; 79 : 80 0 : bool operator==(const AdamsScheme& a, const AdamsScheme& b); 81 0 : bool operator!=(const AdamsScheme& a, const AdamsScheme& b); 82 : 83 : /*! 84 : * Calculate the nonzero terms in an Adams LTS boundary contribution. 85 : * 86 : * The coefficients are generated for a step from \p start_time to \p 87 : * end_time, integrating using the \p small_step_scheme. 88 : * Interpolation from the elements is performed using polynomials 89 : * appropriate for the given \p local_scheme and \p remote_scheme. 90 : * 91 : * This function returns the sum of the coefficients for the small 92 : * steps, i.e., the steps between all the times either side updates 93 : * between the time bounds. Each small step is calculated as 94 : * 95 : * \f{equation} 96 : * \Delta \tilde{y}_n = \Delta \tilde{t}_n \sum_{ij} D(y^L_{n,-i}, y^R_{n,-j}) 97 : * \sum_q \tilde{\alpha}_{nq} 98 : * \ell_i(\tilde{t}_{n-q}; t^L_\cdots, \ldots) 99 : * \ell_j(\tilde{t}_{n-q}; t^R_\cdots, \ldots), 100 : * \f} 101 : * 102 : * where $y^L_{n,0}$ and $y^R_{n,0}$ are the values of the local and 103 : * remote variables at the start of the step containing small step 104 : * $n$, $y^L_{n,1}$ and $y^R_{n,1}$ are the predictor values for those 105 : * steps, and other index values count backwards in the history of 106 : * that side. The range of $i$ and choice of the control times 107 : * $t^L_\cdots$ are determined by \p local_scheme, $j$ and 108 : * $t^R_\cdots$ are determined by \p remote_scheme, and the Adams 109 : * coefficients $\tilde{\alpha}_{nq}$ correspond to \p 110 : * small_step_scheme. 111 : * 112 : * When called for dense output, the arguments must represent a 113 : * single small step, i.e., the step cannot cross any of the control 114 : * times. Any additional terms can be generated by a second call 115 : * treating the remainder of the step as non-dense. 116 : * 117 : * \tparam TimeType The type `Time` for a step aligned with the 118 : * control times or `ApproximateTime` for dense output. 119 : */ 120 : template <typename TimeType> 121 1 : LtsCoefficients lts_coefficients(const ConstBoundaryHistoryTimes& local_times, 122 : const ConstBoundaryHistoryTimes& remote_times, 123 : const Time& start_time, 124 : const TimeType& end_time, 125 : const AdamsScheme& local_scheme, 126 : const AdamsScheme& remote_scheme, 127 : const AdamsScheme& small_step_scheme); 128 : } // namespace TimeSteppers::adams_lts