|
| 1 | +export Cone, DuffyCone, LegendreCone |
| 2 | + |
| 3 | +struct Cone <: Domain{Vec{3,Float64}} end |
| 4 | +struct DuffyCone <: Space{Cone,Float64} end |
| 5 | +struct LegendreCone <: Space{Cone,Float64} end |
| 6 | + |
| 7 | +@containsconstants DuffyCone |
| 8 | +@containsconstants LegendreCone |
| 9 | + |
| 10 | +spacescompatible(::DuffyCone, ::DuffyCone) = true |
| 11 | +spacescompatible(::LegendreCone, ::LegendreCone) = true |
| 12 | + |
| 13 | +domain(::DuffyCone) = Cone() |
| 14 | +domain(::LegendreCone) = Cone() |
| 15 | + |
| 16 | +tensorizer(K::DuffyCone) = DiskTensorizer() |
| 17 | +tensorizer(K::LegendreCone) = DiskTensorizer() |
| 18 | + |
| 19 | +rectspace(::DuffyCone) = NormalizedJacobi(0,1,Segment(1,0))*Fourier() |
| 20 | + |
| 21 | +conepolar(t,θ) = Vec(t, t*cos(θ), t*sin(θ)) |
| 22 | +conepolar(tθ) = ((t,θ) = tθ; conepolar(t,θ)) |
| 23 | + |
| 24 | +points(::Cone, n) = conepolar.(points(rectspace(DuffyCone()), n)) |
| 25 | +checkpoints(::Cone) = conepolar.(checkpoints(rectspace(DuffyCone()))) |
| 26 | + |
| 27 | + |
| 28 | +plan_transform(S::DuffyCone, n::AbstractVector) = |
| 29 | + TransformPlan(S, plan_transform(rectspace(S),n), Val{false}) |
| 30 | +plan_itransform(S::DuffyCone, n::AbstractVector) = |
| 31 | + ITransformPlan(S, plan_itransform(rectspace(S),n), Val{false}) |
| 32 | + |
| 33 | +*(P::TransformPlan{<:Any,<:DuffyCone}, v::AbstractArray) = P.plan*v |
| 34 | +*(P::ITransformPlan{<:Any,<:DuffyCone}, v::AbstractArray) = P.plan*v |
| 35 | + |
| 36 | +evaluate(cfs::AbstractVector, S::DuffyCone, txy) = evaluate(cfs, rectspace(S), ipolar(txy[Vec(2,3)])) |
| 37 | +evaluate(cfs::AbstractVector, S::LegendreCone, txy) = evaluate(coefficients(cfs, S, DuffyCone()), DuffyCone(), txy) |
| 38 | + |
| 39 | + |
| 40 | +# function transform(::DuffyCone, v) |
| 41 | +# n = (1 + isqrt(1+8*length(v))) ÷ 4 |
| 42 | +# F = copy(reshape(v,n,2n-1)) |
| 43 | +# Pt = plan_transform(NormalizedJacobi(0,1,Segment(1,0)), n) |
| 44 | +# Pθ = plan_transform(Fourier(), 2n-1) |
| 45 | +# for j = 1:size(F,2) |
| 46 | +# F[:,j] = Pt*F[:,j] |
| 47 | +# end |
| 48 | +# for k = 1:size(F,1) |
| 49 | +# F[k,:] = Pθ * F[k,:] |
| 50 | +# end |
| 51 | +# fromtensor(rectspace(DuffyCone()), F) |
| 52 | +# end |
| 53 | + |
| 54 | +function evaluate(cfs::AbstractVector, S::DuffyCone, txy::Vec{3}) |
| 55 | + t,x,y = txy |
| 56 | + @assert t ≈ sqrt(x^2+y^2) |
| 57 | + θ = atan(y,x) |
| 58 | + Fun(rectspace(S), cfs)(t,θ) |
| 59 | +end |
| 60 | + |
| 61 | + |
| 62 | +function _coefficients(triangleplan, v::AbstractVector{T}, ::DuffyCone, ::LegendreCone) where T |
| 63 | + F = totensor(rectspace(DuffyCone()), v) |
| 64 | + F = pad(F, :, 2size(F,1)-1) |
| 65 | + Fc = F[:,1:2:end] |
| 66 | + c_execute_tri_lo2hi(triangleplan, Fc) |
| 67 | + F[:,1:2:end] .= Fc |
| 68 | + # ignore first column |
| 69 | + Fc[:,2:end] .= F[:,2:2:end] |
| 70 | + c_execute_tri_lo2hi(triangleplan, Fc) |
| 71 | + F[:,2:2:end] .= Fc[:,2:end] |
| 72 | + fromtensor(LegendreCone(), F) |
| 73 | +end |
| 74 | + |
| 75 | +function _coefficients(triangleplan, v::AbstractVector{T}, ::LegendreCone, ::DuffyCone) where T |
| 76 | + F = totensor(LegendreCone(), v) |
| 77 | + F = pad(F, :, 2size(F,1)-1) |
| 78 | + Fc = F[:,1:2:end] |
| 79 | + c_execute_tri_hi2lo(triangleplan, Fc) |
| 80 | + F[:,1:2:end] .= Fc |
| 81 | + # ignore first column |
| 82 | + Fc[:,2:end] .= F[:,2:2:end] |
| 83 | + c_execute_tri_hi2lo(triangleplan, Fc) |
| 84 | + F[:,2:2:end] .= Fc[:,2:end] |
| 85 | + fromtensor(DuffyCone(), F) |
| 86 | +end |
| 87 | + |
| 88 | +function coefficients(cfs::AbstractVector{T}, CD::DuffyCone, ZD::LegendreCone) where T |
| 89 | + c = totensor(rectspace(DuffyCone()), cfs) # TODO: wasteful |
| 90 | + n = size(c,1) |
| 91 | + _coefficients(c_plan_rottriangle(n, zero(T), zero(T), zero(T)), cfs, CD, ZD) |
| 92 | +end |
| 93 | + |
| 94 | +function coefficients(cfs::AbstractVector{T}, ZD::LegendreCone, CD::DuffyCone) where T |
| 95 | + c = tridevec(cfs) # TODO: wasteful |
| 96 | + n = size(c,1) |
| 97 | + _coefficients(c_plan_rottriangle(n, zero(T), zero(T), zero(T)), cfs, ZD, CD) |
| 98 | +end |
| 99 | + |
| 100 | +struct LegendreConeTransformPlan{DUF,CHEB} |
| 101 | + duffyplan::DUF |
| 102 | + triangleplan::CHEB |
| 103 | +end |
| 104 | + |
| 105 | +function LegendreConeTransformPlan(S::LegendreCone, v::AbstractVector{T}) where T |
| 106 | + D = plan_transform(DuffyCone(),v) |
| 107 | + F = totensor(rectspace(DuffyCone()), D*v) # wasteful, just use to figure out `size(F,1)` |
| 108 | + P = c_plan_rottriangle(size(F,1), zero(T), zero(T), zero(T)) |
| 109 | + LegendreConeTransformPlan(D,P) |
| 110 | +end |
| 111 | + |
| 112 | + |
| 113 | +*(P::LegendreConeTransformPlan, v::AbstractVector) = _coefficients(P.triangleplan, P.duffyplan*v, DuffyCone(), LegendreCone()) |
| 114 | + |
| 115 | +plan_transform(K::LegendreCone, v::AbstractVector) = LegendreConeTransformPlan(K, v) |
| 116 | + |
| 117 | +struct LegendreConeITransformPlan{DUF,CHEB} |
| 118 | + iduffyplan::DUF |
| 119 | + triangleplan::CHEB |
| 120 | +end |
| 121 | + |
| 122 | +function LegendreConeITransformPlan(S::LegendreCone, v::AbstractVector{T}) where T |
| 123 | + F = fromtensor(LegendreCone(), v) # wasteful, just use to figure out `size(F,1)` |
| 124 | + P = c_plan_rottriangle(size(F,1), zero(T), zero(T), zero(T)) |
| 125 | + D = plan_itransform(DuffyCone(), _coefficients(P, v, S, DuffyCone())) |
| 126 | + LegendreConeITransformPlan(D,P) |
| 127 | +end |
| 128 | + |
| 129 | + |
| 130 | +*(P::LegendreConeITransformPlan, v::AbstractVector) = P.iduffyplan*_coefficients(P.triangleplan, v, LegendreCone(), DuffyCone()) |
| 131 | + |
| 132 | + |
| 133 | +plan_itransform(K::LegendreCone, v::AbstractVector) = LegendreConeITransformPlan(K, v) |
| 134 | + |
0 commit comments