LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
hierarchic_fe.cc
1
9#include "hierarchic_fe.h"
10
11namespace lf::fe {
12
27double legendre(unsigned n, double x, double t) {
28 if (n == 0) {
29 return 1;
30 }
31 if (n == 1) {
32 return 2 * x - t;
33 }
34 double Pim1 = 1;
35 double Pi = 2 * x - t;
36 for (unsigned i = 2; i <= n; ++i) {
37 const double Pip1 =
38 (2 * i - 1) * (2 * x - t) / i * Pi - (i - 1) * t * t / i * Pim1;
39 Pim1 = Pi;
40 Pi = Pip1;
41 }
42 return Pi;
43}
44
60double ilegendre(unsigned n, double x, double t) {
61 if (n == 1) {
62 return x;
63 }
64 return (legendre(n, x, t) - t * t * legendre(n - 2, x, t)) /
65 (2 * (2 * n - 1));
66}
67
77double ilegendre_dx(unsigned n, double x, double t) {
78 return legendre(n - 1, x, t);
79}
80
94double ilegendre_dt(unsigned n, double x, double t) {
95 if (n == 1) {
96 return 0;
97 }
98 return -0.5 * (legendre(n - 1, x, t) + t * legendre(n - 2, x, t));
99}
100
114double legendre_dx(unsigned n, double x, double t) {
115 if (n == 0) {
116 return 0;
117 }
118 // This has quadratic complexity and could be improved to linear
119 // but I don't think that's necessary
120 return 2 * n * legendre(n - 1, x, t) + (2 * x - t) * legendre_dx(n - 1, x, t);
121}
122
145double jacobi(unsigned n, double alpha, double beta, double x) {
146 // The recurrence relation is for the non-shifted Jacobi Polynomials
147 // We thus map [0, 1] onto [-1, 1]
148 x = 2 * x - 1;
149 if (n == 0) {
150 return 1;
151 }
152 if (n == 1) {
153 return 0.5 * (alpha - beta + x * (alpha + beta + 2));
154 }
155 double p0 = 1;
156 double p1 = 0.5 * (alpha - beta + x * (alpha + beta + 2));
157 double p2 = 0;
158 for (unsigned j = 1; j < n; ++j) {
159 const double alpha1 =
160 2 * (j + 1) * (j + alpha + beta + 1) * (2 * j + alpha + beta);
161 const double alpha2 =
162 (2 * j + alpha + beta + 1) * (alpha * alpha - beta * beta);
163 const double alpha3 = (2 * j + alpha + beta) * (2 * j + alpha + beta + 1) *
164 (2 * j + alpha + beta + 2);
165 const double alpha4 =
166 2 * (j + alpha) * (j + beta) * (2 * j + alpha + beta + 2);
167 p2 = 1. / alpha1 * ((alpha2 + alpha3 * x) * p1 - alpha4 * p0);
168 p0 = p1;
169 p1 = p2;
170 }
171 return p2;
172}
173
181double jacobi(unsigned n, double alpha, double x) {
182 return jacobi(n, alpha, 0, x);
183}
184
206double ijacobi(unsigned n, double alpha, double x) {
207 if (n == 0) {
208 return -1;
209 }
210 if (n == 1) {
211 return x;
212 }
213 // Compute the n-th, (n-1)-th and (n-2)-th Jacobi Polynomial
214 // This uses the same recurrence relation as the `eval` method
215 double ajp1P = 2 * 2 * (2 + alpha) * (2 * 2 + alpha - 2);
216 double bjp1P = 2 * 2 + alpha - 1;
217 double cjp1P = (2 * 2 + alpha) * (2 * 2 + alpha - 2);
218 double djp1P = 2 * (2 + alpha - 1) * (2 - 1) * (2 * 2 + alpha);
219 double Pjm2 = 1;
220 double Pjm1 = (2 + alpha) * x - 1;
221 double Pj =
222 (bjp1P * (cjp1P * (2 * x - 1) + alpha * alpha) * Pjm1 - djp1P * Pjm2) /
223 ajp1P;
224 for (unsigned j = 2; j < n; ++j) {
225 ajp1P = 2 * (j + 1) * ((j + 1) + alpha) * (2 * (j + 1) + alpha - 2);
226 bjp1P = 2 * (j + 1) + alpha - 1;
227 cjp1P = (2 * (j + 1) + alpha) * (2 * (j + 1) + alpha - 2);
228 djp1P = 2 * ((j + 1) + alpha - 1) * ((j + 1) - 1) * (2 * (j + 1) + alpha);
229 double Pjp1 =
230 (bjp1P * (cjp1P * (2 * x - 1) + alpha * alpha) * Pj - djp1P * Pjm1) /
231 ajp1P;
232 Pjm2 = Pjm1;
233 Pjm1 = Pj;
234 Pj = Pjp1;
235 }
236 // Compute the integral by the formula in the docstring
237 const double anL = (n + alpha) / ((2 * n + alpha - 1) * (2 * n + alpha));
238 const double bnL = alpha / ((2 * n + alpha - 2) * (2 * n + alpha));
239 const double cnL = (n - 1) / ((2 * n + alpha - 2) * (2 * n + alpha - 1));
240 return anL * Pj + bnL * Pjm1 - cnL * Pjm2;
241}
242
253double ijacobi_dx(unsigned n, double alpha, double x) {
254 return jacobi(n - 1, alpha, x);
255}
256
269double jacobi_dx(unsigned n, double alpha, double x) {
270 if (n == 0) {
271 return 0;
272 }
273 return jacobi(n - 1, alpha + 1, 1, x) * (alpha + n + 1);
274}
275
276} // end namespace lf::fe
Collects data structures and algorithms designed for scalar finite element methods primarily meant fo...
Definition: fe.h:47
double ilegendre_dt(unsigned n, double x, double t)
Computes .
double ilegendre_dx(unsigned n, double x, double t)
Computes .
double ijacobi(unsigned n, double alpha, double x)
Evaluate the integral of the (n-1)-th degree Jacobi Polynomial for .
double jacobi_dx(unsigned n, double alpha, double x)
Computes the derivative of the n-th degree Jacobi Polynomial for .
double ilegendre(unsigned n, double x, double t)
computes the integral of the (n-1)-th degree scaled Legendre Polynomial
double legendre_dx(unsigned n, double x, double t)
Computes the derivative of the n-th degree scaled Legendre polynomial.
double jacobi(unsigned n, double alpha, double beta, double x)
Computes the n-th degree shifted Jacobi polynomial.
double legendre(unsigned n, double x, double t)
computes the n-th degree scaled Legendre Polynomial
double ijacobi_dx(unsigned n, double alpha, double x)
Computes the derivative of the n-th integrated scaled Jacobi polynomial.