Skip to content

Commit 4175c69

Browse files
authored
PartialDerivative -> diff (#198)
* PartialDerivative -> diff * AbsLaplacianPower -> abslaplacian * rect tests pass * add coordinate, disk tests pass * Fix some tests, support laplacian on rectangles * Tests pass * Update Project.toml * Update test_triangle.jl
1 parent 5b4763f commit 4175c69

14 files changed

+153
-146
lines changed

Project.toml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "MultivariateOrthogonalPolynomials"
22
uuid = "4f6956fd-4f93-5457-9149-7bfc4b2ce06d"
3-
version = "0.8"
3+
version = "0.9"
44

55
[deps]
66
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"
@@ -25,21 +25,21 @@ StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
2525
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
2626

2727
[compat]
28-
ArrayLayouts = "1.0.9"
28+
ArrayLayouts = "1.11"
2929
BandedMatrices = "1"
3030
BlockArrays = "1.0"
3131
BlockBandedMatrices = "0.13"
32-
ClassicalOrthogonalPolynomials = "0.14.1"
33-
ContinuumArrays = "0.18"
32+
ClassicalOrthogonalPolynomials = "0.15"
33+
ContinuumArrays = "0.19"
3434
DomainSets = "0.7"
3535
FastTransforms = "0.17"
3636
FillArrays = "1.0"
37-
HarmonicOrthogonalPolynomials = "0.6.3"
37+
HarmonicOrthogonalPolynomials = "0.7"
3838
InfiniteArrays = "0.15"
3939
InfiniteLinearAlgebra = "0.9"
4040
LazyArrays = "2.3.1"
41-
LazyBandedMatrices = "0.11.1"
42-
QuasiArrays = "0.11"
41+
LazyBandedMatrices = "0.11.3"
42+
QuasiArrays = "0.12"
4343
RecurrenceRelationships = "0.2"
4444
SpecialFunctions = "1, 2"
4545
StaticArrays = "1"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ julia> using MultivariateOrthogonalPolynomials, StaticArrays, LinearAlgebra
1212
julia> P = JacobiTriangle()
1313
JacobiTriangle(0, 0, 0)
1414

15-
julia> x,y = first.(axes(P,1)), last.(axes(P,1));
15+
julia> x,y = coordinates(P);
1616

1717
julia> u = P * (P \ (exp.(x) .* cos.(y))) # Expand in Triangle OPs
1818
JacobiTriangle(0, 0, 0) * [1.3365085377830084, 0.5687967596428205, -0.22812040274224554, 0.07733064070637755, 0.016169744493985644, -0.08714886622738759, 0.00338435674992512, 0.01220019521126353, -0.016867598915573725, 0.003930461395801074 ]

examples/diskheat.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ pyplot() # pyplot supports disks
33

44
Z = Zernike(1)
55
W = Weighted(Z)
6-
xy = axes(W,1)
7-
x,y = first.(xy),last.(xy)
6+
x,y = coordinates(W)
87
Δ = Z \ Laplacian(xy) * W
98
S = Z \ W
109

examples/diskhelmholtz.jl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@ pyplot()
1414

1515
Z = Zernike(1)
1616
W = Weighted(Z) # w*Z
17-
xy = axes(Z, 1);
18-
x, y = first.(xy), last.(xy);
19-
Δ = Z \ (Laplacian(xy) * W)
17+
x, y = coordinates(W)
18+
Δ = Z \ laplacian(W)
2019
S = Z \ W # identity
2120

2221

examples/multivariatelanczos.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ using MultivariateOrthogonalPolynomials, ClassicalOrthogonalPolynomials, Test
33
P = Legendre()
44
= RectPolynomial(P,P)
55
p₀ = expand(P², 𝐱 -> 1)
6-
𝐱 = axes(P²,1)
7-
x,y = first.(𝐱),last.(𝐱)
6+
x,y = coordinates(P²)
87
w =/\ (x-y).^2
98

109
w .* p₀

src/MultivariateOrthogonalPolynomials.jl

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ using ClassicalOrthogonalPolynomials, FastTransforms, BlockBandedMatrices, Block
66
LazyArrays, SpecialFunctions, LinearAlgebra, BandedMatrices, LazyBandedMatrices, ArrayLayouts,
77
HarmonicOrthogonalPolynomials, RecurrenceRelationships
88

9-
import Base: axes, in, ==, +, -, /, *, ^, \, copy, copyto!, OneTo, getindex, size, oneto, all, resize!, BroadcastStyle, similar, fill!, setindex!, convert, show, summary
9+
import Base: axes, in, ==, +, -, /, *, ^, \, copy, copyto!, OneTo, getindex, size, oneto, all, resize!, BroadcastStyle, similar, fill!, setindex!, convert, show, summary, diff
1010
import Base.Broadcast: Broadcasted, broadcasted, DefaultArrayStyle
1111
import DomainSets: boundary, EuclideanDomain
1212

1313
import QuasiArrays: LazyQuasiMatrix, LazyQuasiArrayStyle, domain
14-
import ContinuumArrays: @simplify, Weight, weight, grid, plotgrid, TransformFactorization, ExpansionLayout, plotvalues, unweighted, plan_transform, checkpoints, transform_ldiv, AbstractBasisLayout, basis_axes, Inclusion, grammatrix, weaklaplacian, layout_broadcasted
14+
import ContinuumArrays: @simplify, Weight, weight, grid, plotgrid, TransformFactorization, ExpansionLayout, plotvalues, unweighted, plan_transform, checkpoints, transform_ldiv, AbstractBasisLayout, basis_axes, Inclusion, grammatrix, weaklaplacian, layout_broadcasted, laplacian, abslaplacian, laplacian_axis, abslaplacian_axis, diff_layout, operatororder, broadcastbasis
1515

1616
import ArrayLayouts: MemoryLayout, sublayout, sub_materialize
1717
import BlockArrays: block, blockindex, BlockSlice, viewblock, blockcolsupport, AbstractBlockStyle, BlockStyle
@@ -23,17 +23,31 @@ import InfiniteArrays: InfiniteCardinal, OneToInf
2323

2424
import ClassicalOrthogonalPolynomials: jacobimatrix, Weighted, orthogonalityweight, HalfWeighted, WeightedBasis, pad, recurrencecoefficients, clenshaw, weightedgrammatrix, Clenshaw
2525
import HarmonicOrthogonalPolynomials: BivariateOrthogonalPolynomial, MultivariateOrthogonalPolynomial, Plan,
26-
PartialDerivative, AngularMomentum, BlockOneTo, BlockRange1, interlace,
26+
AngularMomentum, angularmomentum, BlockOneTo, BlockRange1, interlace,
2727
MultivariateOPLayout, AbstractMultivariateOPLayout, MAX_PLOT_BLOCKS
2828

2929
export MultivariateOrthogonalPolynomial, BivariateOrthogonalPolynomial,
3030
UnitTriangle, UnitDisk,
3131
JacobiTriangle, TriangleWeight, WeightedTriangle,
3232
DunklXuDisk, DunklXuDiskWeight, WeightedDunklXuDisk,
3333
Zernike, ZernikeWeight, zerniker, zernikez,
34-
PartialDerivative, Laplacian, AbsLaplacianPower, AngularMomentum,
34+
AngularMomentum,
3535
RadialCoordinate, Weighted, Block, jacobimatrix, KronPolynomial, RectPolynomial,
36-
grammatrix, oneto
36+
grammatrix, oneto, coordinates, Laplacian, AbsLaplacian, laplacian, abslaplacian, angularmomentum, weaklaplacian
37+
38+
39+
laplacian_axis(::Inclusion{<:SVector{2}}, A; dims...) = diff(A, (2,0); dims...) + diff(A, (0, 2); dims...)
40+
abslaplacian_axis(::Inclusion{<:SVector{2}}, A; dims...) = -(diff(A, (2,0); dims...) + diff(A, (0, 2); dims...))
41+
coordinates(P) = (first.(axes(P,1)), last.(axes(P,1)))
42+
43+
function diff_layout(::AbstractBasisLayout, a, (k,j)::NTuple{2,Int}; dims...)
44+
(k < 0 || j < 0) && throw(ArgumentError("order must be non-negative"))
45+
k == j == 0 && return a
46+
((k,j) == (1,0) || (k,j) == (0,1)) && return diff(a, Val((k,j)); dims...)
47+
k j && return diff(diff(a, (1,0)), (k-1,j))
48+
diff(diff(a, (0,1)), (k,j-1))
49+
end
50+
3751

3852
include("ModalInterlace.jl")
3953
include("clenshawkron.jl")

src/disk.jl

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -262,16 +262,14 @@ plan_transform(Z::Zernike{T}, (N,)::Tuple{Block{1}}, dims=1) where T = ZernikeTr
262262
# Laplacian
263263
###
264264

265-
@simplify function *::Laplacian, WZ::Weighted{<:Any,<:Zernike})
265+
function laplacian(WZ::Weighted{T,<:Zernike}; dims...) where T
266266
@assert WZ.P.a == 0 && WZ.P.b == 1
267-
T = eltype(eltype(WZ))
268267
WZ.P * ModalInterlace{T}(broadcast(k -> Diagonal(-cumsum(k:8:∞)), 4:4:∞), (ℵ₀,ℵ₀), (0,0))
269268
end
270269

