Skip to content

Commit be717c4

Browse files
authored
Add Zernike transform (#64)
* Add Zernike transform * Update test_disk.jl
1 parent b963c6c commit be717c4

File tree

3 files changed

+56
-9
lines changed

3 files changed

+56
-9
lines changed

src/MultivariateOrthogonalPolynomials.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ import LinearAlgebra: factorize
1616
import LazyArrays: arguments, paddeddata
1717

1818
import ClassicalOrthogonalPolynomials: jacobimatrix
19-
import HarmonicOrthogonalPolynomials: BivariateOrthogonalPolynomial, MultivariateOrthogonalPolynomial,
20-
PartialDerivative, BlockOneTo, interlace
19+
import HarmonicOrthogonalPolynomials: BivariateOrthogonalPolynomial, MultivariateOrthogonalPolynomial, Plan,
20+
PartialDerivative, BlockOneTo, BlockRange1, interlace
2121

2222
export UnitTriangle, UnitDisk, JacobiTriangle, TriangleWeight, WeightedTriangle, PartialDerivative, Laplacian,
2323
MultivariateOrthogonalPolynomial, BivariateOrthogonalPolynomial, Zernike, RadialCoordinate

src/disk.jl

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,43 @@ function getindex(Z::Zernike{T}, rθ::RadialCoordinate, B::BlockIndex{1}) where
6060
if iszero(m)
6161
sqrt(convert(T,2)/π) * Normalized(Legendre{T}())[2r^2-1, ℓ ÷ 2 + 1]
6262
else
63-
convert(T,2^((m+2)/2))/π * r^m * Normalized(Jacobi{T}(0, m))[2r^2-1,(ℓ-m) ÷ 2 + 1] * (isodd(k+ℓ) ? cos(m*θ) : sin(m*θ))
63+
sqrt(convert(T,2)^(m+2)/π) * r^m * Normalized(Jacobi{T}(0, m))[2r^2-1,(ℓ-m) ÷ 2 + 1] * (isodd(k+ℓ) ? cos(m*θ) : sin(m*θ))
6464
end
6565
end
6666

6767

6868
getindex(Z::Zernike, xy::StaticVector{2}, B::BlockIndex{1}) = Z[RadialCoordinate(xy), B]
6969
getindex(Z::Zernike, xy::StaticVector{2}, B::Block{1}) = [Z[xy, B[j]] for j=1:Int(B)]
70-
getindex(Z::Zernike, xy::StaticVector{2}, JR::BlockOneTo) = mortar([Z[xy,Block(J)] for J = 1:Int(JR[end])])
70+
getindex(Z::Zernike, xy::StaticVector{2}, JR::BlockOneTo) = mortar([Z[xy,Block(J)] for J = 1:Int(JR[end])])
71+
72+
73+
###
74+
# Transforms
75+
###
76+
77+
const FiniteZernike{T} = SubQuasiArray{T,2,Zernike{T},<:Tuple{<:Inclusion,<:BlockSlice{BlockRange1{OneTo{Int}}}}}
78+
79+
function grid(S::FiniteZernike{T}) where T
80+
N = blocksize(S,2) ÷ 2 + 1 # polynomial degree
81+
M = 4N-3
82+
83+
r = sinpi.((N .-(0:N-1) .- one(T)/2) ./ (2N))
84+
85+
# The angular grid:
86+
θ = (0:M-1)*convert(T,2)/M
87+
RadialCoordinate.(r, π*θ')
88+
end
89+
90+
struct ZernikeTransform{T} <: Plan{T}
91+
N::Int
92+
disk2cxf::FastTransforms.FTPlan{T,2,FastTransforms.DISK}
93+
analysis::FastTransforms.FTPlan{T,2,FastTransforms.DISKANALYSIS}
94+
end
95+
96+
function ZernikeTransform{T}(N::Int) where T<:Real
97+
= N ÷ 2 + 1
98+
ZernikeTransform{T}(N, plan_disk2cxf(T, Ñ, 0, 0), plan_disk_analysis(T, Ñ, 4-3))
99+
end
100+
*(P::ZernikeTransform{T}, f::Matrix{T}) where T = DiskTrav(P.disk2cxf \ (P.analysis * f))[Block.(1:P.N)]
101+
102+
factorize(S::FiniteZernike{T}) where T = TransformFactorization(grid(S), ZernikeTransform{T}(blocksize(S,2)))

test/test_disk.jl

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
using MultivariateOrthogonalPolynomials, StaticArrays, BlockArrays, Test
2-
import MultivariateOrthogonalPolynomials: DiskTrav
1+
using MultivariateOrthogonalPolynomials, StaticArrays, BlockArrays, FastTransforms, LinearAlgebra, Test
2+
import MultivariateOrthogonalPolynomials: DiskTrav, grid
33

44
function chebydiskeval(c::AbstractMatrix{T}, r, θ) where T
55
ret = zero(T)
@@ -21,8 +21,8 @@ end
2121
xy = SVector(rθ)
2222
@test Zernike()[rθ,1] Zernike()[xy,1] inv(sqrt(π))
2323
@test Zernike()[rθ,Block(1)] Zernike()[xy,Block(1)] [inv(sqrt(π))]
24-
@test Zernike()[rθ,Block(2)] [2r/π*sin(θ), 2r/π*cos(θ)]
25-
@test Zernike()[rθ,Block(3)] [sqrt(3/π)*(2r^2-1),sqrt(6)/π*r^2*sin(2θ),sqrt(6)/π*r^2*cos(2θ)]
24+
@test Zernike()[rθ,Block(2)] [2r/sqrt(π)*sin(θ), 2r/sqrt(π)*cos(θ)]
25+
@test Zernike()[rθ,Block(3)] [sqrt(3/π)*(2r^2-1),sqrt(6/π)*r^2*sin(2θ),sqrt(6/π)*r^2*cos(2θ)]
2626
end
2727

2828
@testset "DiskTrav" begin
@@ -40,4 +40,19 @@ end
4040
@test_throws ArgumentError DiskTrav([1 2 3; 4 5 6])
4141
@test_throws ArgumentError DiskTrav([1 2 3 4; 5 6 7 8])
4242
end
43-
end
43+
44+
@testset "Transform" begin
45+
Zn = Zernike()[:,Block.(Base.OneTo(3))]
46+
for k = 1:6
47+
@test factorize(Zn) \ Zernike()[:,k] [zeros(k-1); 1; zeros(6-k)]
48+
end
49+
50+
Z = Zernike();
51+
xy = axes(Z,1); x,y = first.(xy),last.(xy);
52+
u = Z * (Z \ exp.(x .* cos.(y)))
53+
@test u[SVector(0.1,0.2)] exp(0.1cos(0.2))
54+
end
55+
end
56+
57+
58+

0 commit comments

Comments
 (0)