22 const auto n = xs.size();
23 weights.assign(n, 0.);
25 const auto lower = std::lower_bound(xs.begin(), xs.end(), x);
27 if (lower == xs.begin()) {
32 if (lower == xs.end()) {
37 const auto index =
static_cast<unsigned>(std::distance(xs.begin(), lower));
38 const auto lower_loc = xs[index - 1];
39 const auto upper_loc = xs[index];
40 const auto weight_upper = (x - lower_loc) / (upper_loc - lower_loc);
41 weights[index - 1] = 1. - weight_upper;
42 weights[index] = weight_upper;
53inline double LinearInterp(
double x, std::span<const double> xs, std::span<const double> values) {
54 std::vector<double> weights(xs.size());
56 return std::transform_reduce(
57 std::begin(weights), std::end(weights), std::begin(values), 0., std::plus<>(),
70 double x, std::span<const double> xs, std::vector<double>& weights
72 const auto n = xs.size();
73 weights.assign(n, 1.);
76 std::vector<double> x_minus_xm(n);
77 for (
auto m : std::views::iota(0U, n)) {
78 x_minus_xm[m] = x - xs[m];
81 for (
auto j : std::views::iota(0U, n)) {
82 for (
auto m : std::views::iota(0U, n)) {
84 weights[j] *= x_minus_xm[m] / (xs[j] - xs[m]);
98 double x, std::span<const double> xs, std::vector<double>& weights
100 const auto n = xs.size();
101 weights.assign(n, 0.);
103 for (
auto i : std::views::iota(0U, n)) {
106 for (
auto j : std::views::iota(0U, n) | std::views::filter([i](
unsigned j) {
109 auto range = std::views::iota(0U, n) | std::views::filter([i, j](
unsigned k) {
110 return k != i && k != j;
113 auto prod = std::transform_reduce(
114 std::begin(range), std::end(range), 1., std::multiplies<>(),
115 [&xs, x, xi](
auto k) {
116 return (x - xs[k]) / (xi - xs[k]);
119 weight += prod / (xi - xs[j]);
146 double p_n_minus_2{1.};
147 double p_n_minus_1{x};
149 for (
auto i : std::views::iota(2U, n + 1)) {
150 const auto i_double =
static_cast<double>(i);
151 p_n = ((2. * i_double - 1.) * x * p_n_minus_1 - (i_double - 1.) * p_n_minus_2) / i_double;
152 p_n_minus_2 = p_n_minus_1;
170 constexpr auto max_iterations = 1000U;
171 constexpr auto convergence_tolerance = std::numeric_limits<double>::epsilon();
174 throw std::invalid_argument(
"Polynomial order must be >= 1");
177 const size_t n_nodes = order + 1;
178 auto gll_points = std::vector<double>(n_nodes, 0.);
179 gll_points.resize(n_nodes);
182 gll_points.front() = -1.;
183 gll_points.back() = 1.;
186 std::vector<double> legendre_poly(n_nodes, 0.);
187 for (
auto i : std::views::iota(1U, order)) {
190 -std::cos(
static_cast<double>(i) * std::numbers::pi /
static_cast<double>(order));
192 bool converged{
false};
193 for ([[maybe_unused]]
auto iteration : std::views::iota(0U, max_iterations)) {
194 const auto x_old = x_it;
197 for (
auto k : std::views::iota(0U, n_nodes)) {
202 const auto numerator = x_it * legendre_poly[n_nodes - 1] - legendre_poly[n_nodes - 2];
203 const auto denominator =
static_cast<double>(n_nodes) * legendre_poly[n_nodes - 1];
204 x_it -= numerator / denominator;
207 if (std::abs(x_it - x_old) <= convergence_tolerance) {
214 throw std::runtime_error(
215 "Newton-Raphson iteration failed to converge for GLL point index " +
220 gll_points[i] = x_it;
Definition gll_quadrature.hpp:7
std::vector< double > GenerateGLLPoints(const size_t order)
Generates Gauss-Lobatto-Legendre (GLL) points for spectral element discretization.
Definition interpolation.hpp:169
void LagrangePolynomialInterpWeights(double x, std::span< const double > xs, std::vector< double > &weights)
Computes weights for Lagrange polynomial interpolation.
Definition interpolation.hpp:69
double LegendrePolynomial(const size_t n, const double x)
Calculates the value of Legendre polynomial of order n at point x.
Definition interpolation.hpp:136
void LinearInterpWeights(double x, std::span< const double > xs, std::vector< double > &weights)
Computes weights for linear interpolation.
Definition interpolation.hpp:21
void LagrangePolynomialDerivWeights(double x, std::span< const double > xs, std::vector< double > &weights)
Computes weights for Lagrange polynomial derivative interpolation.
Definition interpolation.hpp:97
double LinearInterp(double x, std::span< const double > xs, std::span< const double > values)
Computes linear interpolation.
Definition interpolation.hpp:53