OISEAU
A modern DGTD framework
Loading...
Searching...
No Matches
math.hpp
1// Copyright (C) 2025 Tiago V. L. Amorim (@tiagovla)
2//
3// This file is part of oiseau (https://github.com/tiagovla/oiseau)
4//
5// SPDX-License-Identifier: GPL-3.0-or-later
6
7#pragma once
8
9#include <algorithm>
10#include <cmath>
11#include <concepts>
12#include <limits>
13#include <ranges>
14#include <xtensor/containers/xarray.hpp>
15
16namespace oiseau::utils {
17
19template <class Container>
20concept FloatingArrayLike = std::ranges::contiguous_range<Container> &&
21 std::is_floating_point_v<std::ranges::range_value_t<Container>>;
22
24template <std::floating_point Real>
25Real jacobi(unsigned n, Real alpha, Real beta, Real x) {
26 if (n == 0) {
27 return Real(1);
28 }
29
30 Real y0 = 1;
31 Real y1 = (alpha + 1) + (alpha + beta + 2) * (x - 1) / Real(2);
32
33 Real yk = y1;
34 unsigned k = 2;
35 Real k_max = n * (1 + std::numeric_limits<Real>::epsilon());
36
37 while (k < k_max) {
38 Real denom = 2 * k * (k + alpha + beta) * (2 * k + alpha + beta - 2);
39 Real gamma1 =
40 (2 * k + alpha + beta - 1) *
41 ((2 * k + alpha + beta) * (2 * k + alpha + beta - 2) * x + alpha * alpha - beta * beta);
42 Real gamma0 = -2 * (k + alpha - 1) * (k + beta - 1) * (2 * k + alpha + beta);
43 yk = (gamma1 * y1 + gamma0 * y0) / denom;
44 y0 = y1;
45 y1 = yk;
46 ++k;
47 }
48 return yk;
49}
50
52template <std::floating_point Real, FloatingArrayLike Container>
53Container jacobi_p(unsigned n, Real alpha, Real beta, const Container& input) {
54 Container v = input;
55 Real norm = std::pow(2, alpha + beta + 1) / (2 * n + alpha + beta + 1);
56 norm *= std::tgamma(n + alpha + 1) * std::tgamma(n + beta + 1);
57 norm /= (std::tgamma(n + 1) * std::tgamma(n + alpha + beta + 1));
58 auto partial = [n, alpha, beta, norm](auto& k) {
59 k = jacobi(n, alpha, beta, k) / std::sqrt(norm);
60 };
61 std::for_each(v.begin(), v.end(), partial);
62 return v;
63}
64
66template <std::floating_point Real, FloatingArrayLike Container>
67Container grad_jacobi_p(int n, Real alpha, Real beta, const Container& input) {
68 Container v = input;
69 if (n == 0) {
70 std::fill(v.begin(), v.end(), Real(0));
71 return v;
72 }
73 Real norm = std::sqrt(n * (n + alpha + beta + 1));
74 Container output = jacobi_p(n - 1, alpha + 1, beta + 1, v);
75 std::for_each(output.begin(), output.end(), [norm](auto& k) { k *= norm; });
76 return output;
77}
78
79} // namespace oiseau::utils
Concept that checks for contiguous floating-point containers.
Definition math.hpp:20