271-
@simplify function *::Laplacian, Z::Zernike)
270+
function laplacian(Z::Zernike{T}; dims...) where T
272271
a,b = Z.a,Z.b
273272
@assert a == 0
274-
T = promote_type(eltype(eltype(Δ)),eltype(Z)) # TODO: remove extra eltype
275273
D = Derivative(Inclusion(ChebyshevInterval{T}()))
276274
Δs = BroadcastVector{AbstractMatrix{T}}((C,B,A) -> 4(HalfWeighted{:b}(C)\(D*HalfWeighted{:b}(B)))*(B\(D*A)), Normalized.(Jacobi.(b+2,a:∞)), Normalized.(Jacobi.(b+1,(a+1):∞)), Normalized.(Jacobi.(b,a:∞)))
277275
Δ = ModalInterlace(Δs, (ℵ₀,ℵ₀), (-2,2))
@@ -282,9 +280,9 @@ end
282280
# Fractional Laplacian
283281
###
284282

285-
function *(L::AbsLaplacianPower, WZ::Weighted{<:Any,<:Zernike{<:Any}})
286-
@assert axes(L,1) == axes(WZ,1) && WZ.P.a == 0 && WZ.P.b == L.α
287-
WZ.P * Diagonal(WeightedZernikeFractionalLaplacianDiag{typeof(L.α)}(L.α))
283+
function abslaplacian(WZ::Weighted{<:Any,<:Zernike}, α; dims...)
284+
@assert WZ.P.a == 0 && WZ.P.b == α
285+
WZ.P * Diagonal(WeightedZernikeFractionalLaplacianDiag{typeof(α)}(α))
288286
end
289287

