How to use ApproxFun to multiply differential operators without running into incompatible space issues?

jishnub
Tue, 15 Feb 2022 11:29:36 +0000
Numerics

I’m trying to compute (D + x)^2, where D is the derivative operator.

julia> x = Fun(identity)
Fun(Chebyshev(),[0.0, 1.0])

julia> D = Derivative(Chebyshev())
ConcreteDerivative : Chebyshev() → Ultraspherical(1)
 ⋅  1.0   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   ⋅
 ⋅   ⋅   2.0   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   ⋅
 ⋅   ⋅    ⋅   3.0   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   ⋅
 ⋅   ⋅    ⋅    ⋅   4.0   ⋅    ⋅    ⋅    ⋅    ⋅   ⋅
 ⋅   ⋅    ⋅    ⋅    ⋅   5.0   ⋅    ⋅    ⋅    ⋅   ⋅
 ⋅   ⋅    ⋅    ⋅    ⋅    ⋅   6.0   ⋅    ⋅    ⋅   ⋅
 ⋅   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   7.0   ⋅    ⋅   ⋅
 ⋅   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   8.0   ⋅   ⋅
 ⋅   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   9.0  ⋅
 ⋅   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   ⋱
 ⋅   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   ⋱

julia> D2 = D + x;

julia> D2^2
ERROR: AssertionError: spacescompatible(domainspace(ops[k]), rangespace(ops[k + 1]))

Directly evaluating D2^2 errors, seemingly because the range and domain spaces of D2 differ. However, the conversion from the range space (Ultraspherical(1), or ChebyshevU) to the domain space (Chebyshev) doesn’t appear to not be defined, so this doesn’t work either:

julia> Conversion(rangespace(D2), domainspace(D2))
ERROR: Not implemented
Stacktrace:
 [1] error(s::String)
   @ Base ./error.jl:33
 [2] Conversion(A::Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, B::Chebyshev{ChebyshevInterval{Float64}, Float64})
   @ ApproxFunOrthogonalPolynomials ~/.julia/packages/ApproxFunOrthogonalPolynomials/QcyFy/src/Spaces/Ultraspherical/UltrasphericalOperators.jl:132
 [3] top-level scope
   @ REPL[127]:1

Is there a way to get around this, possibly using some other basis, for which the conversion would be defined? I tried using Ultraspherical(1/2) (Legendre) as the domain space instead of Chebyshev, but that doesn’t seem to work either:

julia> x = Fun(identity, S)
Fun(Ultraspherical(0.5),[-0.0, 1.0, -0.0, -0.0])

julia> D = Derivative(S)
ConcreteDerivative : Ultraspherical(0.5) → Ultraspherical(1.5)
 ⋅  1.0   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   ⋅
 ⋅   ⋅   1.0   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   ⋅
 ⋅   ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   ⋅
 ⋅   ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅    ⋅   ⋅
 ⋅   ⋅    ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅    ⋅   ⋅
 ⋅   ⋅    ⋅    ⋅    ⋅    ⋅   1.0   ⋅    ⋅    ⋅   ⋅
 ⋅   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   1.0   ⋅    ⋅   ⋅
 ⋅   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   1.0   ⋅   ⋅
 ⋅   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   1.0  ⋅
 ⋅   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   ⋱
 ⋅   ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅    ⋅   ⋱

julia> Conversion(rangespace(D2), domainspace(D2))
ERROR: Not implemented
Stacktrace:
 [1] error(s::String)
   @ Base ./error.jl:33
 [2] Conversion(A::Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, B::Chebyshev{ChebyshevInterval{Float64}, Float64})
   @ ApproxFunOrthogonalPolynomials ~/.julia/packages/ApproxFunOrthogonalPolynomials/QcyFy/src/Spaces/Ultraspherical/UltrasphericalOperators.jl:132
 [3] top-level scope
   @ REPL[132]:1

Maybe I’m doing something wrong here, but my eventual goal is to obtain the operator

D2^2 = D^2 + 2xD + x^2 + 1

3 posts - 2 participants