hummingbird
Solving the self-adjoint angular flux transport equation using spectral elements on Cartesian geometry
Loading...
Searching...
No Matches
legendre_polynomials.h
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2// Copyright (c) 2026, Liam Pohlmann
3
4/* The following was written heavily based on the teachings and codes found in
5 * the book Numerical Methods in Physics with Python, Second Edition by Alex
6 * Gezerlis. For more information on this text, please see
7 * https://numphyspy.org/. */
8
9#ifndef HUMMINGBIRD_MATH_LEGENDRE_POLYNOMIALS_H_
10#define HUMMINGBIRD_MATH_LEGENDRE_POLYNOMIALS_H_
11
12#include <vector>
13
14namespace hummingbird {
15/**
16 * @brief Computes the Legendre polynomial of degree n at a point x using the
17 * formula:
18 *
19 * \f[
20 * P_{n+1}(x)=\frac{(2n+1)xP_{n}(x)-nP_{n-1}(x)}{n+1}
21 * \f]
22 *
23 * with:
24 *
25 * \f[
26 * P_0=1,\quad P_1=x
27 * \f]
28 *
29 * The above is implemented to evaluate the n-th order Legendre polynomial by
30 * building from the bottom up, as opposed to using a recursion relation. This
31 * greatly improves the evaluation speed. This algorithm was taken from
32 * https://github.com/CambridgeUniversityPress/NumericalMethodsPhysicsWithPython/blob/master/second_edition/codes/legendre.py
33 * written by Alex Gezerlis for his book, Numerical Methods in Physics With
34 * Python, Second Edition.
35 *
36 * Legendre polynomials are defined on the interval \f$x\in
37 * [-1,1]\f$.
38 *
39 * @param n Order of polynomial to evaluate
40 * @param x Point to evaluate at
41 * @return double
42 */
43double LegendrePolynomial(const int n, const double x);
44
45/**
46 * @brief Computes the first derivative of the Legendre polynomial of degree n
47 * at a point x using the recurrence relation:
48 *
49 * \f[
50 * P'_n (x)=\frac{nP_{n-1}(x)-nxP_n(x)}{1-x^2}
51 * \f]
52 *
53 * The value of the derivative at the bounds is special:
54 *
55 * \f[
56 * P'_n(x)=\begin{cases} (-1)^{n-1}\frac{n(n+1)}{2} & x=-1
57 * \\ \frac{n(n+1)}{2} &x=1 \end{cases}
58 * \f]
59 *
60 * @param n Order of polynomial
61 * @param x Point to evaluate at
62 * @return double
63 */
64double LegendrePolynomialPrime(const int n, const double x);
65
66/**
67 * @brief Computes the second derivative of the Legendre polynomial of degree n
68 * using Legendre's differential equation:
69 *
70 * \f[
71 * (1-x^2)P_n''(x)-2xP_n'(x)+n(n+1)P_n(x)=0
72 * \f]
73 *
74 * @param n Order
75 * @param x Location to evaluate at
76 * @return double
77 */
78double LegendrePolynomialPrimePrime(const int n, const double x);
79
80/**
81 * @brief Compute all roots of the Legendre polynomial of order n
82 *
83 * @param n Order
84 * @return std::vector<double>
85 */
86std::vector<double> AllLegendreRoots(const int n);
87
88/**
89 * @brief Computes the k-th root of the n-th order Legendre polynomial by first
90 * approximating the root with ApproximateLegendreRoot, then using Newton's
91 * method to converge to the root.
92 *
93 * @param n Order of the polynomial
94 * @param k Root to find
95 * @return double
96 */
97double LegendreRoot(const int n, const int k);
98
99/**
100 * @brief Approximates the k-th root of the n-th order Legendre polynomial with:
101 *
102 * \f[
103 * x_k^{(0)}\approx \cos \left(\frac{4k+3}{4n+2}\pi\right)
104 * \f]
105 *
106 * @param n Order
107 * @param k Root number
108 * @return double
109 * @throw std::invalid_argument Root number must be less than polynomial order
110 */
111double ApproximateLegendreRoot(const int n, const int k);
112
113/**
114 * @brief Computes all roots of the \f$P'_n(x)\f$ polynomial. A total of n-1
115 * roots will be computed and returned
116 *
117 * @param n Order
118 * @return std::vector<double>
119 */
120std::vector<double> AllLegendrePrimeRoots(const int n);
121
122/**
123 * @brief Computes the k-th root of the n-th order first derivative of the
124 * Legendre polynomial by first approximating with ApproximateLegendrePrimeRoot,
125 * then using Newton's method to converge
126 *
127 * @param n Order
128 * @param k Root number
129 * @return double
130 */
131double LegendrePrimeRoot(const int n, const int k);
132
133/**
134 * @brief Approximates the k-th root of the first derivative of the n-th degree
135 * Legendre polynomial using the average of the approximations
136 * (ApproximateLegendreRoot()) of the surrounding roots of the n-th degree
137 * Legendre polynomial. Note that zero-indexing is used, so the roots of the
138 * \f$P'_4 (x)\f$ polynomial are \f$k=0,1,2\f$. The approximations of these are
139 * given by:
140 *
141 * \f[
142 * x_k\approx \frac{1}{2} \left( \cos \left(\frac{4k+3}{4n+2}\pi\right) + \cos
143 * \left(\frac{4(k+1)+3}{4n+2}\pi\right) \right) \f]
144 *
145 * @param n Order
146 * @param k Root number (zero-indexed)
147 * @return double
148 */
149double ApproximateLegendrePrimeRoot(const int n, const int k);
150
151} // namespace hummingbird
152
153#endif // HUMMINGBIRD_MATH_LEGENDRE_POLYNOMIALS_H_
std::vector< double > AllLegendrePrimeRoots(const int n)
Computes all roots of the polynomial. A total of n-1 roots will be computed and returned.
double LegendreRoot(const int n, const int k)
Computes the k-th root of the n-th order Legendre polynomial by first approximating the root with App...
double LegendrePolynomialPrime(const int n, const double x)
Computes the first derivative of the Legendre polynomial of degree n at a point x using the recurrenc...
double LegendrePrimeRoot(const int n, const int k)
Computes the k-th root of the n-th order first derivative of the Legendre polynomial by first approxi...
double LegendrePolynomialPrimePrime(const int n, const double x)
Computes the second derivative of the Legendre polynomial of degree n using Legendre's differential e...
double ApproximateLegendrePrimeRoot(const int n, const int k)
Approximates the k-th root of the first derivative of the n-th degree Legendre polynomial using the a...
double LegendrePolynomial(const int n, const double x)
Computes the Legendre polynomial of degree n at a point x using the formula:
std::vector< double > AllLegendreRoots(const int n)
Compute all roots of the Legendre polynomial of order n.
double ApproximateLegendreRoot(const int n, const int k)
Approximates the k-th root of the n-th order Legendre polynomial with: