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