Skip to content

Commit d9a7601

Browse files
authored
Ideal Fluid Flow off an interval (#43)
* Add IdealFluidFlow example * Update test_stieltjes.jl * tests fixed * Add sum and hilbert special case * Update Project.toml * increase coverafge * increase coverage * increase coverage
1 parent 7aa3538 commit d9a7601

13 files changed

+142
-18
lines changed

Project.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ LazyArrays = "5078a376-72f3-5289-bfd5-ec5146d43c02"
2222
LazyBandedMatrices = "d7e5e226-e90b-4449-9968-0f923699bf6f"
2323
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
2424
QuasiArrays = "c4ea9172-b204-11e9-377d-29865faadc5c"
25+
SemiseparableMatrices = "f8ebbe35-cbfb-4060-bf7f-b10e4670cf57"
2526
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
2627

2728
[compat]
@@ -36,11 +37,11 @@ FastGaussQuadrature = "0.4.3"
3637
FastTransforms = "0.12"
3738
FillArrays = "0.11"
3839
HypergeometricFunctions = "0.3.4"
39-
InfiniteArrays = "0.10.3"
40-
InfiniteLinearAlgebra = "0.5.3"
40+
InfiniteArrays = "0.11.1"
41+
InfiniteLinearAlgebra = "0.5.8"
4142
IntervalSets = "0.5"
4243
LazyArrays = "0.21"
43-
LazyBandedMatrices = "0.5.5"
44+
LazyBandedMatrices = "0.6"
4445
QuasiArrays = "0.6"
4546
SpecialFunctions = "1.0"
4647
julia = "1.6"

examples/idealfluidflow.jl

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using ClassicalOrthogonalPolynomials, Plots
2+
3+
##
4+
# Ideal fluid flow consists of level sets of the imagainary part of a function
5+
# that is asymptotic to c*z and whose imaginary part vanishes on Γ
6+
#
7+
#
8+
# On the unit interval, -2*H*u gives the imaginary part of cauchy(u,x)
9+
# So if we want to find u defined on Γ so that hilbert(u,x) = imag(c*x)
10+
# then c*z + 2cauchy(u,z) vanishes on Γ
11+
##
12+
13+
T = ChebyshevT()
14+
U = ChebyshevU()
15+
x = axes(U,1)
16+
H = inv.(x .- x')
17+
18+
c = exp(0.5im)
19+
20+
21+
u = Weighted(U) * ((H * Weighted(U)) \ imag(c * x))
22+
23+
ε = eps(); (inv.(0.1+ε*im .- x') * u + inv.(0.1-ε*im .- x') * u)/2 imag(c*0.1)
24+
ε = eps(); real(inv.(0.1+ε*im .- x') * u ) imag(c*0.1)
25+
26+
v = (s,t) -> (z = (s + im*t); imag(c*z) - real(inv.(z .- x') * u))
27+
28+
29+
xx = range(-3,3; length=100)
30+
yy = range(-1,1; length=100)
31+
plot([-1,1],[0,0]; color=:black)
32+
contour!(xx,yy,v.(xx',yy))
Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
1-
using ClassicalOrthogonalPolynomials, Plots
1+
using ClassicalOrthogonalPolynomials, Plots, Test
2+
3+
###
4+
# We can solve ODEs like the Airy equation
5+
#
6+
# u(-1) = airyai(-1)
7+
# u(1) = airyai(1)
8+
# u'' = x * u
9+
#
10+
# using the ultraspherical spectral method.
211

312
T = Chebyshev()
413
C = Ultraspherical(2)
5-
D = Derivative(axes(T,1))
6-
A = (C\(D^2*T))+100(C\T)
14+
x = axes(T,1)
15+
D = Derivative(x)
716

8-
c = Vcat(T[[-1,1],:], A) \ [1;2;zeros(∞)]
17+
c = [T[[begin,end],:]; C \ (D^2 * T - x .* T)] \ [airyai(-1); airyai(1); zeros(∞)]
918
u = T*c
1019

20+
@test u[0.0] airyai(0.0)
1121
plot(u)

src/ClassicalOrthogonalPolynomials.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import QuasiArrays: cardinality, checkindex, QuasiAdjoint, QuasiTranspose, Inclu
2525
QuasiDiagonal, MulQuasiArray, MulQuasiMatrix, MulQuasiVector, QuasiMatMulMat,
2626
ApplyQuasiArray, ApplyQuasiMatrix, LazyQuasiArrayApplyStyle, AbstractQuasiArrayApplyStyle,
2727
LazyQuasiArray, LazyQuasiVector, LazyQuasiMatrix, LazyLayout, LazyQuasiArrayStyle,
28-
_getindex, layout_getindex, _factorize
28+
_getindex, layout_getindex, _factorize, AbstractQuasiArray, AbstractQuasiMatrix, AbstractQuasiVector
2929

3030
import InfiniteArrays: OneToInf, InfAxes, Infinity, AbstractInfUnitRange, InfiniteCardinal, InfRanges
3131
import ContinuumArrays: Basis, Weight, basis, @simplify, Identity, AbstractAffineQuasiVector, ProjectionFactorization,
@@ -59,7 +59,8 @@ include("interlace.jl")
5959
cardinality(::FullSpace{<:AbstractFloat}) = ℵ₁
6060
cardinality(::EuclideanDomain) = ℵ₁
6161

62-
transform_ldiv(A, f, ::Tuple{<:Any,InfiniteCardinal{0}}) = adaptivetransform_ldiv(A, f)
62+
transform_ldiv(A::AbstractQuasiArray{T}, f::AbstractQuasiArray{V}, ::Tuple{<:Any,InfiniteCardinal{0}}) where {T,V} =
63+
adaptivetransform_ldiv(convert(AbstractQuasiArray{promote_type(T,V)}, A), f)
6364

6465
function chop!(c::AbstractVector, tol::Real)
6566
@assert tol >= 0
@@ -279,7 +280,7 @@ _tritrunc(X, n) = _tritrunc(MemoryLayout(X), X, n)
279280
jacobimatrix(V::SubQuasiArray{<:Any,2,<:Any,<:Tuple{Inclusion,OneTo}}) =
280281
_tritrunc(jacobimatrix(parent(V)), maximum(parentindices(V)[2]))
281282

282-
grid(P::SubQuasiArray{<:Any,2,<:OrthogonalPolynomial,<:Tuple{Inclusion,AbstractUnitRange}}) =
283+
grid(P::SubQuasiArray{<:Any,2,<:OrthogonalPolynomial,<:Tuple{Inclusion,Any}}) =
283284
eigvals(symtridiagonalize(jacobimatrix(P)))
284285

285286
function golubwelsch(X)

src/classical/chebyshev.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ on -1..1.
2222
struct Chebyshev{kind,T} <: AbstractJacobi{T} end
2323
Chebyshev{kind}() where kind = Chebyshev{kind,Float64}()
2424

25+
AbstractQuasiArray{T}(::Chebyshev{kind}) where {T,kind} = Chebyshev{kind,T}()
26+
AbstractQuasiMatrix{T}(::Chebyshev{kind}) where {T,kind} = Chebyshev{kind,T}()
2527

2628
const WeightedChebyshev{kind,T} = WeightedBasis{T,<:ChebyshevWeight{kind},<:Chebyshev{kind}}
2729

src/classical/jacobi.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,12 +204,12 @@ summary(io::IO, P::Jacobi) = print(io, "Jacobi($(P.a), $(P.b))")
204204
# transforms
205205
###
206206

207-
function grid(Pn::SubQuasiArray{T,2,<:AbstractJacobi,<:Tuple{Inclusion,AbstractUnitRange}}) where T
207+
function grid(Pn::SubQuasiArray{T,2,<:AbstractJacobi,<:Tuple{Inclusion,Any}}) where T
208208
kr,jr = parentindices(Pn)
209209
ChebyshevGrid{1,T}(maximum(jr))
210210
end
211211

212-
function plotgrid(Pn::SubQuasiArray{T,2,<:AbstractJacobi,<:Tuple{Inclusion,AbstractUnitRange}}) where T
212+
function plotgrid(Pn::SubQuasiArray{T,2,<:AbstractJacobi,<:Tuple{Inclusion,Any}}) where T
213213
kr,jr = parentindices(Pn)
214214
ChebyshevGrid{2,T}(40maximum(jr))
215215
end

src/clenshaw.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ Base.unsafe_getindex(P::OrthogonalPolynomial, x::Number, ::Colon) = Base.unsafe_
8080
Base.unsafe_getindex(P::OrthogonalPolynomial, x::Number, n::Number) = Base.unsafe_getindex(P,x,oneto(n))[end]
8181

8282
getindex(P::OrthogonalPolynomial, x::Number, jr::AbstractInfUnitRange{Int}) = view(P, x, jr)
83+
getindex(P::OrthogonalPolynomial, x::AbstractVector, jr::AbstractInfUnitRange{Int}) = view(P, x, jr)
8384
Base.unsafe_getindex(P::OrthogonalPolynomial{T}, x::Number, jr::AbstractInfUnitRange{Int}) where T =
8485
BroadcastVector{T}(Base.unsafe_getindex, Ref(P), x, jr)
8586

src/normalized.jl

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ QuasiArrays.ApplyQuasiArray(Q::Normalized) = ApplyQuasiArray(*, arguments(ApplyL
8383

8484
ArrayLayouts.mul(Q::Normalized, C::AbstractArray) = ApplyQuasiArray(*, Q, C)
8585

86-
grid(Q::SubQuasiArray{<:Any,2,<:Normalized}) = grid(view(parent(Q).P, parentindices(Q)...))
86+
grid(Q::SubQuasiArray{<:Any,2,<:Normalized,<:Tuple{Inclusion,Any}}) = grid(view(parent(Q).P, parentindices(Q)...))
87+
plotgrid(Q::SubQuasiArray{<:Any,2,<:Normalized,<:Tuple{Inclusion,Any}}) = plotgrid(view(parent(Q).P, parentindices(Q)...))
8788

8889
# transform_ldiv(Q::Normalized, C::AbstractQuasiArray) = Q.scaling .\ (Q.P \ C)
8990
function transform_ldiv(Q::Normalized, C::AbstractQuasiArray)
@@ -215,3 +216,10 @@ broadcasted(::LazyQuasiArrayStyle{2}, ::typeof(*), x::Inclusion, Q::Weighted) =
215216
summary(io::IO, Q::Weighted) = print(io, "Weighted($(Q.P))")
216217

217218
__sum(::NormalizedBasisLayout, A, dims) = __sum(ApplyLayout{typeof(*)}(), A, dims)
219+
function __sum(::WeightedOPLayout, A, dims)
220+
@assert dims == 1
221+
Hcat(sum(weight(A)), Zeros{eltype(A)}(1,∞))
222+
end
223+
224+
_sum(p::SubQuasiArray{T,1,<:Weighted,<:Tuple{Inclusion,Int}}, ::Colon) where T =
225+
parentindices(p)[2] == 1 ? convert(T, sum(weight(parent(p)))) : zero(T)

src/stieltjes.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,9 +143,20 @@ end
143143
w = orthogonalityweight(P)
144144
X = jacobimatrix(P)
145145
z, x = parent(S).args[1].args
146+
z in axes(P,1) && transpose((inv.(x .- x') * wP)[z,:])
146147
transpose((X'-z*I) \ [-sum(w)*_p0(P); zeros(∞)])
147148
end
148149

150+
sqrtx2(z::Number) = sqrt(z-1)*sqrt(z+1)
151+
sqrtx2(x::Real) = sign(x)*sqrt(x^2-1)
152+
153+
@simplify function *(S::StieltjesPoint, wP::Weighted{<:Any,<:ChebyshevU})
154+
z, x = parent(S).args[1].args
155+
z in axes(wP,1) && transpose((inv.(x .- x') * wP)[z,:])
156+
ξ = inv(z + sqrtx2(z))
157+
transpose(π * ξ.^oneto(∞))
158+
end
159+
149160

150161
@simplify function *(S::StieltjesPoint, wT::SubQuasiArray{<:Any,2,<:Any,<:Tuple{<:AbstractAffineQuasiVector,<:Any}})
151162
P = parent(wT)

test/test_chebyshev.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ import ContinuumArrays: MappedWeightedBasisLayout, Map
3232
@test axes(T[1:1,:]) === (oneto(1), oneto(∞))
3333
@test T[1:1,:][:,1:5] == ones(1,5)
3434
@test T[0.1,:][1:10] T[0.1,1:10] (T')[1:10,0.1]
35+
36+
@testset "inf-range-indexing" begin
37+
@test T[[begin,end],2:∞][:,2:5] == T[[-1,1],3:6]
38+
end
3539
end
3640

3741
@testset "U" begin
@@ -136,6 +140,9 @@ import ContinuumArrays: MappedWeightedBasisLayout, Map
136140
@test WT \ (exp.(x) ./ sqrt.(1 .- x.^2)) wT \ (exp.(x) ./ sqrt.(1 .- x.^2))
137141
@test WT[:,1:20] \ (exp.(x) ./ sqrt.(1 .- x.^2)) (WT \ (exp.(x) ./ sqrt.(1 .- x.^2)))[1:20]
138142
@test WT \ (x .* WT) == T \ (x .* T)
143+
@test sum(WT; dims=1)[:,1:10] zeros(1,9)]
144+
@test sum(WT[:,1]) π
145+
@test iszero(sum(WT[:,2]))
139146
end
140147

141148
@testset "mapped" begin
@@ -359,6 +366,11 @@ import ContinuumArrays: MappedWeightedBasisLayout, Map
359366
@testset "plot" begin
360367
@test ContinuumArrays.plotgrid(ChebyshevT()[:,1:5]) == ChebyshevGrid{2}(200)
361368
end
369+
370+
@testset "conversion" begin
371+
T = ChebyshevT()
372+
@test ChebyshevT{ComplexF64}() convert(AbstractQuasiArray{ComplexF64}, T) convert(AbstractQuasiMatrix{ComplexF64}, T)
373+
end
362374
end
363375

364376
struct QuadraticMap{T} <: Map{T} end

0 commit comments

Comments
 (0)