|
| 1 | + |
| 2 | +""" |
| 3 | + ClenshawKron(coefficientmatrix, (A₁,A₂), (B₁,B₂), (C₁,C₂), (X₁,X₂))) |
| 4 | +
|
| 5 | +represents the multiplication operator of a tensor product of two orthogonal polynomials. That is, |
| 6 | +if `f(x,y) = P(x)*F*Q(y)'` and `a(x,y) = R(x)*A*S(y)'` then |
| 7 | +
|
| 8 | + M = ClenshawKron(A, tuple.(recurrencecoefficients(R), recurrencecoefficients(S)), (jacobimatrix(P), jacobimatrix(Q)) |
| 9 | + M * KronTrav(F) |
| 10 | +
|
| 11 | +Gives the coefficients of `a(x,y)*f(x,y)`. |
| 12 | +""" |
| 13 | +struct ClenshawKron{T, Coefs<:AbstractMatrix{T}, Rec<:NTuple{2,NTuple{3,AbstractVector}}, Jac<:NTuple{2,AbstractMatrix}} <: AbstractBandedBlockBandedMatrix{T} |
| 14 | + c::Coefs |
| 15 | + recurrencecoeffients::Rec |
| 16 | + X::Jac |
| 17 | +end |
| 18 | + |
| 19 | + |
| 20 | +copy(M::ClenshawKron) = M |
| 21 | +size(M::ClenshawKron) = (ℵ₀, ℵ₀) |
| 22 | +axes(M::ClenshawKron) = (blockedrange(oneto(∞)),blockedrange(oneto(∞))) |
| 23 | +blockbandwidths(M::ClenshawKron) = (size(M.c,1)-1,size(M.c,1)-1) |
| 24 | +subblockbandwidths(M::ClenshawKron) = (size(M.c,2)-1,size(M.c,2)-1) |
| 25 | + |
| 26 | +function square_getindex(M::ClenshawKron, N::Block{1}) |
| 27 | + # Consider P(x) = L^1_x \ 𝐞_0 |
| 28 | + # So that if a(x,y) = P(x)*c*Q(y)' then we have |
| 29 | + # a(X,Y) = 𝐞_0' * inv(L^1_X') * c * Q(Y)' |
| 30 | + # So we first apply 1D clenshaw to each column |
| 31 | + |
| 32 | + (A₁,B₁,C₁), (A₂,B₂,C₂) = M.recurrencecoeffients |
| 33 | + X,Y = M.X |
| 34 | + m,n = size(M.c) |
| 35 | + @assert m == n |
| 36 | + # Apply Clenshaw to each column |
| 37 | + g = (a,b,N) -> LazyBandedMatrices.krontrav(a[1:N,1:N], b[1:N,1:N]) |
| 38 | + cols = [Clenshaw(M.c[1:m-j+1,j], A₁, B₁, C₁, X) for j=1:n] |
| 39 | + |
| 40 | + M = m-2+Int(N) # over sample |
| 41 | + Q_Y = forwardrecurrence(n, A₂, B₂, C₂, Y[1:M,1:M]) |
| 42 | + +(broadcast((a,b,N) -> LazyBandedMatrices.krontrav(a[1:N,1:N], b[1:N,1:N]), Q_Y, cols, Int(N))...) |
| 43 | +end |
| 44 | + |
| 45 | +getindex(M::ClenshawKron, KR::BlockRange{1}, JR::BlockRange{1}) = square_getindex(M, max(maximum(KR), maximum(JR)))[KR,JR] |
| 46 | +getindex(M::ClenshawKron, K::Block{1}, J::Block{1}) = square_getindex(M, max(K, J))[K,J] |
| 47 | +getindex(M::ClenshawKron, Kk::BlockIndex{1}, Jj::BlockIndex{1}) = M[block(Kk), block(Jj)][blockindex(Kk), blockindex(Jj)] |
| 48 | +getindex(M::ClenshawKron, k::Int, j::Int) = M[findblockindex(axes(M,1),k), findblockindex(axes(M,2),j)] |
| 49 | + |
| 50 | +Base.array_summary(io::IO, C::ClenshawKron{T}, inds::Tuple{Vararg{OneToInf{Int}}}) where T = |
| 51 | + print(io, Base.dims2string(length.(inds)), " ClenshawKron{$T} with $(size(C.c)) polynomial") |
0 commit comments