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 : 8 : /// \cond 9 : class DataVector; 10 : class Matrix; 11 : namespace Spectral { 12 : enum class Quadrature : uint8_t; 13 : } // namespace Spectral 14 : /// \endcond 15 : 16 : namespace Spectral { 17 : 18 : /*! 19 : * \ingroup SpectralGroup 20 : * 21 : * \brief A collection of helper functions for Chebyshev polynomials 22 : * 23 : * \details The Chebyshev polynomials are given by: 24 : * \f[ 25 : * T_n (x) = \cos(n \theta), \text{ } \theta = \arccos(x) 26 : * \f] 27 : * 28 : * The Chebyshev expansion of a function \f$f \in [-1,1] \f$ is given by: 29 : * \f[ 30 : * f(x) = \sum_{n=0}^{\infty} f_n T_n(x) 31 : * \f] 32 : * where 33 : * \f[ 34 : * f_n = \frac{1}{c_n} \int_{-1}^1 f(x) T_n(x) w(x) dx 35 : * \f] 36 : * where the weight function is \f$w(x) = (1-x^2)^{-1/2}\f$ and the basis 37 : * function normalization value is given by: 38 : * \f{align*}{ 39 : * c_n 40 : * &=\begin{cases} 41 : * \hfil \pi \hfil & \text{if } n = 0 \\ 42 : * \hfil \frac{\pi}{2} \hfil & \text{otherwise} 43 : * \end{cases} 44 : * \f} 45 : * 46 : * If a function is discretized at \f$N+1\f$ collocation points, the modal 47 : * representation will have \f$N+1\f$ spectral coefficients consisting of 48 : * \f[ 49 : * f_n \qquad \text{for } n = 0, \ldots, N 50 : * \f] 51 : * 52 : * For more details about using Chebyshev polynomials see e.g. \cite Boyd2001 53 : * and \cite Fornberg1996. 54 : */ 55 1 : class Chebyshev { 56 : public: 57 : /*! 58 : * \brief Value of the basis function \f$\Phi_k(x) = T_k(x)\f$ 59 : */ 60 : template <typename T> 61 1 : static T basis_function_value(size_t k, const T& x); 62 : 63 : /*! 64 : * \brief The normalization square \f$c_k\f$ of the basis function 65 : * \f$\Phi_k(x)\f$, i.e. the definite integral of its square. 66 : */ 67 1 : static double basis_function_normalization_square(size_t k); 68 : 69 : /*! 70 : * \brief Collocation points \f$\{x_i\}\f$ 71 : * 72 : * \details The collocation points on the interval \f$[-1, 1]\f$ are given by 73 : * \f{align*}{ 74 : * x_i 75 : * &=\begin{cases} 76 : * \hfil - \cos \frac{(2i+1)\pi}{2N+2} \hfil & 77 : * \text{for Quadrature::Gauss} \\ 78 : * \hfil - \cos \frac{i \pi}{N} \hfil & 79 : * \text{for Quadrature::GaussLobatto} 80 : * \end{cases} 81 : * \f} 82 : */ 83 : template <Quadrature quadrature> 84 1 : static DataVector collocation_points(size_t num_points); 85 : 86 : /*! 87 : * \brief Integration weights \f$\{w_i\}\f$ 88 : * 89 : * \details The integration weights are used to approximate the weighted 90 : * integral \f$Q[f]=\int f(x)w(x)\mathrm{d}x\approx \sum_k f_k w_k\f$. 91 : * For Quadrature::Gauss, the weights are given by: 92 : * \f[ 93 : * w_i = \frac{\pi}{N+1} 94 : * \f] 95 : * 96 : * For Quadrature::GaussLobatto, the weights are given by: 97 : * \f{align*}{ 98 : * w_i 99 : * &=\begin{cases} 100 : * \hfil \frac{\pi}{2N} \hfil & \text{for } j = 0, N\\ 101 : * \hfil \frac{\pi}{N} \hfil & \text{for } j = 1, \ldots, N-1 102 : * \end{cases} 103 : * \f} 104 : * 105 : * \note These weights are used to compute the modes from the nodal 106 : * values. They are not used to evaluate definite or indefinite 107 : * integrals directly from the nodal values. 108 : */ 109 : template <Quadrature quadrature> 110 1 : static DataVector integration_weights(size_t num_points); 111 : 112 : /*! 113 : * \brief Matrix used to compute the modes of the indefinite 114 : * integral from the modes of the integrand such that the constant 115 : * of integration is determined by requiring the integral to be zero 116 : * at \f$x=-1\f$. 117 : * 118 : * \details Chebyshev polynomials satisfy the identity: 119 : * \f[ 120 : * \int^x dy T_n (y) = \left\{ \frac{T_{n+1}(x)}{2(n+1)} + 121 : * \frac{T_{n-1}(x)}{2(n-1)} \right\}, \qquad n \geq 2 122 : * \f] 123 : * 124 : * Thus the modes \f$\tilde{f}_j\f$ of the integral are given as: 125 : * \f{align*}{ 126 : * \tilde{f}_i 127 : * &=\begin{cases} 128 : * \hfil \frac{f_{i-1}-f_{i+1}}{2i}, \hfil & \text{for } i > 1\\ 129 : * \hfil f_0 - \frac{f_2}{2} \hfil & \text{for } i = 1 130 : * \end{cases} 131 : * \f} 132 : * where \f$f_j\f$ are the modes of the integrand. 133 : *\f$\tilde{f}_0\f$ is a constant of integration, which we choose such that 134 : * the integral is 0 at the left boundary of the domain (\f$x=-1\f$). The 135 : * condition for this is: 136 : * 137 : * \f[ 138 : * \tilde{f}_0=\sum_{i=1}^{N}(-1)^{i+1}\tilde{f}_i 139 : * \f] 140 : */ 141 1 : static Matrix indefinite_integral_matrix(size_t num_points); 142 : 143 : /*! 144 : * \brief Row-vector used to compute the definite integral from the modes of 145 : * the integrand 146 : * 147 : * \details Given the modes \f$\tilde{f}_j\f$ of the integral (see 148 : * indefinite_integral_matrix), the definite integral is given by evaluating 149 : * the series at \f$x=1\f$ and \f$x=-1\f$ and taking the difference. Given 150 : * that \f$T_n(1) = 1\f$ and \f$T_n(-1) = (-1)^n\f$, this means multiplying 151 : * the indefinite_integral_matrix by the row-vector \f$\{0, 2, 0, 2, \ldots 152 : * \}\f$ which yields: 153 : * \f{align*}{ 154 : * \tilde{q}_i 155 : * &=\begin{cases} 156 : * \hfil -\frac{2}{n^2-1}, \hfil & \text{for } i \text{ even}\\ 157 : * \hfil 0 \hfil & \text{for } i \text{ odd} 158 : * \end{cases} 159 : * \f} 160 : */ 161 1 : static Matrix definite_integral_matrix(size_t num_points); 162 : }; 163 : } // namespace Spectral