290288
# gives the entries for the (negative!) fractional Laplacian (-Δ)^(α) times (1-r^2)^α * Zernike(α)

src/rect.jl

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,11 @@ function jacobimatrix(::Val{2}, P::RectPolynomial)
5252
Y = jacobimatrix(B)
5353
KronTrav(Y, Eye{eltype(Y)}(∞))
5454
end
55-
@simplify function *(Dx::PartialDerivative{1}, P::RectPolynomial)
56-
A,B = P.args
57-
U,M = (Derivative(axes(A,1))*A).args
58-
# We want I ⊗ D² as A ⊗ B means B * X * A'
59-
RectPolynomial(U,B) * KronTrav(Eye{eltype(M)}(∞), M)
55+
function diff(P::KronPolynomial{N}, order::NTuple{N,Int}; dims...) where N
56+
diffs = diff.(P.args, order)
57+
RectPolynomial(basis.(diffs)...) * KronTrav(coefficients.(diffs)...)
6058
end
6159

62-
@simplify function *(Dx::PartialDerivative{2}, P::RectPolynomial)
63-
A,B = P.args
64-
U,M = (Derivative(axes(B,1))*B).args
65-
RectPolynomial(A,U) * KronTrav(M, Eye{eltype(M)}(∞))
66-
end
6760

