Skip to content

Commit 0c252e0

Browse files
start triangular harmonics
1 parent 66d3b7a commit 0c252e0

File tree

10 files changed

+226
-6
lines changed

10 files changed

+226
-6
lines changed

LICENSE.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
The FastTransforms.jl package is licensed under the MIT "Expat" License:
22

3-
> Copyright (c) 2017: Richard Mikael Slevinsky.
3+
> Copyright (c) 2016-2017: Richard Mikael Slevinsky and other contributors:
4+
>
5+
> https://github.com/MikaelSlevinsky/FastTransforms.jl/graphs/contributors
46
>
57
> Permission is hereby granted, free of charge, to any person obtaining
68
> a copy of this software and associated documentation files (the

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ As with other fast transforms, `plan_sph2fourier` saves effort by caching the pr
166166

167167
[1] B. Alpert and V. Rokhlin. <a href="http://dx.doi.org/10.1137/0912009">A fast algorithm for the evaluation of Legendre expansions</a>, *SIAM J. Sci. Stat. Comput.*, **12**:158—179, 1991.
168168

169-
[2] N. Hale and A. Townsend. <a href="http://dx.doi.org/10.1137/130932223">A fast, simple, and stable Chebyshev—Legendre transform using and asymptotic formula</a>, *SIAM J. Sci. Comput.*, **36**:A148—A167, 2014.
169+
[2] N. Hale and A. Townsend. <a href="http://dx.doi.org/10.1137/130932223">A fast, simple, and stable Chebyshev—Legendre transform using an asymptotic formula</a>, *SIAM J. Sci. Comput.*, **36**:A148—A167, 2014.
170170

171171
[3] J. Keiner. <a href="http://dx.doi.org/10.1137/070703065">Computing with expansions in Gegenbauer polynomials</a>, *SIAM J. Sci. Comput.*, **31**:2151—2171, 2009.
172172

src/FastTransforms.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ export SlowSphericalHarmonicPlan, FastSphericalHarmonicPlan, ThinSphericalHarmon
2929
export sph2fourier, fourier2sph, plan_sph2fourier
3030
export sphones, sphzeros, sphrand, sphrandn, sphevaluate
3131

32+
export SlowTriangularHarmonicPlan
33+
export tri2cheb, cheb2tri, plan_tri2cheb
34+
export triones, trizeros, trirand, trirandn, trievaluate
35+
3236
# Other module methods and constants:
3337
#export ChebyshevJacobiPlan, jac2cheb, cheb2jac
3438
#export sqrtpi, pochhammer, stirlingseries, stirlingremainder, Aratio, Cratio, Anαβ
@@ -69,6 +73,7 @@ jac2jac(x...)=th_jac2jac(x...)
6973

7074
include("hierarchical.jl")
7175
include("SphericalHarmonics/SphericalHarmonics.jl")
76+
include("TriangularHarmonics/TriangularHarmonics.jl")
7277

7378
include("gaunt.jl")
7479

src/SphericalHarmonics/fastplan.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ function Base.At_mul_B!(Y::Matrix, FP::FastSphericalHarmonicPlan, X::Matrix)
7777
At_mul_B_col_J!(Y, BF[J-1], B, 2J)
7878
At_mul_B_col_J!(Y, BF[J-1], B, 2J+1)
7979
end
80-
zero_spurious_modes!(Y)
80+
sph_zero_spurious_modes!(Y)
8181
end
8282

8383
Base.Ac_mul_B!(Y::Matrix, FP::FastSphericalHarmonicPlan, X::Matrix) = At_mul_B!(Y, FP, X)

src/SphericalHarmonics/slowplan.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ function Base.At_mul_B!(Y::Matrix, SP::SlowSphericalHarmonicPlan, X::Matrix)
177177
A_mul_B_col_J!!(Y, p1inv, B, J)
178178
A_mul_B_col_J!!(Y, p1inv, B, J+1)
179179
end
180-
zero_spurious_modes!(At_mul_B!(RP, Y))
180+
sph_zero_spurious_modes!(At_mul_B!(RP, Y))
181181
end
182182

183183
Base.Ac_mul_B!(Y::Matrix, SP::SlowSphericalHarmonicPlan, X::Matrix) = At_mul_B!(Y, SP, X)

src/SphericalHarmonics/sphfunctions.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
function zero_spurious_modes!(A::AbstractMatrix)
1+
function sph_zero_spurious_modes!(A::AbstractMatrix)
22
M, N = size(A)
33
n = N÷2
44
@inbounds for j = 1:n

src/SphericalHarmonics/thinplan.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ function Base.At_mul_B!(Y::Matrix, TP::ThinSphericalHarmonicPlan, X::Matrix)
148148
end
149149
end
150150

151-
zero_spurious_modes!(Y)
151+
sph_zero_spurious_modes!(Y)
152152
end
153153

154154
Base.Ac_mul_B!(Y::Matrix, TP::ThinSphericalHarmonicPlan, X::Matrix) = At_mul_B!(Y, TP, X)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
@compat abstract type TriangularHarmonicPlan{T} end
2+
3+
function *(P::TriangularHarmonicPlan, X::AbstractMatrix)
4+
A_mul_B!(zero(X), P, X)
5+
end
6+
7+
function \(P::TriangularHarmonicPlan, X::AbstractMatrix)
8+
At_mul_B!(zero(X), P, X)
9+
end
10+
11+
include("trifunctions.jl")
12+
include("slowplan.jl")
13+
14+
function plan_tri2cheb(A::AbstractMatrix, α, β, γ; opts...)
15+
M, N = size(A)
16+
if M 1023
17+
SlowTriangularHarmonicPlan(A, α, β, γ)
18+
else
19+
ThinTriangularHarmonicPlan(A, α, β, γ; opts...)
20+
end
21+
end
22+
23+
tri2cheb(A::AbstractMatrix, α, β, γ; opts...) = plan_tri2cheb(A, α, β, γ; opts...)*A
24+
cheb2tri(A::AbstractMatrix, α, β, γ; opts...) = plan_tri2cheb(A, α, β, γ; opts...)\A

src/TriangularHarmonics/slowplan.jl

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
immutable Pnmp1toPlm{T} <: AbstractRotation{T}
2+
rotations::Vector{Givens{T}}
3+
end
4+
5+
function Pnmp1toPlm{T}(::Type{T}, n::Int, m::Int, α::T, β::T, γ::T)
6+
G = Vector{Givens{T}}(n)
7+
@inbounds for= 1:n
8+
c = sqrt((2m+β+γ+2)/(ℓ+2m+β+γ+2)*(2+2m+α+β+γ+2)/(ℓ+2m+α+β+γ+2))
9+
s = sqrt(ℓ/(ℓ+2m+β+γ+2)*(ℓ+α)/(ℓ+2m+α+β+γ+2))
10+
G[n+1-ℓ] = Givens(ℓ, ℓ+1, c, s)
11+
end
12+
Pnmp1toPlm(G)
13+
end
14+
15+
@inline length(P::Pnmp1toPlm) = length(P.rotations)
16+
@inline getindex(P::Pnmp1toPlm, i::Int) = P.rotations[i]
17+
18+
function Base.A_mul_B!(C::Pnmp1toPlm, A::AbstractVecOrMat)
19+
@inbounds for i = 1:length(C)
20+
A_mul_B!(C.rotations[i], A)
21+
end
22+
A
23+
end
24+
25+
function Base.A_mul_B!(A::AbstractMatrix, C::Pnmp1toPlm)
26+
@inbounds for i = length(C):-1:1
27+
A_mul_B!(A, C.rotations[i])
28+
end
29+
A
30+
end
31+
32+
immutable TriRotationPlan{T} <: AbstractRotation{T}
33+
layers::Vector{Pnmp1toPlm{T}}
34+
end
35+
36+
function TriRotationPlan{T}(::Type{T}, n::Int, α::T, β::T, γ::T)
37+
layers = Vector{Pnmp1toPlm{T}}(n)
38+
@inbounds for m = 0:n-1
39+
layers[m+1] = Pnmp1toPlm(T, n-m, m, α, β, γ)
40+
end
41+
TriRotationPlan(layers)
42+
end
43+
44+
function Base.A_mul_B!(P::TriRotationPlan, A::AbstractMatrix)
45+
M, N = size(A)
46+
@inbounds for m = N-1:-1:1
47+
layer = P.layers[m]
48+
for= (m+1):N
49+
@simd for i = 1:length(layer)
50+
G = layer[i]
51+
a1, a2 = A[G.i1,ℓ], A[G.i2,ℓ]
52+
A[G.i1,ℓ] = G.c*a1 + G.s*a2
53+
A[G.i2,ℓ] = G.c*a2 - G.s*a1
54+
end
55+
end
56+
end
57+
A
58+
end
59+
60+
function Base.At_mul_B!(P::TriRotationPlan, A::AbstractMatrix)
61+
M, N = size(A)
62+
@inbounds for m = 1:N-1
63+
layer = P.layers[m]
64+
for= (m+1):N
65+
@simd for i = length(layer):-1:1
66+
G = layer[i]
67+
a1, a2 = A[G.i1,ℓ], A[G.i2,ℓ]
68+
A[G.i1,ℓ] = G.c*a1 - G.s*a2
69+
A[G.i2,ℓ] = G.s*a1 + G.c*a2
70+
end
71+
end
72+
end
73+
A
74+
end
75+
76+
Base.Ac_mul_B!(P::TriRotationPlan, A::AbstractMatrix) = At_mul_B!(P, A)
77+
78+
79+
immutable SlowTriangularHarmonicPlan{T} <: TriangularHarmonicPlan{T}
80+
RP::TriRotationPlan{T}
81+
p::NormalizedLegendreToChebyshevPlan{T}
82+
pinv::ChebyshevToNormalizedLegendrePlan{T}
83+
B::Matrix{T}
84+
end
85+
86+
function SlowTriangularHarmonicPlan{T}(A::Matrix{T}, α, β, γ)
87+
@assert β == γ == -half(T)
88+
@assert α == zero(T)
89+
M, N = size(A)
90+
n = N
91+
RP = TriRotationPlan(T, n-1, α, β, γ)
92+
p = plan_normleg2cheb(A)
93+
pinv = plan_cheb2normleg(A)
94+
B = zeros(A)
95+
SlowTriangularHarmonicPlan(RP, p, pinv, B)
96+
end
97+
98+
function Base.A_mul_B!(Y::Matrix, SP::SlowTriangularHarmonicPlan, X::Matrix)
99+
RP, p, B = SP.RP, SP.p, SP.B
100+
copy!(B, X)
101+
A_mul_B!(RP, B)
102+
M, N = size(X)
103+
for J = 1:N
104+
A_mul_B_col_J!!(Y, p, B, J)
105+
end
106+
@inbounds for J = 1:N
107+
nrm = sqrt/(2-δ(J-1,0)))
108+
@simd for I = 1:M
109+
Y[I,J] *= nrm
110+
end
111+
end
112+
Y
113+
end
114+
115+
function Base.At_mul_B!(Y::Matrix, SP::SlowTriangularHarmonicPlan, X::Matrix)
116+
RP, pinv, B = SP.RP, SP.pinv, SP.B
117+
copy!(B, X)
118+
M, N = size(X)
119+
@inbounds for J = 1:N
120+
nrm = sqrt((2-δ(J-1,0))/π)
121+
@simd for I = 1:M
122+
B[I,J] *= nrm
123+
end
124+
end
125+
for J = 1:N
126+
A_mul_B_col_J!!(Y, pinv, B, J)
127+
end
128+
tri_zero_spurious_modes!(At_mul_B!(RP, Y))
129+
end
130+
131+
Base.Ac_mul_B!(Y::Matrix, SP::SlowTriangularHarmonicPlan, X::Matrix) = At_mul_B!(Y, SP, X)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
function tri_zero_spurious_modes!(A::AbstractMatrix)
2+
M, N = size(A)
3+
@inbounds for j = 2:N
4+
@simd for i = M-j+2:M
5+
A[i,j] = 0
6+
end
7+
end
8+
A
9+
end
10+
11+
function trirand{T}(::Type{T}, m::Int, n::Int)
12+
A = zeros(T, m, n)
13+
for j = 1:n
14+
for i = 1:m+1-j
15+
A[i,j] = rand(T)
16+
end
17+
end
18+
A
19+
end
20+
21+
function trirandn{T}(::Type{T}, m::Int, n::Int)
22+
A = zeros(T, m, n)
23+
for j = 1:n
24+
for i = 1:m+1-j
25+
A[i,j] = randn(T)
26+
end
27+
end
28+
A
29+
end
30+
31+
function triones{T}(::Type{T}, m::Int, n::Int)
32+
A = zeros(T, m, n)
33+
for j = 1:n
34+
for i = 1:m+1-j
35+
A[i,j] = one(T)
36+
end
37+
end
38+
A
39+
end
40+
41+
trizeros{T}(::Type{T}, m::Int, n::Int) = zeros(T, m, n)
42+
43+
doc"""
44+
Pointwise evaluation of triangular harmonic:
45+
46+
```math
47+
\tilde{P}_{\ell,m}^{(\alpha,\beta,\gamma)}(x,y).
48+
```
49+
"""
50+
trievaluate(x, y, L, M, α, β, γ) = trievaluate(x, L, M, α, β, γ)*trievaluate(x, y, M, β, γ)
51+
52+
function trievaluate(x::Number, L::Integer, M::Integer, α::Number, β::Number, γ::Number)
53+
54+
end
55+
56+
function trievaluate(x::Number, y::Number, M::Integer, β::Number, γ::Number)
57+
58+
end

0 commit comments

Comments
 (0)