Skip to content

Commit ef98b07

Browse files
committed
2 parents 40d79d7 + 3166b2d commit ef98b07

File tree

8 files changed

+905
-1726
lines changed

8 files changed

+905
-1726
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ os:
55
- osx
66
- windows
77
julia:
8-
- 1.4
8+
- 1.5
99
- nightly
1010
matrix:
1111
allow_failures:

Project.toml

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

55
[deps]
6-
ApproxFun = "28f2ccd6-bb30-5033-b560-165f7b14dc2f"
7-
ApproxFunBase = "fbd15aa5-315a-5a7d-a8a4-24992e37be05"
8-
ApproxFunFourier = "59844689-9c9d-51bf-9583-5b794ec66d30"
9-
ApproxFunOrthogonalPolynomials = "b70543e2-c0d9-56b8-a290-0d4d6d4de211"
106
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"
117
BandedMatrices = "aae01518-5342-5314-be14-df237901396f"
128
BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e"
139
BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0"
10+
ContinuumArrays = "7ae1f121-cc2c-504b-ac30-9b923412ae5c"
1411
DomainSets = "5b8099bc-c8ec-5219-889f-1d9e522a28bf"
15-
FastGaussQuadrature = "442a2c76-b920-505d-bb47-c5924d526838"
1612
FastTransforms = "057dd010-8810-581a-b7be-e3fc3b93f78c"
1713
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
1814
InfiniteArrays = "4858937d-0d70-526a-a4dd-2d5cb5dd786c"
19-
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
15+
InfiniteLinearAlgebra = "cde9dba0-b1de-11e9-2c62-0bab9446c55c"
2016
LazyArrays = "5078a376-72f3-5289-bfd5-ec5146d43c02"
21-
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
17+
LazyBandedMatrices = "d7e5e226-e90b-4449-9968-0f923699bf6f"
2218
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
23-
Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a"
24-
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
25-
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
26-
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
19+
OrthogonalPolynomialsQuasi = "aa41a628-2c43-45df-899b-83ab96621781"
20+
QuasiArrays = "c4ea9172-b204-11e9-377d-29865faadc5c"
2721
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
2822
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
2923
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
3024

3125
[compat]
32-
ApproxFun = "0.11, 0.12"
33-
ApproxFunBase = "0.3"
34-
ApproxFunFourier = "0.2"
35-
ApproxFunOrthogonalPolynomials = "0.3"
36-
ArrayLayouts = "0.1, 0.2, 0.3, 0.4"
37-
BandedMatrices = "0.14, 0.15"
38-
BlockArrays = "0.11, 0.12"
39-
BlockBandedMatrices = "0.7, 0.8"
40-
DomainSets = "0.1, 0.2, 0.3"
41-
FastGaussQuadrature = "0.4"
42-
FastTransforms = "0.8, 0.9, 0.11"
43-
FillArrays = "0.8, 0.9, 0.10"
44-
InfiniteArrays = "0.6, 0.7"
45-
LazyArrays = "0.14, 0.15, 0.16, 0.18, 0.19"
46-
Makie = "0.10, 0.11"
47-
RecipesBase = "0.5, 0.6, 0.7, 1"
48-
SpecialFunctions = "0.7, 0.8, 0.9, 0.10, 1.0"
49-
StaticArrays = "0.11, 0.12, 1.0"
50-
julia = "1.3"
26+
ArrayLayouts = "0.5.1"
27+
BandedMatrices = "0.16"
28+
BlockArrays = "0.14.1"
29+
BlockBandedMatrices = "0.10"
30+
ContinuumArrays = "0.4"
31+
DomainSets = "0.4"
32+
FastTransforms = "0.11"
33+
FillArrays = "0.11"
34+
InfiniteArrays = "0.9"
35+
InfiniteLinearAlgebra = "0.4.5"
36+
LazyArrays = "0.20"
37+
LazyBandedMatrices = "0.4"
38+
OrthogonalPolynomialsQuasi = "0.4"
39+
SpecialFunctions = "0.10, 1"
40+
StaticArrays = "0.12, 1"
41+
julia = "1.5"

