Skip to content

Commit 69fa6b5

Browse files
Merge branch 'master' into feat-spherical-isometries
2 parents e369544 + da2fb36 commit 69fa6b5

File tree

12 files changed

+231
-159
lines changed

12 files changed

+231
-159
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
docs/build/
2-
docs/site/
2+
docs/src/generated
33
deps/build.log
44
deps/libfasttransforms.*
55
.DS_Store

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "FastTransforms"
22
uuid = "057dd010-8810-581a-b7be-e3fc3b93f78c"
3-
version = "0.10.1"
3+
version = "0.10.2"
44

55
[deps]
66
AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c"

README.md

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# FastTransforms.jl
22

3-
[![Build Status](https://github.com/JuliaApproximation/FastTransforms.jl/workflows/CI/badge.svg)](https://github.com/JuliaApproximation/FastTransforms.jl/actions?query=workflow%3ACI) [![Travis](https://travis-ci.org/JuliaApproximation/FastTransforms.jl.svg?branch=master)](https://travis-ci.org/JuliaApproximation/FastTransforms.jl) [![codecov](https://codecov.io/gh/JuliaApproximation/FastTransforms.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JuliaApproximation/FastTransforms.jl) [![](https://img.shields.io/badge/docs-stable-blue.svg)](https://JuliaApproximation.github.io/FastTransforms.jl/stable) [![](https://img.shields.io/badge/docs-dev-blue.svg)](https://JuliaApproximation.github.io/FastTransforms.jl/dev)
3+
[![Build Status](https://github.com/JuliaApproximation/FastTransforms.jl/workflows/CI/badge.svg)](https://github.com/JuliaApproximation/FastTransforms.jl/actions?query=workflow%3ACI) [![Travis](https://travis-ci.com/JuliaApproximation/FastTransforms.jl.svg?branch=master)](https://travis-ci.com/JuliaApproximation/FastTransforms.jl) [![codecov](https://codecov.io/gh/JuliaApproximation/FastTransforms.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JuliaApproximation/FastTransforms.jl) [![](https://img.shields.io/badge/docs-stable-blue.svg)](https://JuliaApproximation.github.io/FastTransforms.jl/stable) [![](https://img.shields.io/badge/docs-dev-blue.svg)](https://JuliaApproximation.github.io/FastTransforms.jl/dev)
44

55
`FastTransforms.jl` allows the user to conveniently work with orthogonal polynomials with degrees well into the millions.
66

@@ -157,18 +157,8 @@ julia> @time norm(ipaduatransform(paduatransform(v)) - v)/norm(v)
157157

158158
# References:
159159

160-
[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.
160+
[1] D. Ruiz—Antolín and A. Townsend. <a href="https://doi.org/10.1137/17M1134822">A nonuniform fast Fourier transform based on low rank approximation</a>, *SIAM J. Sci. Comput.*, **40**:A529–A547, 2018.
161161

162-
[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.
162+
[2] R. M. Slevinsky. <a href="https://doi.org/10.1016/j.acha.2017.11.001">Fast and backward stable transforms between spherical harmonic expansions and bivariate Fourier series</a>, *Appl. Comput. Harmon. Anal.*, **47**:585—606, 2019.
163163

164-
[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.
165-
166-
[4] D. Ruiz—Antolín and A. Townsend. <a href="https://arxiv.org/abs/1701.04492">A nonuniform fast Fourier transform based on low rank approximation</a>, arXiv:1701.04492, 2017.
167-
168-
[5] R. M. Slevinsky. <a href="https://doi.org/10.1093/imanum/drw070">On the use of Hahn's asymptotic formula and stabilized recurrence for a fast, simple, and stable Chebyshev—Jacobi transform</a>, *IMA J. Numer. Anal.*, **38**:102—124, 2018.
169-
170-
[6] R. M. Slevinsky. <a href="https://doi.org/10.1016/j.acha.2017.11.001">Fast and backward stable transforms between spherical harmonic expansions and bivariate Fourier series</a>, *Appl. Comput. Harmon. Anal.*, **47**:585—606, 2019.
171-
172-
[7] R. M. Slevinsky, <a href="https://arxiv.org/abs/1711.07866">Conquering the pre-computation in two-dimensional harmonic polynomial transforms</a>, arXiv:1711.07866, 2017.
173-
174-
[8] A. Townsend, M. Webb, and S. Olver. <a href="https://doi.org/10.1090/mcom/3277">Fast polynomial transforms based on Toeplitz and Hankel matrices</a>, in press at *Math. Comp.*, 2017.
164+
[3] R. M. Slevinsky, <a href="https://arxiv.org/abs/1711.07866">Conquering the pre-computation in two-dimensional harmonic polynomial transforms</a>, arXiv:1711.07866, 2017.

docs/Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
[deps]
22
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
3+
FastTransforms = "057dd010-8810-581a-b7be-e3fc3b93f78c"
4+
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
35

46
[compat]
57
Documenter = "~0.24"

docs/make.jl

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,41 @@
1-
using Documenter, FastTransforms
1+
using Documenter, FastTransforms, Literate
2+
3+
const EXAMPLES_DIR = joinpath(@__DIR__, "..", "examples")
4+
const OUTPUT_DIR = joinpath(@__DIR__, "src/generated")
5+
6+
examples = [
7+
"chebyshev.jl",
8+
"disk.jl",
9+
"nonlocaldiffusion.jl",
10+
"padua.jl",
11+
"sphere.jl",
12+
"spinweighted.jl",
13+
"triangle.jl",
14+
]
15+
16+
for example in examples
17+
example_filepath = joinpath(EXAMPLES_DIR, example)
18+
Literate.markdown(example_filepath, OUTPUT_DIR; execute=true)
19+
end
220

321
makedocs(
4-
doctest = false,
5-
format = Documenter.HTML(),
6-
sitename = "FastTransforms.jl",
7-
authors = "Richard Mikael Slevinsky",
8-
pages = Any[
9-
"Home" => "index.md"
10-
]
11-
)
22+
doctest = false,
23+
format = Documenter.HTML(),
24+
sitename = "FastTransforms.jl",
25+
authors = "Richard Mikael Slevinsky",
26+
pages = Any[
27+
"Home" => "index.md",
28+
"Examples" => [
29+
"generated/chebyshev.md",
30+
"generated/disk.md",
31+
"generated/nonlocaldiffusion.md",
32+
"generated/padua.md",
33+
"generated/sphere.md",
34+
"generated/spinweighted.md",
35+
"generated/triangle.md",
36+
],
37+
]
38+
)
1239

1340

1441
deploydocs(

examples/chebyshev.jl

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,46 @@
1-
#############
1+
# # Chebyshev transform
22
# This demonstrates the Chebyshev transform and inverse transform,
33
# explaining precisely the normalization and points
4-
#############
54

65
using FastTransforms
7-
8-
# first kind points -> first kind polynomials
96
n = 20
7+
8+
# First kind points $\to$ first kind polynomials
109
p_1 = chebyshevpoints(Float64, n, Val(1))
1110
f = exp.(p_1)
1211
= chebyshevtransform(f, Val(1))
13-
1412
= x -> [cos(k*acos(x)) for k=0:n-1]' *
1513
(0.1) exp(0.1)
1614

17-
# first kind polynomials -> first kind points
15+
# First kind polynomials $\to$ first kind points
1816
ichebyshevtransform(f̌, Val(1)) exp.(p_1)
1917

20-
# second kind points -> first kind polynomials
18+
# Second kind points $\to$ first kind polynomials
2119
p_2 = chebyshevpoints(Float64, n, Val(2))
2220
f = exp.(p_2)
2321
= chebyshevtransform(f, Val(2))
24-
2522
= x -> [cos(k*acos(x)) for k=0:n-1]' *
2623
(0.1) exp(0.1)
2724

28-
# first kind polynomials -> second kind points
25+
# First kind polynomials $\to$ second kind points
2926
ichebyshevtransform(f̌, Val(2)) exp.(p_2)
3027

31-
32-
# first kind points -> second kind polynomials
33-
n = 20
28+
# First kind points $\to$ second kind polynomials
3429
p_1 = chebyshevpoints(Float64, n, Val(1))
3530
f = exp.(p_1)
3631
= chebyshevutransform(f, Val(1))
3732
= x -> [sin((k+1)*acos(x))/sin(acos(x)) for k=0:n-1]' *
3833
(0.1) exp(0.1)
3934

40-
# second kind polynomials -> first kind points
35+
# Second kind polynomials $\to$ first kind points
4136
ichebyshevutransform(f̌, Val(1)) exp.(p_1)
4237

43-
44-
# second kind points -> second kind polynomials
38+
# Second kind points $\to$ second kind polynomials
4539
p_2 = chebyshevpoints(Float64, n, Val(2))[2:n-1]
4640
f = exp.(p_2)
4741
= chebyshevutransform(f, Val(2))
4842
= x -> [sin((k+1)*acos(x))/sin(acos(x)) for k=0:n-3]' *
4943
(0.1) exp(0.1)
5044

51-
# second kind polynomials -> second kind points
45+
# Second kind polynomials $\to$ second kind points
5246
ichebyshevutransform(f̌, Val(2)) exp.(p_2)

examples/disk.jl

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,56 @@
1-
#############
1+
# # Holomorphic integration on the unit disk
22
# In this example, we explore integration of a harmonic function:
3-
#
4-
# f(x,y) = (x^2-y^2+1)/[(x^2-y^2+1)^2+(2xy+1)^2],
5-
#
3+
# ```math
4+
# f(x,y) = \frac{x^2-y^2+1}{(x^2-y^2+1)^2+(2xy+1)^2},
5+
# ```
66
# over the unit disk. In this case, we know from complex analysis that the
7-
# integral of a holomorphic function is equal to π × f(0,0).
8-
# We analyze the function on an N×M tensor product grid defined by:
9-
#
10-
# rₙ = cos[(n+1/2)π/2N], for 0 ≤ n < N, and
11-
#
12-
# θₘ = 2π m/M, for 0 ≤ m < M;
13-
#
7+
# integral of a holomorphic function is equal to $\pi \times f(0,0)$.
8+
# We analyze the function on an $N\times M$ tensor product grid defined by:
9+
# ```math
10+
# \begin{aligned}
11+
# r_n & = \cos\left[(n+\tfrac{1}{2})\pi/2N\right],\quad{\rm for}\quad 0\le n < N,\quad{\rm and}\\
12+
# \theta_m & = 2\pi m/M,\quad{\rm for}\quad 0\le m < M;
13+
# \end{aligned}
14+
# ```
1415
# we convert the function samples to Chebyshev×Fourier coefficients using
1516
# `plan_disk_analysis`; and finally, we transform the Chebyshev×Fourier
16-
# coefficients to disk harmonic coefficients using `plan_disk2cxf`.
17+
# coefficients to Zernike polynomial coefficients using `plan_disk2cxf`.
1718
#
18-
# For the storage pattern of the arrays, please consult the documentation.
19-
#############
19+
# For the storage pattern of the arrays, please consult the
20+
# [documentation](https://MikaelSlevinsky.github.io/FastTransforms).
2021

2122
using FastTransforms, LinearAlgebra
2223

24+
# Our function $f$ on the disk:
2325
f = (x,y) -> (x^2-y^2+1)/((x^2-y^2+1)^2+(2x*y+1)^2)
2426

27+
# The Zernike polynomial degree:
2528
N = 5
2629
M = 4N-3
2730

31+
# The radial grid:
2832
r = [sinpi((N-n-0.5)/(2N)) for n in 0:N-1]
29-
θ = (0:M-1)*2/M # mod π.
33+
34+
# The angular grid (mod $\pi$):
35+
θ = (0:M-1)*2/M
3036

3137
# On the mapped tensor product grid, our function samples are:
3238
F = [f(r*cospi(θ), r*sinpi(θ)) for r in r, θ in θ]
3339

40+
# We precompute a Zernike--Chebyshev×Fourier plan:
3441
P = plan_disk2cxf(F)
42+
43+
# And an FFTW Chebyshev×Fourier analysis plan on the disk:
3544
PA = plan_disk_analysis(F)
3645

3746
# Its Zernike coefficients are:
3847
U = P\(PA*F)
3948

40-
# The Zernike coefficients are useful for integration. The integral of f(x,y)
41-
# over the disk should be π/2 by harmonicity. The coefficient of Z_0^0
42-
# multiplied by √π is:
49+
# The Zernike coefficients are useful for integration. The integral of $f(x,y)$
50+
# over the disk should be $\pi/2$ by harmonicity. The coefficient of $Z_0^0$
51+
# multiplied by `√π` is:
4352
U[1, 1]*sqrt(π)
4453

45-
# Using an orthonormal basis, the integral of [f(x,y)]^2 over the disk is
54+
# Using an orthonormal basis, the integral of $[f(x,y)]^2$ over the disk is
4655
# approximately the square of the 2-norm of the coefficients:
4756
norm(U)^2

examples/nonlocaldiffusion.jl

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,39 @@
1+
# # Nonlocal diffusion on $\mathbb{S}^2$
2+
# This example calculates the spectrum of the nonlocal diffusion operator:
3+
# ```math
4+
# \mathcal{L}_\delta u = \int_{\mathbb{S}^2} \rho_\delta(|\mathbf{x}-\mathbf{y}|)\left[u(\mathbf{x}) - u(\mathbf{y})\right] \,\mathrm{d}\Omega(\mathbf{y}),
5+
# ```
6+
# defined in Eq. (2) of
7+
#
8+
# R. M. Slevinsky, H. Montanelli, and Q. Du, [A spectral method for nonlocal diffusion operators on the sphere](https://doi.org/10.1016/j.jcp.2018.06.024), *J. Comp. Phys.*, **372**:893--911, 2018.
9+
#
10+
# In the above, $0<\delta<2$, $-1<\alpha<1$, and the kernel:
11+
# ```math
12+
# \rho_\delta(|\mathbf{x}-\mathbf{y}|) = \frac{4(1+\alpha)}{\pi \delta^{2+2\alpha}} \frac{\chi_{[0,\delta]}(|\mathbf{x}-\mathbf{y}|)}{|\mathbf{x}-\mathbf{y}|^{2-2\alpha}},
13+
# ```
14+
# where $\chi_I(\cdot)$ is the indicator function on the set $I$.
15+
#
16+
# This nonlocal operator is diagonalized by spherical harmonics:
17+
# ```math
18+
# \mathcal{L}_\delta Y_\ell^m(\mathbf{x}) = \lambda_\ell(\alpha, \delta) Y_\ell^m(\mathbf{x}),
19+
# ```
20+
# and its eigenfunctions are given by the generalized Funk--Hecke formula:
21+
# ```math
22+
# \lambda_\ell(\alpha, \delta) = \frac{(1+\alpha) 2^{2+\alpha}}{\delta^{2+2\alpha}}\int_{1-\delta^2/2}^1 \left[P_\ell(t)-1\right] (1-t)^{\alpha-1} \,\mathrm{d} t.
23+
# ```
24+
# In the paper, the authors use Clenshaw--Curtis quadrature and asymptotic evaluation of Legendre polynomials to achieve $\mathcal{O}(n^2\log n)$ complexity for the evaluation of the first $n$ eigenvalues. With a change of basis, this complexity can be reduced to $\mathcal{O}(n\log n)$.
25+
#
26+
# First, we represent:
27+
# ```math
28+
# P_n(t) - 1 = \sum_{j=0}^{n-1} \left[P_{j+1}(t) - P_j(t)\right] = -\sum_{j=0}^{n-1} (1-t) P_j^{(1,0)}(t).
29+
# ```
30+
# Then, we represent $P_j^{(1,0)}(t)$ with Jacobi polynomials $P_i^{(\alpha,0)}(t)$ and we integrate using [DLMF 18.9.16](https://dlmf.nist.gov/18.9.16):
31+
# ```math
32+
# \int_x^1 P_i^{(\alpha,0)}(t)(1-t)^\alpha\,\mathrm{d}t = \left\{ \begin{array}{cc} \frac{(1-x)^{\alpha+1}}{\alpha+1} & \mathrm{for~}i=0,\\ \frac{1}{2i}(1-x)^{\alpha+1}(1+x)P_{i-1}^{(\alpha+1,1)}(x), & \mathrm{for~}i>0.\end{array}\right.
33+
# ```
34+
# The code below implements this algorithm, making use of the Jacobi--Jacobi transform `plan_jac2jac`.
35+
# For numerical stability, the conversion from Jacobi polynomials $P_j^{(1,0)}(t)$ to $P_i^{(\alpha,0)}(t)$ is divided into conversion from $P_j^{(1,0)}(t)$ to $P_k^{(0,0)}(t)$, before conversion from $P_k^{(0,0)}(t)$ to $P_i^{(\alpha,0)}(t)$.
36+
137
using FastTransforms, LinearAlgebra
238

339
function oprec!(n::Integer, v::AbstractVector, alpha::Real, delta2::Real)
@@ -13,19 +49,6 @@ function oprec!(n::Integer, v::AbstractVector, alpha::Real, delta2::Real)
1349
return v
1450
end
1551

16-
"""
17-
This example calculates the spectrum of the nonlocal diffusion operator:
18-
19-
```math
20-
ℒ_δ u = ∫_𝕊² ρ_δ(|𝐱-𝐲|)[u(𝐱) - u(𝐲)] dΩ(𝐲),
21-
```
22-
23-
defined in Eq. (2) of
24-
25-
R. M. Slevinsky, H. Montanelli, and Q. Du, A spectral method for nonlocal diffusion operators on the sphere, J. Comp. Phys., 372:893--911, 2018.
26-
27-
available at https://doi.org/10.1016/j.jcp.2018.06.024
28-
"""
2952
function evaluate_lambda(n::Integer, alpha::T, delta::T) where T
3053
delta2 = delta*delta
3154
scl = (1+alpha)*(2-delta2/2)
@@ -60,7 +83,11 @@ function evaluate_lambda(n::Integer, alpha::T, delta::T) where T
6083
return lambda
6184
end
6285

63-
lambda = evaluate_lambda(1024, -0.5, 1.0)
64-
lambdabf = evaluate_lambda(1024, parse(BigFloat, "-0.5"), parse(BigFloat, "1.0"))
86+
# The spectrum in `Float64`:
87+
lambda = evaluate_lambda(10, -0.5, 1.0)
88+
89+
# The spectrum in `BigFloat`:
90+
lambdabf = evaluate_lambda(10, parse(BigFloat, "-0.5"), parse(BigFloat, "1.0"))
6591

92+
# The $\infty$-norm relative error:
6693
norm(lambda-lambdabf, Inf)/norm(lambda, Inf)

examples/padua.jl

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1-
#############
1+
# # Padua transform
22
# This demonstrates the Padua transform and inverse transform,
33
# explaining precisely the normalization and points
4-
#############
54

65
using FastTransforms
76

7+
# We define the Padua points and extract Cartesian components:
88
N = 15
99
pts = paduapoints(N)
10-
x = pts[:,1]; y = pts[:,2]
10+
x = pts[:,1]
11+
y = pts[:,2];
1112

13+
# We take the Padua transform of the function:
1214
f = (x,y) -> exp(x + cos(y))
13-
= paduatransform(f.(x , y))
15+
= paduatransform(f.(x , y));
16+
17+
# and use the coefficients to create an approximation to the function $f$:
1418
= (x,y) -> begin
1519
j = 1
1620
ret = 0.0
@@ -21,6 +25,8 @@ f̃ = (x,y) -> begin
2125
ret
2226
end
2327

28+
# At a particular point, is the function well-approximated?
2429
(0.1,0.2) f(0.1,0.2)
2530

31+
# Does the inverse transform bring us back to the grid?
2632
ipaduatransform(f̌) .(x,y)

0 commit comments

Comments
 (0)