1
1
2
+ # Supporting functions
3
+
4
+ # See DLMF (18.9.2)
5
+ # http://dlmf.nist.gov/18.9#i
6
+ function jacobi_rec_An (α:: T , β:: T , n:: Int ) where T
7
+ if (n == 0 ) && (α + β + 1 == 0 )
8
+ one (T)/ 2 * (α+ β)+ 1
9
+ else
10
+ T (2 * n + α + β + 1 ) * (2 n + α + β + 2 ) / T (2 * (n+ 1 ) * (n + α + β + 1 ))
11
+ end
12
+ end
13
+ function jacobi_rec_Bn (α:: T , β:: T , n:: Int ) where T
14
+ if (n == 0 ) && ((α + β + 1 == 0 ) || (α+ β == 0 ))
15
+ one (T)/ 2 * (α- β)
16
+ else
17
+ T (α^ 2 - β^ 2 ) * (2 * n + α + β + 1 ) / T (2 * (n+ 1 ) * (n + α + β + 1 ) * (2 * n + α + β))
18
+ end
19
+ end
20
+ function jacobi_rec_Cn (α:: T , β:: T , n:: Int ) where T
21
+ T (n + α) * (n + β) * (2 * n + α + β + 2 ) / T ((n+ 1 ) * (n + α + β + 1 ) * (2 * n + α + β))
22
+ end
23
+
24
+ # TODO : move these elsewhere. But where?
25
+ # The packages GridArrays (which defines the nodes) and DomainIntegrals (which define the
26
+ # jacobi_x functions) do not depend on each other.
27
+ jacobi_α (x:: GridArrays.JacobiNodes ) = x. α
28
+ jacobi_β (x:: GridArrays.JacobiNodes ) = x. β
29
+ jacobi_α (w:: GridArrays.JacobiWeights ) = w. α
30
+ jacobi_β (w:: GridArrays.JacobiWeights ) = w. β
31
+
32
+
33
+ " Abstract supertype of Jacobi polynomials."
34
+ abstract type AbstractJacobi{T} <: IntervalOPS{T} end
35
+
36
+ iscompatible (b1:: AbstractJacobi , b2:: AbstractJacobi ) =
37
+ jacobi_α (b1) == jacobi_α (b2) && jacobi_β (b1) == jacobi_β (b2)
38
+ isequaldict (b1:: AbstractJacobi , b2:: AbstractJacobi ) =
39
+ length (b1)== length (b2) && iscompatible (b1,b2)
40
+
41
+ isorthogonal (b:: AbstractJacobi , μ:: DomainIntegrals.AbstractJacobiWeight ) =
42
+ jacobi_α (b) == jacobi_α (μ) && jacobi_β (b) == jacobi_β (μ)
43
+
44
+ issymmetric (dict:: AbstractJacobi ) = jacobi_α (dict)≈ jacobi_β (dict)
45
+
46
+ rec_An (b:: AbstractJacobi , n:: Int ) = jacobi_rec_An (jacobi_α (b), jacobi_β (b), n)
47
+ rec_Bn (b:: AbstractJacobi , n:: Int ) = jacobi_rec_Bn (jacobi_α (b), jacobi_β (b), n)
48
+ rec_Cn (b:: AbstractJacobi , n:: Int ) = jacobi_rec_Cn (jacobi_α (b), jacobi_β (b), n)
49
+
50
+ interpolation_grid (b:: AbstractJacobi ) = JacobiNodes (length (b), jacobi_α (b), jacobi_β (b))
51
+ iscompatiblegrid (b:: AbstractJacobi , grid:: JacobiNodes ) =
52
+ length (b) == length (grid) &&
53
+ jacobi_α (b) ≈ jacobi_α (grid) && jacobi_β (b) ≈ jacobi_β (grid)
54
+ isorthogonal (b:: AbstractJacobi , μ:: GaussJacobi ) =
55
+ jacobi_α (b) ≈ jacobi_α (μ) && jacobi_β (b) ≈ jacobi_β (μ) && opsorthogonal (b, μ)
56
+
57
+ gauss_rule (b:: AbstractJacobi ) = GaussJacobi (length (b), jacobi_α (b), jacobi_β (b))
58
+
59
+ first_moment (b:: AbstractJacobi ) = moment (measure (b))
60
+
61
+ function dict_innerproduct_native (d1:: AbstractJacobi , i:: PolynomialDegree , d2:: AbstractJacobi , j:: PolynomialDegree , measure:: AbstractJacobiWeight ; options... )
62
+ T = coefficienttype (d1)
63
+ if iscompatible (d1, d2) && isorthogonal (d1, measure)
64
+ if i == j
65
+ a = jacobi_α (d1)
66
+ b = jacobi_β (d1)
67
+ n = value (i)
68
+ 2 ^ (a+ b+ 1 )/ (2 n+ a+ b+ 1 ) * gamma (n+ a+ 1 )* gamma (n+ b+ 1 )/ factorial (n)/ gamma (n+ a+ b+ 1 )
69
+ else
70
+ zero (T)
71
+ end
72
+ else
73
+ dict_innerproduct1 (d1, i, d2, j, measure; options... )
74
+ end
75
+ end
76
+
77
+
78
+
2
79
"""
3
80
A basis of the classical Jacobi polynomials on the interval `[-1,1]`.
4
81
These polynomials are orthogonal with respect to the weight function
5
82
```
6
83
w(x) = (1-x)^α (1+x)^β.
7
84
```
8
85
"""
9
- struct Jacobi{T} <: IntervalOPS {T}
86
+ struct Jacobi{T} <: AbstractJacobi {T}
10
87
n :: Int
11
88
α :: T
12
89
β :: T
13
90
14
- Jacobi {T} (n, α = 0 , β = 0 ) where {T} = new {T} (n, α, β)
91
+ function Jacobi {T} (n, α = 0 , β = 0 ) where T
92
+ @assert α > - 1 && β > - 1
93
+ new {T} (n, α, β)
94
+ end
15
95
end
16
96
17
97
Jacobi (n:: Int ; α = 0 , β = 0 ) = Jacobi (n, α, β)
@@ -28,83 +108,33 @@ const JacobiExpansion{T,C} = Expansion{T,T,Jacobi{T},C}
28
108
29
109
similar (b:: Jacobi , :: Type{T} , n:: Int ) where {T} = Jacobi {T} (n, b. α, b. β)
30
110
31
- iscompatible (d1:: Jacobi , d2:: Jacobi ) = d1. α == d2. α && d1. β == d2. β
32
- isequaldict (b1:: Jacobi , b2:: Jacobi ) = length (b1)== length (b2) && iscompatible (b1,b2)
33
-
34
- first_moment (b:: Jacobi{T} ) where {T} = (b. α+ b. β+ 1 ≈ 0 ) ?
35
- T (2 ).^ (b. α+ b. β+ 1 )* gamma (b. α+ 1 )* gamma (b. β+ 1 ) :
36
- T (2 ).^ (b. α+ b. β+ 1 )* gamma (b. α+ 1 )* gamma (b. β+ 1 )/ (b. α+ b. β+ 1 )/ gamma (b. α+ b. β+ 1 )
37
- # 2^(b.α+b.β) / (b.α+b.β+1) * gamma(b.α+1) * gamma(b.β+1) / gamma(b.α+b.β+1)
38
-
39
111
jacobi_α (b:: Jacobi ) = b. α
40
112
jacobi_β (b:: Jacobi ) = b. β
41
113
42
114
measure (b:: Jacobi ) = JacobiWeight (b. α, b. β)
43
115
44
116
45
- isorthogonal (dict:: Jacobi , measure:: JacobiWeight ) =
46
- dict. α == measure. α && dict. β == measure. β
47
-
48
- gauss_rule (dict:: Jacobi ) = GaussJacobi (length (dict), dict. α, dict. β)
49
117
50
- interpolation_grid (dict:: Jacobi ) = JacobiNodes (length (dict), dict. α, dict. β)
51
- iscompatiblegrid (dict:: Jacobi , grid:: JacobiNodes ) = length (dict) == length (grid) && dict. α ≈ grid. α && dict. β ≈ grid. β
52
- isorthogonal (dict:: Jacobi , measure:: GaussJacobi ) = jacobi_α (dict) ≈ jacobi_α (measure) && jacobi_β (dict) ≈ jacobi_β (measure) && opsorthogonal (dict, measure)
53
-
54
- issymmetric (dict:: Jacobi ) = jacobi_α (dict)≈ jacobi_β (dict)
118
+ """
119
+ The basis of ultraspherical orthogonal polynomials on `[-1,1]`.
55
120
56
- # See DLMF (18.9.2)
57
- # http://dlmf.nist.gov/18.9#i
58
- function rec_An (b :: Jacobi{T} , n :: Int ) where {T}
59
- if (n == 0 ) && (b . α + b . β + 1 == 0 )
60
- one (T) / 2 * (b . α + b . β) + 1
61
- else
62
- T ( 2 * n + b . α + b . β + 1 ) * ( 2 * n + b . α + b . β + 2 ) / T ( 2 * (n + 1 ) * (n + b . α + b . β + 1 ))
63
- end
121
+ They are orthogonal with respect to the weight function
122
+ ```
123
+ w(x) = (1-x^2)^(λ-1/2).
124
+ ```
125
+ """
126
+ struct Ultraspherical{T} <: AbstractJacobi{T}
127
+ n :: Int
128
+ λ :: T
64
129
end
65
130
66
- function rec_Bn (b:: Jacobi{T} , n:: Int ) where {T}
67
- if (n == 0 ) && ((b. α + b. β + 1 == 0 ) || (b. α+ b. β == 0 ))
68
- one (T)/ 2 * (b. α- b. β)
69
- else
70
- T (b. α^ 2 - b. β^ 2 ) * (2 * n + b. α + b. β + 1 ) / T (2 * (n+ 1 ) * (n + b. α + b. β + 1 ) * (2 * n + b. α + b. β))
71
- end
72
- end
131
+ const Gegenbauer = Ultraspherical
73
132
74
- rec_Cn (b:: Jacobi {T}, n :: Int ) where {T} =
75
- T (n + b . α) * (n + b. β) * ( 2 * n + b . α + b . β + 2 ) / T ((n + 1 ) * (n + b . α + b . β + 1 ) * ( 2 * n + b . α + b . β))
133
+ jacobi_α (b:: Ultraspherical {T} ) where T = b . λ - one (T) / 2
134
+ jacobi_β (b :: Ultraspherical{T} ) where T = b. λ - one (T) / 2
76
135
77
- function dict_innerproduct_native (d1:: Jacobi , i:: PolynomialDegree , d2:: Jacobi , j:: PolynomialDegree , measure:: JacobiWeight ; options... )
78
- T = coefficienttype (d1)
79
- if iscompatible (d1, d2) && isorthogonal (d1, measure)
80
- if i == j
81
- a = d1. α
82
- b = d1. β
83
- n = value (i)
84
- 2 ^ (a+ b+ 1 )/ (2 n+ a+ b+ 1 ) * gamma (n+ a+ 1 )* gamma (n+ b+ 1 )/ factorial (n)/ gamma (n+ a+ b+ 1 )
85
- else
86
- zero (T)
87
- end
88
- else
89
- dict_innerproduct1 (d1, i, d2, j, measure; options... )
90
- end
91
- end
136
+ measure (b:: Ultraspherical{T} ) where T = DomainIntegrals. UltrasphericalWeight (b. λ)
92
137
93
- # function expansion_sum(src1::Jacobi, src2::Jacobi, coef1, coef2)
94
- # if iscompatible(src1, src2)
95
- # default_expansion_sum(src1, src2, coef1, coef2)
96
- # else
97
- # to_chebyshev_expansion_sum(src1, src2, coef1, coef2)
98
- # end
99
- # end
100
-
101
- # function expansion_multiply(src1::Jacobi, src2::Jacobi, coef1, coef2)
102
- # if iscompatible(src1, src2)
103
- # default_poly_expansion_multiply(src1, src2, coef1, coef2)
104
- # else
105
- # to_chebyshev_expansion_multiply(src1, src2, coef1, coef2)
106
- # end
107
- # end
108
138
109
139
# # Printing
110
140
function show (io:: IO , b:: Jacobi{Float64} )
@@ -123,14 +153,6 @@ function show(io::IO, b::Jacobi{T}) where T
123
153
end
124
154
end
125
155
126
- # TODO : move to its own file and make more complete
127
- # Or better yet: implement in terms of Jacobi polynomials
128
- struct UltrasphericalBasis{T} <: OPS{T}
129
- n :: Int
130
- alpha :: T
131
- end
132
-
133
- jacobi_α (b:: UltrasphericalBasis ) = b. α
134
- jacobi_β (b:: UltrasphericalBasis ) = b. α
135
-
136
- weightfun (b:: UltrasphericalBasis , x) = (1 - x)^ (b. α) * (1 + x)^ (b. α)
156
+ show (io:: IO , b:: Ultraspherical{Float64} ) = print (io, " Ultraspherical($(length (b)) , $(b. λ) )" )
157
+ show (io:: IO , b:: Ultraspherical{T} ) where T =
158
+ print (io, " Ultraspherical{$(T) }($(length (b)) , $(b. λ) )" )
0 commit comments