6861
function weaklaplacian(P::RectPolynomial)
6962
A,B = P.args
@@ -188,3 +181,6 @@ function layout_broadcasted(::Tuple{ExpansionLayout{KronOPLayout{2}},KronOPLayou
188181

189182
P * ClenshawKron(C, (recurrencecoefficients(A), recurrencecoefficients(B)), (jacobimatrix(T), jacobimatrix(U)))
190183
end
184+
185+
186+
broadcastbasis(::typeof(+), A::KronPolynomial, B::KronPolynomial) = KronPolynomial(broadcastbasis.(+, A.args, B.args)...)

src/rectdisk.jl

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ const WeightedDunklXuDisk{T} = WeightedBasis{T,<:DunklXuDiskWeight,<:DunklXuDisk
4141

4242
WeightedDunklXuDisk(β) = DunklXuDiskWeight(β) .* DunklXuDisk(β)
4343

44-
@simplify function *(Dx::PartialDerivative{1}, P::DunklXuDisk)
44+
function diff(P::DunklXuDisk, ::Val{(1,0)}; dims=1)
45+
@assert dims == 1
4546
β = P.β
4647
n = mortar(Fill.(oneto(∞),oneto(∞)))
4748
k = mortar(Base.OneTo.(oneto(∞)))
@@ -53,14 +54,15 @@ WeightedDunklXuDisk(β) = DunklXuDiskWeight(β) .* DunklXuDisk(β)
5354
DunklXuDisk+1) * _BandedBlockBandedMatrix(dat', axes(k,1), (-1,1), (0,2))
5455
end
5556

56-
@simplify function *(Dy::PartialDerivative{2}, P::DunklXuDisk)
57+
function diff(P::DunklXuDisk{T}, ::Val{(0,1)}; dims=1) where T
58+
@assert dims == 1
5759
β = P.β
5860
k = mortar(Base.OneTo.(oneto(∞)))
59-
T = promote_type(eltype(Dy), eltype(P)) # avoid bug in convert
6061
DunklXuDisk+1) * _BandedBlockBandedMatrix(((k .+ T(2β)) ./ 2)', axes(k,1), (-1,1), (-1,1))
6162
end
6263

63-
@simplify function *(Dx::PartialDerivative{1}, w_P::WeightedDunklXuDisk)
64+
function diff(w_P::WeightedDunklXuDisk, ::Val{(1,0)}; dims=1)
65+
@assert dims == 1
6466
wP, P = w_P.args
6567
@assert P.β == wP.β
6668
β = P.β
@@ -74,11 +76,11 @@ end
7476
WeightedDunklXuDisk-1) * _BandedBlockBandedMatrix(dat', axes(k,1), (1,-1), (2,0))
7577
end
7678

77-
@simplify function *(Dy::PartialDerivative{2}, w_P::WeightedDunklXuDisk)
79+
function diff(w_P::WeightedDunklXuDisk{T}, ::Val{(0,1)}; dims=1) where T
80+
@assert dims == 1
7881
wP, P = w_P.args
7982
@assert P.β == wP.β
8083
k = mortar(Base.OneTo.(oneto(∞)))
81-
T = promote_type(eltype(Dy), eltype(P)) # avoid bug in convert
8284
WeightedDunklXuDisk(P.β-1) * _BandedBlockBandedMatrix((T(-2).*k)', axes(k,1), (1,-1), (1,-1))
8385
end
8486

@@ -178,7 +180,7 @@ function jacobimatrix(::Val{2}, P::DunklXuDisk)
178180
_BandedBlockBandedMatrix(dat', axes(k,1), (1,1), (1,1))
179181
end
180182

181-
@simplify function *(A::AngularMomentum, P::DunklXuDisk)
183+
function angularmomentum(P::DunklXuDisk)
182184
β = P.β
183185
n = mortar(Fill.(oneto(∞),oneto(∞)))
184186
k = mortar(Base.OneTo.(oneto(∞)))

src/triangle.jl

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ summary(io::IO, P::TriangleWeight) = print(io, "x^$(P.a)*y^$(P.b)*(1-x-y)^$(P.c)
147147

148148
orthogonalityweight(P::JacobiTriangle) = TriangleWeight(P.a, P.b, P.c)
149149

150-
@simplify function *(Dx::PartialDerivative{1}, P::JacobiTriangle)
150+
function diff(P::JacobiTriangle{T}, ::Val{(1,0)}; dims=1) where T
151+
@assert dims == 1
151152
a,b,c = P.a,P.b,P.c
152153
n = mortar(Fill.(oneto(∞),oneto(∞)))
153154
k = mortar(Base.OneTo.(oneto(∞)))
@@ -158,16 +159,17 @@ orthogonalityweight(P::JacobiTriangle) = TriangleWeight(P.a, P.b, P.c)
158159
JacobiTriangle(a+1,b,c+1) * _BandedBlockBandedMatrix(dat', axes(k,1), (-1,1), (0,1))
159160
end
160161

161-
@simplify function *(Dy::PartialDerivative{2}, P::JacobiTriangle)
162+
function diff(P::JacobiTriangle{T}, ::Val{(0,1)}; dims=1) where T
163+
@assert dims == 1
162164
a,b,c = P.a,P.b,P.c
163165
k = mortar(Base.OneTo.(oneto(∞)))
164-
T = promote_type(eltype(Dy), eltype(P)) # avoid bug in convert
165166
JacobiTriangle(a,b+1,c+1) * _BandedBlockBandedMatrix((k .+ convert(T, b+c))', axes(k,1), (-1,1), (-1,1))
166167
end
167168

168169
# TODO: The derivatives below only hold for a, b, c > 0.
169-
@simplify function *(Dx::PartialDerivative{1}, P::WeightedTriangle)
170-
a, b, c = P.P.a, P.P.b, P.P.c
170+
function diff(w_P::WeightedTriangle{T}, ::Val{(1,0)}; dims=1) where T
171+
@assert dims == 1
172+
a, b, c = w_P.P.a, w_P.P.b, w_P.P.c
171173
n = mortar(Fill.(oneto(∞),oneto(∞)))
172174
k = mortar(Base.OneTo.(oneto(∞)))
173175
scale = -(2k .+ (b + c - 1))
@@ -177,19 +179,13 @@ end
177179
WeightedTriangle(a-1, b, c-1) * _BandedBlockBandedMatrix(dat', axes(k, 1), (1, -1), (1, 0))
178180
end
179181

180-
@simplify function *(Dy::PartialDerivative{2}, P::WeightedTriangle)
181-
a, b, c = P.P.a, P.P.b, P.P.c
182+
function diff(w_P::WeightedTriangle{T}, ::Val{(0,1)}; dims=1) where T
183+
@assert dims == 1
184+
a, b, c = w_P.P.a, w_P.P.b, w_P.P.c
182185
k = mortar(Base.OneTo.(oneto(∞)))
183-
T = promote_type(eltype(Dy), eltype(P)) # avoid bug in convert
184186
WeightedTriangle(a, b-1, c-1) * _BandedBlockBandedMatrix(-one(T) * k', axes(k, 1), (1, -1), (1, -1))
185187
end
186188

187-
# @simplify function *(Δ::Laplacian, P)
188-
# _lap_mul(P, eltype(axes(P,1)))
189-
# end
190-
191-
192-
193189
function grammatrix(A::JacobiTriangle)
194190
@assert A == JacobiTriangle()
195191
n = mortar(Fill.(oneto(∞),oneto(∞)))

0 commit comments

Comments
 (0)