Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1bab186

Browse files
authored
recursive evaluation of derivatives (#5)
1 parent 7d70c32 commit 1bab186

File tree

6 files changed

+336
-96
lines changed

6 files changed

+336
-96
lines changed

‎Project.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "LegendrePolynomials"
22
uuid = "3db4a2ba-fc88-11e8-3e01-49c72059a882"
3-
version = "0.3.1"
3+
version = "0.3.2"
44

55
[deps]
66
OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881"

‎docs/Project.toml‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
[deps]
22
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
3-
DualNumbers = "fa6b7ba4-c1ee-5f82-b5fc-ecf0adba8f74"
43
HyperDualNumbers = "50ceba7f-c3ee-5a84-a6e8-3ad40456ec97"
54
LegendrePolynomials = "3db4a2ba-fc88-11e8-3e01-49c72059a882"
65

76
[compat]
87
Documenter = "0.26"
9-
DualNumbers = "0.6"
108
HyperDualNumbers = "4"

‎docs/src/derivatives.md‎

Lines changed: 21 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,31 @@
11
# Derivatives of Legendre Polynomials
22

3+
## Analytical recursive approach
4+
5+
The Bonnet's recursion formula
6+
7+
```math
8+
P_\ell(x) = \left((2\ell-1) x P_{\ell-1}(x) - (\ell-1)P_{\ell - 2}(x)\right)/\ell
9+
```
10+
11+
may be differentiated an arbitrary number of times analytically to obtain recursion relations for higher derivatives:
12+
13+
```math
14+
\frac{d^n P_\ell(x)}{dx^n} = \frac{(2\ell-1)}{\ell} \left(x \frac{d^n P_{\ell-1}(x)}{dx^n} +
15+
n \frac{d^{(n-1)} P_{\ell-1}(x)}{dx^{(n-1)}} \right) - \frac{(\ell-1)}{\ell} \frac{d^n P_{\ell-2}(x)}{dx^n}
16+
```
17+
18+
This provides a simultaneous recursion relation in ``\ell`` as well as ``n``, solving which we may obtain derivatives up to any order. This is the approach used in this package to compute the derivatives of Legendre polynomials.
19+
20+
## Automatic diferentiation
21+
322
The Julia automatic differentiation framework may be used to compute the derivatives of Legendre polynomials alongside their values. Since the defintions of the polynomials are completely general, they may be called with dual or hyperdual numbers as arguments to evaluate derivarives in one go.
423
We demonstrate one example of this using the package [`HyperDualNumbers.jl`](https://github.com/JuliaDiff/HyperDualNumbers.jl) v4:
524

625
```@meta
726
DocTestSetup = quote
827
using LegendrePolynomials
28+
using HyperDualNumbers
929
end
1030
```
1131

@@ -84,51 +104,4 @@ Pl_dPl_d2Pl (generic function with 1 method)
84104
85105
julia> Pl_dPl_d2Pl(0.5, lmax = 3)
86106
([1.0, 0.5, -0.125, -0.4375], [0.0, 1.0, 1.5, 0.375], [0.0, 0.0, 3.0, 7.5])
87-
```
88-
89-
# Analytical approach for higher derivatives
90-
91-
Legendre polynomials satisfy the differential equation
92-
93-
```math
94-
\frac{d}{dx}\left[(1-x^2)\frac{d P_n}{dx} \right] + n(n+1) P_n(x) = 0
95-
```
96-
97-
We may rearrange the terms to obtain
98-
99-
```math
100-
\frac{d^2 P_n}{dx^2} = \frac{1}{(1-x^2)}\left( 2x \frac{d P_n(x)}{dx} - n(n+1)P_n{x} \right)
101-
```
102-
103-
We may therefore compute the second derivative from the function and its first derivative. Higher derivatives may further be computed in terms of the lower ones.
104-
105-
We demonstrate the second-derivative computation using the package [`DualNumbers.jl`](https://github.com/JuliaDiff/DualNumbers.jl) v0.5:
106-
107-
```jldoctest dual
108-
julia> using DualNumbers
109-
110-
julia> x = 0.5;
111-
112-
julia> xd = Dual(x, one(x));
113-
114-
julia> d2Pl(x, P, dP, n) = (2x * dP - n*(n+1) * P)/(1 - x^2);
115-
116-
julia> function d2Pl(x, n)
117-
xd = Dual(x, one(x))
118-
y = Pl(xd, n)
119-
P, dP = realpart(y), dualpart(y)
120-
d2Pl(x, P, dP, n)
121-
end;
122-
123-
julia> d2Pl(x, 20)
124-
32.838787646905985
125-
```
126-
127-
We may check that this matches the result obtained using `HyperDualNumbers`:
128-
129-
```jldoctest hyperdual
130-
julia> ε1ε2part(Pl(xh, 20))
131-
32.838787646905985
132-
```
133-
134-
Unfortunately at this point, higher derivatives need to be evaluated analytically and expresed in terms of lower derivatives.
107+
```

‎docs/src/index.md‎

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ end
77

88
# Introduction
99

10-
Compute [Legendre polynomials](https://en.wikipedia.org/wiki/Legendre_polynomials) using a 3-term recursion relation (Bonnet’s recursion formula).
10+
Compute [Legendre polynomials](https://en.wikipedia.org/wiki/Legendre_polynomials) and their derivatives using a 3-term recursion relation (Bonnet’s recursion formula).
1111

1212
```math
1313
P_\ell(x) = \left((2\ell-1) x P_{\ell-1}(x) - (\ell-1)P_{\ell - 2}(x)\right)/\ell
@@ -19,10 +19,12 @@ Currently this package evaluates the standard polynomials that satisfy ``P_\ell(
1919
\int_{-1}^1 P_m(x) P_n(x) dx = \frac{2}{2n+1} \delta_{mn}.
2020
```
2121

22-
There are two main functions:
22+
There are four main functions:
2323

2424
* [`Pl(x,l)`](@ref Pl): this evaluates the Legendre polynomial for a given degree `l` at the argument `x`. The argument needs to satisfy `-1 <= x <= 1`.
2525
* [`collectPl(x; lmax)`](@ref collectPl): this evaluates all the polynomials for `l` lying in `0:lmax` at the argument `x`. As before the argument needs to lie in the domain of validity. Functionally this is equivalent to `Pl.(x, 0:lmax)`, except `collectPl` evaluates the result in one pass, and is therefore faster. There is also the in-place version [`collectPl!`](@ref) that uses a pre-allocated array.
26+
* [`dnPl(x, l, n)`](@ref dnPl): this evaluates the ``n``-th derivative of the Legendre polynomial ``P_\ell(x)`` at the argument ``x``. The argument needs to satisfy `-1 <= x <= 1`.
27+
* [`collectdnPl(x; n, lmax)`](@ref collectdnPl): this evaluates the ``n``-th derivative of all the Legendre polynomials for `l = 0:lmax`. There is also an in-place version [`collectdnPl!`](@ref) that uses a pre-allocated array.
2628

2729
# Quick Start
2830

@@ -33,7 +35,14 @@ julia> Pl(0.5, 3)
3335
-0.4375
3436
```
3537

36-
Evaluate all the polynomials for `l` in `0:lmax` as
38+
Evaluate the `n`th derivative for one `l` as `dnPl(x, l, n)`:
39+
40+
```jldoctest
41+
julia> dnPl(0.5, 3, 2)
42+
7.5
43+
```
44+
45+
Evaluate all the polynomials for `l` in `0:lmax` as `collectPl(x; lmax)`
3746

3847
```jldoctest
3948
julia> collectPl(0.5, lmax = 3)
@@ -44,6 +53,19 @@ julia> collectPl(0.5, lmax = 3)
4453
-0.4375
4554
```
4655

56+
Evaluate all the `n`th derivatives as `collectdnPl(x; lmax, n)`:
57+
58+
```jldoctest
59+
julia> collectdnPl(0.5, lmax = 5, n = 3)
60+
6-element OffsetArray(::Array{Float64,1}, 0:5) with eltype Float64 with indices 0:5:
61+
0.0
62+
0.0
63+
0.0
64+
15.0
65+
52.5
66+
65.625
67+
```
68+
4769
# Increase precision
4870

4971
The precision of the result may be changed by using arbitrary-precision types such as `BigFloat`. For example, using `Float64` arguments we obtain
@@ -69,6 +91,16 @@ julia> setprecision(300) do
6991
0.33333333333333333333333333333333333333333333333333333333333333333333333333333333333333333317
7092
```
7193

94+
This is particularly important to avoid overflow while computing high-order derivatives. For example:
95+
96+
```jldoctest
97+
julia> dnPl(0.5, 300, 200) # Float64
98+
NaN
99+
100+
julia> dnPl(big(1)/2, 300, 200) # BigFloat
101+
1.738632750542319394663553898425873258768856732308227932150592526951212145232716e+499
102+
```
103+
72104
# Reference
73105

74106
```@autodocs

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /