LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
Loading...
Searching...
No Matches
hierarchic_fe.cc
1
8
9#include "hierarchic_fe.h"
10
11namespace lf::fe {
12
13double Legendre(unsigned n, double x, double t) {
14 if (n == 0) {
15 return 1;
16 }
17 if (n == 1) {
18 return 2 * x - t;
19 }
20 double Pim1 = 1;
21 double Pi = 2 * x - t;
22 for (unsigned i = 2; i <= n; ++i) {
23 const double Pip1 =
24 (2 * i - 1) * (2 * x - t) / i * Pi - (i - 1) * t * t / i * Pim1;
25 Pim1 = Pi;
26 Pi = Pip1;
27 }
28 return Pi;
29}
30
31double ILegendre(unsigned n, double x, double t) {
32 if (n == 1) {
33 return x;
34 }
35 return (Legendre(n, x, t) - t * t * Legendre(n - 2, x, t)) /
36 (2 * (2 * n - 1));
37}
38
39double ILegendreDx(unsigned n, double x, double t) {
40 return Legendre(n - 1, x, t);
41}
42
43double ILegendreDt(unsigned n, double x, double t) {
44 if (n == 1) {
45 return 0;
46 }
47 return -0.5 * (Legendre(n - 1, x, t) + t * Legendre(n - 2, x, t));
48}
49
50// NOLINTNEXTLINE(misc-no-recursion)
51double LegendreDx(unsigned n, double x, double t) {
52 if (n == 0) {
53 return 0;
54 }
55 // This has quadratic complexity and could be improved to linear
56 // but I don't think that's necessary
57 return 2 * n * Legendre(n - 1, x, t) + (2 * x - t) * LegendreDx(n - 1, x, t);
58}
59
60double Jacobi(unsigned n, double alpha, double beta, double x) {
61 // The recurrence relation is for the non-shifted Jacobi Polynomials
62 // We thus map [0, 1] onto [-1, 1]
63 x = 2 * x - 1;
64 if (n == 0) {
65 return 1;
66 }
67 if (n == 1) {
68 return 0.5 * (alpha - beta + x * (alpha + beta + 2));
69 }
70 double p0 = 1;
71 double p1 = 0.5 * (alpha - beta + x * (alpha + beta + 2));
72 double p2 = 0;
73 for (unsigned j = 1; j < n; ++j) {
74 const double alpha1 =
75 2 * (j + 1) * (j + alpha + beta + 1) * (2 * j + alpha + beta);
76 const double alpha2 =
77 (2 * j + alpha + beta + 1) * (alpha * alpha - beta * beta);
78 const double alpha3 = (2 * j + alpha + beta) * (2 * j + alpha + beta + 1) *
79 (2 * j + alpha + beta + 2);
80 const double alpha4 =
81 2 * (j + alpha) * (j + beta) * (2 * j + alpha + beta + 2);
82 p2 = 1. / alpha1 * ((alpha2 + alpha3 * x) * p1 - alpha4 * p0);
83 p0 = p1;
84 p1 = p2;
85 }
86 return p2;
87}
88
89double Jacobi(unsigned n, double alpha, double x) {
90 return Jacobi(n, alpha, 0, x);
91}
92
93double IJacobi(unsigned n, double alpha, double x) {
94 if (n == 0) {
95 return -1;
96 }
97 if (n == 1) {
98 return x;
99 }
100 // Compute the n-th, (n-1)-th and (n-2)-th Jacobi Polynomial
101 // This uses the same recurrence relation as the `eval` method
102 double ajp1P = 2 * 2 * (2 + alpha) * (2 * 2 + alpha - 2);
103 double bjp1P = 2 * 2 + alpha - 1;
104 double cjp1P = (2 * 2 + alpha) * (2 * 2 + alpha - 2);
105 double djp1P = 2 * (2 + alpha - 1) * (2 - 1) * (2 * 2 + alpha);
106 double Pjm2 = 1;
107 double Pjm1 = (2 + alpha) * x - 1;
108 double Pj =
109 (bjp1P * (cjp1P * (2 * x - 1) + alpha * alpha) * Pjm1 - djp1P * Pjm2) /
110 ajp1P;
111 for (unsigned j = 2; j < n; ++j) {
112 ajp1P = 2 * (j + 1) * ((j + 1) + alpha) * (2 * (j + 1) + alpha - 2);
113 bjp1P = 2 * (j + 1) + alpha - 1;
114 cjp1P = (2 * (j + 1) + alpha) * (2 * (j + 1) + alpha - 2);
115 djp1P = 2 * ((j + 1) + alpha - 1) * ((j + 1) - 1) * (2 * (j + 1) + alpha);
116 const double Pjp1 =
117 (bjp1P * (cjp1P * (2 * x - 1) + alpha * alpha) * Pj - djp1P * Pjm1) /
118 ajp1P;
119 Pjm2 = Pjm1;
120 Pjm1 = Pj;
121 Pj = Pjp1;
122 }
123 // Compute the integral by the formula in the docstring
124 const double anL = (n + alpha) / ((2 * n + alpha - 1) * (2 * n + alpha));
125 const double bnL = alpha / ((2 * n + alpha - 2) * (2 * n + alpha));
126 const double cnL = (n - 1) / ((2 * n + alpha - 2) * (2 * n + alpha - 1));
127 return anL * Pj + bnL * Pjm1 - cnL * Pjm2;
128}
129
130double IJacobiDx(unsigned n, double alpha, double x) {
131 return Jacobi(n - 1, alpha, x);
132}
133
134double JacobiDx(unsigned n, double alpha, double x) {
135 if (n == 0) {
136 return 0;
137 }
138 return Jacobi(n - 1, alpha + 1, 1, x) * (alpha + n + 1);
139}
140
141} // end namespace lf::fe
Collects data structures and algorithms designed for scalar finite element methods primarily meant fo...
Definition fe.h:47
double Legendre(unsigned n, double x, double t)
computes the n-th degree scaled Legendre Polynomial
double ILegendreDx(unsigned n, double x, double t)
Computes .
double IJacobiDx(unsigned n, double alpha, double x)
Computes the derivative of the n-th integrated scaled Jacobi polynomial.
double ILegendre(unsigned n, double x, double t)
computes the integral of the (n-1)-th degree scaled Legendre Polynomial
double Jacobi(unsigned n, double alpha, double beta, double x)
Computes the n-th degree shifted Jacobi polynomial.
double IJacobi(unsigned n, double alpha, double x)
Evaluate the integral of the (n-1)-th degree Jacobi Polynomial for .
double JacobiDx(unsigned n, double alpha, double x)
Computes the derivative of the n-th degree Jacobi Polynomial for .
double ILegendreDt(unsigned n, double x, double t)
Computes .
double LegendreDx(unsigned n, double x, double t)
Computes the derivative of the n-th degree scaled Legendre polynomial.