From d280bda6ffafeabd5d6d7620bfd7a90c2420b959 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Sun, 2 Mar 2025 17:13:42 -0600 Subject: [PATCH 1/3] Add tests for the Jacobi ladder operators --- src/ClassicalOrthogonalPolynomials.jl | 4 ++++ test/test_jacobi.jl | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/ClassicalOrthogonalPolynomials.jl b/src/ClassicalOrthogonalPolynomials.jl index c2c5d59..97187a9 100644 --- a/src/ClassicalOrthogonalPolynomials.jl +++ b/src/ClassicalOrthogonalPolynomials.jl @@ -255,6 +255,10 @@ function layout_broadcasted(::Tuple{PolynomialLayout,AbstractOPLayout}, ::typeof C*jacobimatrix(C) end +function layout_broadcasted(::Tuple{ScalarLayout,AbstractOPLayout}, ::typeof(*), c, C) + C * c +end + # function broadcasted(::LazyQuasiArrayStyle{2}, ::typeof(*), a::BroadcastQuasiVector, C::OrthogonalPolynomial) # axes(a,1) == axes(C,1) || throw(DimensionMismatch()) diff --git a/test/test_jacobi.jl b/test/test_jacobi.jl index b2b85e3..c334962 100644 --- a/test/test_jacobi.jl +++ b/test/test_jacobi.jl @@ -552,4 +552,30 @@ import ClassicalOrthogonalPolynomials: recurrencecoefficients, basis, MulQuasiMa @test expand(W, x -> (1-x^2)*exp(x))[0.1] ≈ (1-0.1^2)*exp(0.1) @test grid(W, 5) == grid(W.P, 5) end + + @testset "ladder operators" begin + a,b = 0.1,0.2 + P = Jacobi(a,b) + A₊,A₋ = Jacobi(a+1,b),Jacobi(a-1,b) + B₊,B₋ = Jacobi(a,b+1),Jacobi(a,b-1) + C₊,C₋ = Jacobi(a+1,b+1),Jacobi(a-1,b-1) + D₊,D₋ = Jacobi(a+1,b-1), Jacobi(a-1,b+1) + t,n = 0.3,5 + x = axes(P,1) + D = Derivative(P) + + @test (D*P)[t,n+1] ≈ (n+a+b+1)/2 * C₊[t,n] # L₁ + @test (((a+b+n+1)*I + (1 .+ x) .* D)*P)[t,n+1] ≈ (JacobiWeight(0,-(a+b+n)) .* D * (JacobiWeight(0,a+b+n+1) .* P))[t,n+1] ≈ (n+a+b+1) * A₊[t,n+1] # L₂ + @test (((a+b+n+1)*I - (1 .- x) .* D)*P)[t,n+1] ≈ -(JacobiWeight(-(a+b+n),0) .* D * (JacobiWeight(a+b+n+1,0) .* P))[t,n+1] ≈ (n+a+b+1) * B₊[t,n+1] # L₃ + @test ((1 .+ t)*a - (1 .- t)*(b+n+1))*P[t,n+1] - (((1 .- x.^2) .* D)*P)[t,n+1] ≈ -(JacobiWeight(1-a,-(b+n)) .* D * (JacobiWeight(a,b+n+1) .* P))[t,n+1] ≈ 2*(n+1) * A₋[t,n+2] # L₄ + @test ((1 .+ t)*(a+n+1) - (1 .- t)*b)*P[t,n+1] - (((1 .- x.^2) .* D)*P)[t,n+1] ≈ -(JacobiWeight(-(a+n),1-b) .* D * (JacobiWeight(a+n+1,b) .* P))[t,n+1] ≈ 2*(n+1) * B₋[t,n+2] # L₅ + @test ((b*I + (1 .+ x) .* D)*P)[t,n+1] ≈ (JacobiWeight(0,1-b) .* D * (JacobiWeight(0,b) .* P))[t,n+1] ≈ (n+b) * D₊[t,n+1] # L₆ + + @test ((1 .+ t)*a - (1 .- t)*b)*P[t,n+1] - (((1 .- x.^2) .* D)*P)[t,n+1] ≈ -(JacobiWeight(1-a,1-b) .* D * (JacobiWeight(a,b) .* P))[t,n+1] ≈ 2*(n+1) * C₋[t,n+2] # L₁' + @test (2a + (1 .- t)*n)*P[t,n+1] - (((1 .- x.^2) .* D)*P)[t,n+1] ≈ -(JacobiWeight(1-a,1+a+n) .* D * (JacobiWeight(a,-a-n) .* P))[t,n+1] ≈ 2*(n+a) * A₋[t,n+1] # L₂' + @test (2b + (1 .+ t)*n)*P[t,n+1] + (((1 .- x.^2) .* D)*P)[t,n+1] ≈ (JacobiWeight(1+b+n,1-b) .* D * (JacobiWeight(-b-n,b) .* P))[t,n+1] ≈ 2*(n+b) * B₋[t,n+1] # L₃' + @test ((-n*I + (1 .+ x) .* D)*P)[t,n+1] ≈ (JacobiWeight(0,n+1) .* D * (JacobiWeight(0,-n) .* P))[t,n+1] ≈ (n+b) * A₊[t,n] # L₄' + @test ((n*I + (1 .- x) .* D)*P)[t,n+1] ≈ (JacobiWeight(n+1,0) .* D * (JacobiWeight(-n,0) .* P))[t,n+1] ≈ (n+a) * B₊[t,n] # L₅' + @test ((a*I - (1 .- x) .* D)*P)[t,n+1] ≈ -(JacobiWeight(1-a,0) .* D * (JacobiWeight(a,0) .* P))[t,n+1] ≈ (n+a) * D₋[t,n+1] # L₆' + end end \ No newline at end of file From 6eea74c7f2bb3462a00e708ae031aeed7f435fe8 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Mon, 3 Mar 2025 13:26:23 -0600 Subject: [PATCH 2/3] Update test_ultraspherical.jl --- test/test_ultraspherical.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/test_ultraspherical.jl b/test/test_ultraspherical.jl index b58a7be..d65675d 100644 --- a/test/test_ultraspherical.jl +++ b/test/test_ultraspherical.jl @@ -204,4 +204,16 @@ using ClassicalOrthogonalPolynomials: grammatrix @test (C \ diff(U,1))[1:10,1:10] == (C \ diff(U))[1:10,1:10] @test (C³ \ diff(U,2))[1:10,1:10] == (C³ \ diff(diff(U)))[1:10,1:10] end + + @testset "ladder" begin + λ = 3/4 + P = Jacobi(λ-1/2,λ-1/2) + W = Jacobi(λ-1-1/2,λ-1-1/2) + Q = Jacobi(λ+1-1/2,λ+1-1/2) + D = Derivative(P) + t,n = 0.3,5 + @test (D*P)[t,n+1] ≈ (n+2λ)/2 * Q[t,n] # L₁ + # L₃L₂ + -(JacobiWeight(-(a+b+n),0) .* (D * (JacobiWeight(a+b+n+1,-(a+b+n)) .* D * (JacobiWeight(0,a+b+n+1) .* P))))[t,n+1] + end end \ No newline at end of file From 549acaffe9ea4331199a7b0df6a32cb2622ef5a5 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Wed, 5 Mar 2025 13:53:13 -0600 Subject: [PATCH 3/3] support (w .* (w .* P)) --- src/classical/jacobi.jl | 4 ++++ test/test_ultraspherical.jl | 23 +++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/classical/jacobi.jl b/src/classical/jacobi.jl index 7067312..8303e22 100644 --- a/src/classical/jacobi.jl +++ b/src/classical/jacobi.jl @@ -485,6 +485,10 @@ broadcastbasis(::typeof(+), w_A::WeightedJacobi, w_B::Weighted{<:Any,<:Jacobi}) broadcastbasis(::typeof(+), A::Jacobi, B::Weighted{<:Any,<:Jacobi{<:Any,<:Integer}}) = A broadcastbasis(::typeof(+), A::Weighted{<:Any,<:Jacobi{<:Any,<:Integer}}, B::Jacobi) = B +broadcasted(::LazyQuasiArrayStyle{2}, ::typeof(*), w::AbstractJacobiWeight, v::WeightedJacobi) = + (w .* v.args[1]) .* v.args[2] + + function \(w_A::WeightedJacobi, w_B::WeightedJacobi) wA,A = w_A.args wB,B = w_B.args diff --git a/test/test_ultraspherical.jl b/test/test_ultraspherical.jl index d65675d..98d9792 100644 --- a/test/test_ultraspherical.jl +++ b/test/test_ultraspherical.jl @@ -210,10 +210,29 @@ using ClassicalOrthogonalPolynomials: grammatrix P = Jacobi(λ-1/2,λ-1/2) W = Jacobi(λ-1-1/2,λ-1-1/2) Q = Jacobi(λ+1-1/2,λ+1-1/2) + # a+ b = 2λ-1 D = Derivative(P) - t,n = 0.3,5 + x,n = 0.3,5 + # L₁ @test (D*P)[t,n+1] ≈ (n+2λ)/2 * Q[t,n] # L₁ # L₃L₂ - -(JacobiWeight(-(a+b+n),0) .* (D * (JacobiWeight(a+b+n+1,-(a+b+n)) .* D * (JacobiWeight(0,a+b+n+1) .* P))))[t,n+1] + @test -(JacobiWeight(-(2λ+n),0) .* (D * (JacobiWeight(2λ+n+1,-(2λ+n-1)) .* D * (JacobiWeight(0,2λ+n) .* P))))[x,n+1] ≈ + (n + 2λ)*(1 + n + 2λ) * P[x,n+1] + 2x*(1+n+2λ)* diff(P)[x,n+1] + (x^2-1) * diff(P,2)[x,n+1] ≈ (n+2λ)*(n+2λ+1)*Q[x,n+1] + # L₄'L₃ == L₅'L₂ + @test -(JacobiWeight(0,n+1) .* (D * (JacobiWeight(-(2λ+n-1),-n) .* D * (JacobiWeight(2λ+n,0) .* P))))[x,n+1] ≈ + (JacobiWeight(n+1,0) .* (D * (JacobiWeight(-n,-(2λ+n-1)) .* D * (JacobiWeight(0,2λ+n) .* P))))[x,n+1] ≈ + -n * (n + 2λ) * P[x,n+1] + (1 + 2n + x + 2λ + 2x*λ)* diff(P)[x,n+1] + (x^2-1) * diff(P,2)[x,n+1] ≈ + n * (n + 2λ) * P[x,n+1] + (1 + 2n - x + 2λ - 2x*λ)* diff(P)[x,n+1] + (1-x^2) * diff(P,2)[x,n+1] ≈ (n+2λ)*(n+λ+1/2)*Q[x,n] + # L₅'L₄' == L₄'L₅' + @test (JacobiWeight(n,0) .* (D * (JacobiWeight(1-n,n+1) .* D * (JacobiWeight(0,-n) .* P))))[x,n+1] ≈ + (JacobiWeight(0,n) .* (D * (JacobiWeight(n+1,1-n) .* D * (JacobiWeight(-n,0) .* P))))[x,n+1] ≈ + -n * (n - 1) * P[x,n+1] + 2x * (n-1)* diff(P)[x,n+1] - (x^2-1) * diff(P,2)[x,n+1] ≈ + (n+λ-1/2)^2*Q[x,n-1] + + P = Ultraspherical(λ) + Q = Ultraspherical(λ+1) + # L₃L₂ + @test (n + 2λ)*(1 + n + 2λ) * P[t,n+1] + 2t*(1+n+2λ)* diff(P)[t,n+1] + (t^2-1) * diff(P,2)[t,n+1] ≈ 2λ*(1 + 2n + 2λ)Q[t,n+1] + end end \ No newline at end of file