In-place SciMLOperators

Hello :grinning:,
Can anyone tell me more about SciMLOperators.jl’s in-place operations?

using SciMLOperators
using BenchmarkTools

function Afunc!(w,v,u,p,t)
    w[1] = -2v[1] + v[2]
    for i in 2:4
        w[i] = v[i-1] - 2v[i] + v[i+1]
    end
    w[5] = v[4] - 2v[5]
    nothing
end

function Afunc!(v,u,p,t)
    w = zeros(5)
    Afunc!(w,v,u,p,t)
    w
end

mfopA = FunctionOperator(Afunc!, zeros(5), zeros(5), isinplace=true, outofplace=false, isconstant=true, islinear=true)
res = zeros(5)
v = rand(5)
@btime mfopA * v
@btime mul!(res, mfopA, v)
@btime res = mfopA(v, nothing, nothing, nothing)

give the following results:

julia> @btime mfopA * v
  26.439 ns (2 allocations: 96 bytes)
5-element Vector{Float64}:
  0.11998935724715909
 -0.8311223582350354
  0.462012816005153
 -0.0787003727323099
  0.05822953891971461

julia> @btime mul!(res, mfopA, v)
  13.179 ns (0 allocations: 0 bytes)
5-element Vector{Float64}:
  0.11998935724715909
 -0.8311223582350354
  0.462012816005153
 -0.0787003727323099
  0.05822953891971461

julia> @btime res = mfopA(v, nothing, nothing, nothing)
  30.402 ns (3 allocations: 272 bytes)
5-element Vector{Float64}:
  0.11998935724715909
 -0.8311223582350354
  0.462012816005153
 -0.0787003727323099
  0.05822953891971461

So the only in-place non allocating version is mul!(res, mfopA, v).
My questions are:

  • Why/when should I indicate isinplace=true in the FunctionOperator definition?
  • If I am not wrong, it is stated here that v_mat = F(u_mat, p, t) # == mul!(v_mat, F, u_mat), so why it is not the case in my example?
  • I don’t get the point with cache_operator function. When should I use it?

Thanks a lot!
fdekerm