README.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,21 @@
33
[![Build Status](https://travis-ci.org/JuliaApproximation/MultivariateOrthogonalPolynomials.jl.svg?branch=master)](https://travis-ci.org/JuliaApproximation/MultivariateOrthogonalPolynomials.jl)
44

55
This is an experimental package to add support for multivariate orthogonal polynomials on disks, spheres, triangles, and other simple
6-
geometries to [ApproxFun.jl](https://github.com/JuliaApproximation/ApproxFun.jl). At the moment it primarily supports triangles. For example,
6+
geometries to [ContinuumArrays.jl](https://github.com/JuliaApproximation/ContinuumArrays.jl). At the moment it primarily supports triangles. For example,
77
we can solve variable coefficient Helmholtz on the triangle with zero Dirichlet conditions as follows:
88
```julia
9-
using ApproxFun, MultivariateOrthogonalPolynomials
10-
x,y = Fun(Triangle())
11-
Δ = Laplacian() : TriangleWeight(1.0,1.0,1.0,JacobiTriangle(1.0,1.0,1.0))
12-
V = x*y^2
13-
L = Δ + 200^2*V
14-
u = \(L, ones(Triangle()); tolerance=1E-5)
9+
julia> using MultivariateOrthogonalPolynomials, StaticArrays, LinearAlgebra
10+
11+
julia> P = JacobiTriangle()
12+
JacobiTriangle(0, 0, 0)
13+
14+
julia> x,y = first.(axes(P,1)), last.(axes(P,1));
15+
16+
julia> u = P * (P \ (exp.(x) .* cos.(y))) # Expand in Triangle OPs
17+
JacobiTriangle(0, 0, 0) * [1.3365085377830084, 0.5687967596428205, -0.22812040274224554, 0.07733064070637755, 0.016169744493985644, -0.08714886622738759, 0.00338435674992512, 0.01220019521126353, -0.016867598915573725, 0.003930461395801074 ]
18+
19+
julia> u[SVector(0.1,0.2)] # Evaluate expansion
20+
1.083141079608063
1521
```
1622
See the examples folder for more examples, including non-zero Dirichlet conditions, Neumann conditions, and piecing together multiple triangles. In particular, the [examples](examples/triangleexamples.jl) from Olver, Townsend & Vasil 2019.
1723

Lines changed: 114 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,137 @@
11
module MultivariateOrthogonalPolynomials
2-
using Base, RecipesBase, ApproxFun, BandedMatrices, BlockArrays, BlockBandedMatrices,
3-
FastTransforms, FastGaussQuadrature, StaticArrays, FillArrays,
4-
LinearAlgebra, Libdl, SpecialFunctions, LazyArrays, InfiniteArrays,
5-
DomainSets, ArrayLayouts
2+
using OrthogonalPolynomialsQuasi, FastTransforms, BlockBandedMatrices, BlockArrays, DomainSets,
3+
QuasiArrays, StaticArrays, ContinuumArrays, InfiniteArrays, InfiniteLinearAlgebra,
4+
LazyArrays, SpecialFunctions, LinearAlgebra, BandedMatrices, LazyBandedMatrices, ArrayLayouts
65

7-
# package code goes here
8-
import Base: values,getindex,setindex!,*, +, -, ==,<,<=,>,
9-
>=,/,^,\,,transpose, in, convert, issubset
6+
import Base: axes, in, ==, *, ^, \, copy, OneTo, getindex, size
7+
import DomainSets: boundary
108

9+
import QuasiArrays: LazyQuasiMatrix, LazyQuasiArrayStyle
10+
import ContinuumArrays: @simplify, Weight, grid, TransformFactorization, Expansion
1111

12-
import BandedMatrices: inbands_getindex, inbands_setindex!
12+
import BlockArrays: block, blockindex, BlockSlice, viewblock
13+
import BlockBandedMatrices: _BandedBlockBandedMatrix
14+
import LinearAlgebra: factorize
15+
import LazyArrays: arguments, paddeddata
1316

14-
import BlockArrays: getblock, Block, blocksize
17+
import OrthogonalPolynomialsQuasi: jacobimatrix
1518

16-
import BlockBandedMatrices: blockbandwidths, subblockbandwidths
19+
export Triangle, JacobiTriangle, TriangleWeight, WeightedTriangle, PartialDerivative, Laplacian, MultivariateOrthogonalPolynomial, BivariateOrthogonalPolynomial
1720

18-
# ApproxFun general import
19-
import ApproxFunBase: BandedMatrix,
20-
linesum,complexlength, BandedBlockBandedMatrix,
21-
real, eps, isapproxinteger, FiniteRange, DFunction,
22-
TransformPlan, ITransformPlan, plan_transform!
21+
#########
22+
# PartialDerivative{k}
23+
# takes a partial derivative in the k-th index.
24+
#########
25+
26+
27+
struct PartialDerivative{k,T,Ax<:Inclusion} <: LazyQuasiMatrix{T}
28+
axis::Ax
29+
end
30+
31+
PartialDerivative{k,T}(axis::Inclusion) where {k,T} = PartialDerivative{k,T,typeof(axis)}(axis)
32+
PartialDerivative{k,T}(domain) where {k,T} = PartialDerivative{k,T}(Inclusion(domain))
33+
PartialDerivative{k}(axis) where k = PartialDerivative{k,eltype(eltype(axis))}(axis)
2334

24-
# Domains import
25-
import ApproxFunBase: fromcanonical, tocanonical, domainscompatible
35+
axes(D::PartialDerivative) = (D.axis, D.axis)
36+
==(a::PartialDerivative{k}, b::PartialDerivative{k}) where k = a.axis == b.axis
37+
copy(D::PartialDerivative{k}) where k = PartialDerivative{k}(copy(D.axis))
2638

27-
# Operator import
28-
import ApproxFunBase: bandwidths,SpaceOperator, ConversionWrapper, DerivativeWrapper,
29-
rangespace, domainspace, InterlaceOperator,
30-
promotedomainspace, CalculusOperator, interlace, Multiplication,
31-
choosedomainspace, SubOperator, ZeroOperator,
32-
Dirichlet, DirichletWrapper, Neumann, Laplacian, ConstantTimesOperator, Conversion,
33-
Derivative, ConcreteMultiplication, ConcreteConversion, ConcreteLaplacian,
34-
ConcreteDerivative, TimesOperator, MultiplicationWrapper, TridiagonalOperator
39+
struct Laplacian{T,D} <: LazyQuasiMatrix{T}
40+
axis::Inclusion{T,D}
41+
end
3542

43+
Laplacian{T}(axis::Inclusion{<:Any,D}) where {T,D} = Laplacian{T,D}(axis)
44+
Laplacian{T}(domain) where T = Laplacian{T}(Inclusion(domain))
45+
Laplacian(axis) = Laplacian{eltype(axis)}(axis)
3646

37-
# Spaces import
38-
import ApproxFunBase: ConstantSpace, NoSpace, prectype,
39-
SumSpace,PiecewiseSpace, ArraySpace, @containsconstants,
40-
UnsetSpace, canonicalspace, canonicaldomain, domain, evaluate,
41-
AnyDomain, plan_transform,plan_itransform,
42-
transform,itransform,transform!,itransform!,
43-
isambiguous, fromcanonical, tocanonical, checkpoints, ∂, spacescompatible,
44-
mappoint, UnivariateSpace, setdomain, setcanonicaldomain, canonicaldomain,
45-
Space, points, space, conversion_rule, maxspace_rule,
46-
union_rule, coefficients, RealUnivariateSpace, PiecewiseSegment, rangetype, cfstype
47+
axes(D::Laplacian) = (D.axis, D.axis)
48+
==(a::Laplacian, b::Laplacian) = a.axis == b.axis
49+
copy(D::Laplacian) = Laplacian(copy(D.axis), D.k)
4750

48-
# Multivariate import
49-
import ApproxFunBase: DirectSumSpace, AbstractProductSpace, factor,
50-
BivariateFun, ProductFun, LowRankFun, lap, columnspace,
51-
fromtensor, totensor, isbandedblockbanded,
52-
Tensorizer, tensorizer, block, blockstart, blockstop, blocklengths,
53-
domaintensorizer, rangetensorizer, blockrange, BlockRange1,
54-
float
51+
^(D::PartialDerivative, k::Integer) = ApplyQuasiArray(^, D, k)
52+
^(D::Laplacian, k::Integer) = ApplyQuasiArray(^, D, k)
5553

56-
# Singularities
57-
import ApproxFunBase: WeightSpace, weight
5854

59-
# Vec is for two points
60-
import ApproxFunBase: Vec
55+
abstract type MultivariateOrthogonalPolynomial{d,T} <: Basis{T} end
56+
const BivariateOrthogonalPolynomial{T} = MultivariateOrthogonalPolynomial{2,T}
57+
const BlockOneTo = BlockRange{1,Tuple{OneTo{Int}}}
6158

62-
# Jacobi import
63-
import ApproxFunOrthogonalPolynomials: jacobip, JacobiSD, PolynomialSpace, order
6459

65-
import ApproxFunFourier: polar, ipolar
60+
getindex(P::MultivariateOrthogonalPolynomial{<:Any,D}, xy::SVector{D}, JR::BlockOneTo) where D =
61+
error("Overload")
62+
getindex(P::MultivariateOrthogonalPolynomial{D}, xy::SVector{D}, J::Block{1}) where D = P[xy, Block.(OneTo(Int(J)))][J]
63+
getindex(P::MultivariateOrthogonalPolynomial{D}, xy::SVector{D}, JR::BlockRange{1}) where D = P[xy, Block.(OneTo(Int(maximum(JR))))][JR]
64+
getindex(P::MultivariateOrthogonalPolynomial{D}, xy::SVector{D}, Jj::BlockIndex{1}) where D = P[xy, block(Jj)][blockindex(Jj)]
65+
getindex(P::MultivariateOrthogonalPolynomial{D}, xy::SVector{D}, j::Integer) where D = P[xy, findblockindex(axes(P,2), j)]
66+
getindex(P::MultivariateOrthogonalPolynomial{D}, xy::SVector{D}, jr::AbstractVector) where D = P[xy, Block.(OneTo(Int(findblock(axes(P,2), maximum(jr)))))][jr]
6667

68+
const FirstInclusion = BroadcastQuasiVector{<:Any, typeof(first), <:Tuple{Inclusion}}
69+
const LastInclusion = BroadcastQuasiVector{<:Any, typeof(last), <:Tuple{Inclusion}}
6770

68-
include("Triangle/Triangle.jl")
69-
include("Disk/Disk.jl")
70-
include("Cone/Cone.jl")
71+
function Base.broadcasted(::LazyQuasiArrayStyle{2}, ::typeof(*), x::FirstInclusion, P::BivariateOrthogonalPolynomial)
72+
axes(x,1) == axes(P,1) || throw(DimensionMismatch())
73+
P*jacobimatrix(Val(1), P)
74+
end
75+
76+
function Base.broadcasted(::LazyQuasiArrayStyle{2}, ::typeof(*), x::LastInclusion, P::BivariateOrthogonalPolynomial)
77+
axes(x,1) == axes(P,1) || throw(DimensionMismatch())
78+
P*jacobimatrix(Val(2), P)
79+
end
80+
81+
"""
82+
forwardrecurrence!(v, A, B, C, (x,y))
83+
84+
evaluates the bivaraite orthogonal polynomials at points `(x,y)` ,
85+
where `A`, `B`, and `C` are `AbstractVector`s containing the recurrence coefficients
86+
matrices. In particular, note that for any OPs we have
87+
88+
P[N+1,x] = (A[N]* [x*I; y*I] + B[N]) * P[N,x] - C[N] * P[N-1,x]
89+
90+
where A[N] is (N+1) x 2N, B[N] and C[N] are (N+1) x N.
91+
92+
"""
93+
# function forwardrecurrence!(v::AbstractBlockVector{T}, A::AbstractVector, B::AbstractVector, C::AbstractVector, xy) where T
94+
# N = blocklength(v)
95+
# N == 0 && return v
96+
# length(A)+1 ≥ N && length(B)+1 ≥ N && length(C)+1 ≥ N || throw(ArgumentError("A, B, C must contain at least $(N-1) entries"))
97+
# v[Block(1)] .= one(T)
98+
# N = 1 && return v
99+
# p_1 = view(v,Block(2))
100+
# p_0 = view(v,Block(1))
101+
# mul!(p_1, B[1], p_0)
102+
# xy_muladd!(xy, A[1], p_0, one(T), p_1)
71103

72-
include("clenshaw.jl")
104+
# @inbounds for n = 2:N-1
105+
# p_2 = view(v,Block(n+1))
106+
# mul!(p_2, B[n], p_1)
107+
# xy_muladd!(xy, A[n], p_1, one(T), p_2)
108+
# muladd!(-one(T), C[n], p_0, one(T), p_2)
109+
# p_1,p_0 = p_2,p_1
110+
# end
111+
# v
112+
# end
73113

74-
# include("Sphere/SphericalHarmonics.jl")
75114

76-
include("show.jl")
77-
include("plot.jl")
115+
# forwardrecurrence(N::Block{1}, A::AbstractVector, B::AbstractVector, C::AbstractVector, xy) =
116+
# forwardrecurrence!(PseudoBlockVector{promote_type(eltype(eltype(A)),eltype(eltype(B)),eltype(eltype(C)),eltype(xy))}(undef, 1:Int(N)), A, B, C, xy)
117+
118+
# use block expansion
119+
ContinuumArrays.transform_ldiv(V::SubQuasiArray{<:Any,2,<:BivariateOrthogonalPolynomial,<:Tuple{Inclusion,BlockSlice{BlockOneTo}}}, B, _) =
120+
factorize(V) \ B
121+
function ContinuumArrays.transform_ldiv(V::SubQuasiArray{<:Any,2,<:BivariateOrthogonalPolynomial,<:Tuple{Inclusion,AbstractVector{Int}}}, B, _)
122+
P = parent(V)
123+
_,jr = parentindices(V)
124+
J = findblock(axes(P,2),maximum(jr))
125+
(P[:,Block.(OneTo(Int(J)))] \ B)[jr]
126+
end
127+
128+
# Make sure block structure matches. Probably should do this for all block mul
129+
LazyArrays.mul(A::MultivariateOrthogonalPolynomial, b::AbstractVector) =
130+
ApplyQuasiArray(*, A, PseudoBlockVector(b, (axes(A,2),)))
131+
132+
133+
134+
include("Triangle/Triangle.jl")
135+
78136

79137
end # module

0 commit comments

Comments
 (0)