Skip to content

Commit 20238d8

Browse files
authored
Large error in two-band transform (#47)
* Large error in two-band transform * Fix error in transform for associated OPs * Update Project.toml * Update equilibriummeasure.jl * Update test_derivative.jl * v0.2.2
1 parent 48e0faf commit 20238d8

File tree

6 files changed

+103
-41
lines changed

6 files changed

+103
-41
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "SemiclassicalOrthogonalPolynomials"
22
uuid = "291c01f3-23f6-4eb6-aeb0-063a639b53f2"
33
authors = ["Sheehan Olver <[email protected]>"]
4-
version = "0.2.1"
4+
version = "0.2.2"
55

66
[deps]
77
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"

examples/equilibriummeasure.jl

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ function equilibriumcoefficients(T, b)
4040
W = Weighted(T)
4141
t = axes(W,1)
4242
H = @. inv(t - t')
43-
= U \ (H*W)
43+
= U \H*W
4444
[1/(b*sum(W[:,1])); 2H̃[:,2:end] \ ( U \ derivative.(V, b*t))]
4545
end
4646
function equilibriumendpointvalue(b::Number)
@@ -55,10 +55,24 @@ function equilibrium(b::Number)
5555
Weighted(U)[affine(-b..b,axes(T,1)),:] * ((Weighted(T) \ Weighted(U))[3:end,:] \ equilibriumcoefficients(T,b)[3:end])
5656
end
5757

58+
μ = equilibrium(sqrt(2))
59+
60+
T = Chebyshev()
61+
b = sqrt(2)
62+
μ = Weighted(T) * equilibriumcoefficients(T, b)
63+
x = axes(μ,1)
64+
65+
plot(μ)
66+
67+
xx = 0.7; 2b*(log.(abs.(x .- x'))*μ)[xx] - V(b*xx)
68+
69+
70+
5871
b = 1.0 # initial guess
5972
for _ = 1:10
6073
b -= derivative(equilibriumendpointvalue,b) \ equilibriumendpointvalue(b)
6174
end
75+
b
6276

6377
plot(equilibrium(b))
6478

@@ -92,12 +106,15 @@ function equilibriumcoefficients(P,a,b)
92106
W = Weighted(P)
93107
Q = associated(P)
94108
t = axes(W,1)
95-
H = @. inv(t - t')
96-
= Q \ (H*W)
97-
[1/(b*sum(W[:,1])); 2H̃[:,2:end] \( Q \ derivative.(V, b*t))]
109+
x = axes(Q,1)
110+
H = @. inv(x - t')
111+
= Q \ H*W
112+
[1/(b*sum(W[:,1])); 2H̃[:,2:end] \( Q \ derivative.(V, b*x))]
98113
end
99114
function equilibriumendpointvalues(ab::SVector{2})
100115
a,b = ab
116+
# orthogonal polynomials w.r.t.
117+
# abs(x) / (sqrt(1-x^2) * sqrt(x^2 - ρ^2))
101118
P = TwoBandJacobi(a/b, -one(a)/2, -one(a)/2, one(a)/2)
102119
Vector(P[[a/b,1],:] * equilibriumcoefficients(P,a,b))
103120
end
@@ -110,7 +127,11 @@ end
110127

111128
ab = SVector(2.,3.)
112129
ab -= jacobian(equilibriumendpointvalues,ab) \ equilibriumendpointvalues(ab)
113-
130+
a,b = ab
131+
xx = range(-4,4;length=1000)
132+
μ = equilibrium(ab)
133+
μx = x -> a < abs(x) < b ? μ[x/b] : 0.0
134+
plot!(xx, μx.(xx))
114135

115136
plot(equilibrium(ab))
116137

src/SemiclassicalOrthogonalPolynomials.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import LazyArrays: resizedata!, paddeddata, CachedVector, CachedMatrix, CachedAb
1111
import ClassicalOrthogonalPolynomials: OrthogonalPolynomial, recurrencecoefficients, jacobimatrix, normalize, _p0, UnitInterval, orthogonalityweight, NormalizedBasisLayout,
1212
Bidiagonal, Tridiagonal, SymTridiagonal, symtridiagonalize, normalizationconstant, LanczosPolynomial,
1313
OrthogonalPolynomialRatio, Weighted, Expansion, UnionDomain, oneto, Hilbert, WeightedOrthogonalPolynomial, HalfWeighted,
14-
Associated
14+
Associated, golubwelsch, associated
1515
import InfiniteArrays: OneToInf, InfUnitRange
1616
import ContinuumArrays: basis, Weight, @simplify, AbstractBasisLayout, BasisLayout, MappedBasisLayout, grid, plotgrid
1717
import FillArrays: SquareEye

src/twoband.jl

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
twoband) = UnionDomain(-1..(-ρ), ρ..1)
2-
1+
twoband::T) where T = UnionDomain(-one(T)..(-ρ), ρ..one(T))
2+
twoband_0::T) where T = UnionDomain(-one(T)..(-ρ), zero(T), ρ..one(T))
33

44
"""
55
TwoBandWeight(ρ, a, b, c)
@@ -32,9 +32,9 @@ function sum(w::TwoBandWeight{T}) where T
3232
else
3333
error("not implemented")
3434
# 1/2 \[Pi] (-((\[Rho]^(1 + 2 b + 2 c)
35-
# Gamma[1 + b] Hypergeometric2F1Regularized[-a, 1/2 + c,
35+
# Gamma[1 + b] Hypergeometric2F1Regularized[-a, 1/2 + c,
3636
# 3/2 + b + c, \[Rho]^2])/Gamma[1/2 - c]) + (
37-
# Gamma[1 + a] Hypergeometric2F1Regularized[-b, -(1/2) - a - b - c,
37+
# Gamma[1 + a] Hypergeometric2F1Regularized[-b, -(1/2) - a - b - c,
3838
# 1/2 - b - c, \[Rho]^2])/
3939
# Gamma[3/2 + a + b + c]) Sec[(b + c) \[Pi]]
4040
end
@@ -69,14 +69,14 @@ copy(A::TwoBandJacobi) = A
6969

7070
orthogonalityweight(Z::TwoBandJacobi) = TwoBandWeight(Z.ρ, Z.a, Z.b, Z.c)
7171

72-
function getindex(R::TwoBandJacobi, x::Real, j::Integer)
73-
ρ = R.ρ
74-
if isodd(j)
75-
R.P[(1-x^2)/(1-ρ^2), (j+1)÷2]
76-
else
77-
x * R.Q[(1-x^2)/(1-ρ^2), j÷2]
78-
end
79-
end
72+
# function getindex(R::TwoBandJacobi, x::Real, j::Integer)
73+
# ρ = R.ρ
74+
# if isodd(j)
75+
# R.P[(1-x^2)/(1-ρ^2), (j+1)÷2]
76+
# else
77+
# x * R.Q[(1-x^2)/(1-ρ^2), j÷2]
78+
# end
79+
# end
8080

8181

8282
struct Interlace{T,AA,BB} <: LazyVector{T}
@@ -94,28 +94,49 @@ getindex(A::Interlace{T}, k::Int) where T = convert(T, isodd(k) ? A.a[(k+1)÷2]
9494
function jacobimatrix(R::TwoBandJacobi{T}) where T
9595
ρ = R.ρ
9696
L = R.P \ (SemiclassicalJacobiWeight(R.P.t,0,0,1) .* R.Q)
97-
Tridiagonal(Interlace(L.dv/L[1,1], (1-ρ^2) * L.ev), Zeros{T}(∞), Interlace((1-ρ^2) * L.dv,L.ev/L[1,1]))
97+
Tridiagonal(Interlace(L.dv/L[1,1], (ρ^2-1) * L.ev), Zeros{T}(∞), Interlace((1-ρ^2) * L.dv,L.ev/(-L[1,1])))
9898
end
9999

100100

101-
@simplify function *(H::Hilbert, w::TwoBandWeight)
102-
if 2w.a == 2w.b == -1 && 2w.c == 1
103-
zeros(promote_type(eltype(H),eltype(w)), axes(w,1))
101+
const ConvKernel2{T,D1,D2} = BroadcastQuasiMatrix{T,typeof(-),Tuple{D1,QuasiAdjoint{T,D2}}}
102+
const Hilbert2{T,D1,D2} = BroadcastQuasiMatrix{T,typeof(inv),Tuple{ConvKernel2{T,Inclusion{T,D1},Inclusion{T,D2}}}}
103+
104+
@simplify function *(H::Hilbert2, w::TwoBandWeight)
105+
if 2w.a == 2w.b == -1 && 2w.c == 1 && axes(H,2) == axes(w,1) && axes(H,1).domain twoband_0(w.ρ)
106+
zeros(promote_type(eltype(H),eltype(w)), axes(H,1))
104107
else
105108
error("Not Implemented")
106109
end
107110
end
108111

109-
110-
function grid(L::SubQuasiArray{T,2,<:Associated{<:Any,<:TwoBandJacobi},<:Tuple{Inclusion,OneTo}}) where T
111-
g = grid(legendre(parent(L).P.ρ .. 1)[:,parentindices(L)[2]])
112-
[-g; g]
113-
end
114-
115112
function plotgrid(L::SubQuasiArray{T,2,<:TwoBandJacobi,<:Tuple{Inclusion,AbstractUnitRange}}) where T
116113
g = plotgrid(legendre(parent(L).ρ .. 1)[:,parentindices(L)[2]])
117114
[-g; g]
118115
end
119116

120-
LinearAlgebra.factorize(L::SubQuasiArray{<:Any,2,<:Associated{<:Any,<:TwoBandJacobi},<:Tuple{Inclusion,OneTo}}) =
121-
ContinuumArrays._factorize(BasisLayout(), L)
117+
###
118+
# Associated
119+
###
120+
121+
axes(Q::Associated{T,<:TwoBandJacobi}) where T = (Inclusion(twoband_0(Q.P.ρ)), axes(Q.P,2))
122+
function golubwelsch(V::SubQuasiArray{T,2,<:Normalized{<:Any,<:Associated{<:Any,<:TwoBandJacobi}},<:Tuple{Inclusion,AbstractUnitRange}}) where T
123+
x,w = golubwelsch(jacobimatrix(V))
124+
n = length(x)
125+
if isodd(n)
126+
x[(n+1)÷2] = zero(T) # make exactly zero
127+
else
128+
x[n÷2] = zero(T) # make exactly zero
129+
x[(n÷2)+1] = zero(T) # make exactly zero
130+
end
131+
w .*= sum(orthogonalityweight(parent(V)))
132+
x,w
133+
end
134+
135+
@simplify function *(H::Hilbert2, wP::Weighted{<:Any,<:TwoBandJacobi})
136+
P = wP.P
137+
w = orthogonalityweight(P)
138+
A = recurrencecoefficients(P)[1]
139+
Q = associated(P)
140+
@assert axes(H,1) == axes(Q,1)
141+
Q * BandedMatrix(1 =>Fill(-A[1]*sum(w),∞))
142+
end

test/test_derivative.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import SemiclassicalOrthogonalPolynomials: MulAddAccumulate, HalfWeighted
3535
L = Q \ (D * P̃);
3636
# L is bidiagonal
3737
@test norm(triu(L[1:10,1:10],3))  3E-12
38-
@test L[:,5] isa Vcat
38+
@test L[:,5][1:10] L[1:10,5]
3939

4040
A,B,C = recurrencecoefficients(P);
4141
α,β,γ = recurrencecoefficients(Q);

test/test_twoband.jl

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using SemiclassicalOrthogonalPolynomials, ClassicalOrthogonalPolynomials, Test
1+
using SemiclassicalOrthogonalPolynomials, ClassicalOrthogonalPolynomials, BandedMatrices, Test
22
import ClassicalOrthogonalPolynomials: orthogonalityweight, Weighted, associated, plotgrid
33

44
@testset "Two Band" begin
@@ -27,21 +27,33 @@ import ClassicalOrthogonalPolynomials: orthogonalityweight, Weighted, associated
2727
@test !issymmetric(jacobimatrix(T)[1:10,1:10])
2828
end
2929

30+
@testset "Associated" begin
31+
ρ = 0.5
32+
T = TwoBandJacobi(ρ, -1/2, -1/2, 1/2)
33+
Q = associated(T)
34+
x = axes(Q,1)
35+
@test 0 in x
36+
@test (Q[0.6,1:101]' * (Q[:,Base.OneTo(101)] \ exp.(x))) exp(0.6)
37+
@test (Q[-0.6,1:101]' * (Q[:,Base.OneTo(101)] \ exp.(x))) exp(-0.6)
38+
39+
@test (Q * (Q \ exp.(x)))[0.6] exp(0.6)
40+
end
41+
3042
@testset "Hilbert" begin
3143
ρ = 0.5
3244
w = TwoBandWeight(ρ, -1/2, -1/2, 1/2)
33-
x = axes(w,1)
34-
H = inv.(x .- x')
45+
T = TwoBandJacobi(ρ, -1/2, -1/2, 1/2)
46+
Q = associated(T)
47+
t = axes(w,1)
48+
x = axes(Q,1)
49+
H = inv.(x .- t')
3550
@test iszero(H*w)
3651
@test sum(w) π
3752

38-
T = TwoBandJacobi(ρ, -1/2, -1/2, 1/2)
39-
Q = associated(T)
40-
@test (Q[0.6,1:100]' * (Q[:,Base.OneTo(100)] \ exp.(x))) exp(0.6)
41-
@test (Q[-0.6,1:100]' * (Q[:,Base.OneTo(100)] \ exp.(x))) exp(-0.6)
53+
B = Q \ H * Weighted(T)
54+
@test B isa BandedMatrix
4255

43-
@test (Q * (Q \ exp.(x)))[0.6] exp(0.6)
44-
@test_broken Q \ (H * Weighted(T)) # need to deal with Hcat
56+
@test Q[0.6,:]'* (B * (T\exp.(t))) -4.701116657130821 # Mathematica
4557

4658
@test_broken H*TwoBandWeight(ρ, 1/2, 1/2, -1/2)
4759
end
@@ -51,4 +63,12 @@ import ClassicalOrthogonalPolynomials: orthogonalityweight, Weighted, associated
5163
P = TwoBandJacobi(ρ, -1/2, -1/2, 1/2)
5264
@test all(x -> ρ abs(x)  1, plotgrid(P[:,1:5]))
5365
end
66+
67+
@testset "associated transform error" begin
68+
a,b = 0.5, 0.9
69+
Vp = x -> 4x^3 - 20x
70+
Q = associated(TwoBandJacobi((a/b), -1/2, -1/2, 1/2))
71+
x = axes(Q,1)
72+
@test norm((Q[:,Base.OneTo(30)] \ Vp.(b*x))[1])  1E-13
73+
end
5474
end

0 commit comments

Comments
 (0)