22"""
33 Matrix free operators (given by a function)
44"""
5- mutable struct FunctionOperator{iip,oop,T<: Number ,F,Fa,Fi,Fai,Tr,P,Tt,C} <: AbstractSciMLOperator{T}
5+ mutable struct FunctionOperator{iip,oop,mul5, T<: Number ,F,Fa,Fi,Fai,Tr,P,Tt,C} <: AbstractSciMLOperator{T}
66 """ Function with signature op(u, p, t) and (if isinplace) op(du, u, p, t) """
77 op:: F
88 """ Adjoint operator"""
@@ -33,11 +33,13 @@ mutable struct FunctionOperator{iip,oop,T<:Number,F,Fa,Fi,Fai,Tr,P,Tt,C} <: Abst
3333
3434 iip = traits. isinplace
3535 oop = traits. outofplace
36+ mul5 = traits. has_mul5
3637 T = traits. T
3738
3839 new{
3940 iip,
4041 oop,
42+ mul5,
4143 T,
4244 typeof (op),
4345 typeof (op_adjoint),
@@ -88,6 +90,8 @@ function FunctionOperator(op,
8890
8991 isinplace:: Union{Nothing,Bool} = nothing ,
9092 outofplace:: Union{Nothing,Bool} = nothing ,
93+ has_mul5:: Union{Nothing,Bool} = nothing ,
94+ cache:: Union{Nothing, NTuple{2}} = nothing ,
9195 T:: Union{Type{<:Number},Nothing} = nothing ,
9296
9397 op_adjoint= nothing ,
@@ -109,21 +113,34 @@ function FunctionOperator(op,
109113 )
110114
111115 sz = (size (output, 1 ), size (input, 1 ))
112- T = T isa Nothing ? promote_type (eltype .((input, output))... ) : T
113- t = t isa Nothing ? zero (real (T)) : t
116+ T = isnothing (T) ? promote_type (eltype .((input, output))... ) : T
117+ t = isnothing (t) ? zero (real (T)) : t
114118
115- isinplace = if isinplace isa Nothing
119+ isinplace = if isnothing ( isinplace)
116120 static_hasmethod (op, typeof ((output, input, p, t)))
117121 else
118122 isinplace
119123 end
120124
121- outofplace = if outofplace isa Nothing
125+ outofplace = if isnothing ( outofplace)
122126 static_hasmethod (op, typeof ((input, p, t)))
123127 else
124128 outofplace
125129 end
126130
131+ has_mul5 = if isnothing (has_mul5)
132+ has_mul5 = true
133+ for f in (
134+ op, op_adjoint, op_inverse, op_adjoint_inverse,
135+ )
136+ if ! isnothing (f)
137+ has_mul5 *= static_hasmethod (f, typeof ((output, input, p, t, t, t)))
138+ end
139+ end
140+
141+ has_mul5
142+ end
143+
127144 if ! isinplace & ! outofplace
128145 @error " Please provide a funciton with signatures `op(u, p, t)` for applying
129146 the operator out-of-place, and/or the signature is `op(du, u, p, t)` for
@@ -155,12 +172,12 @@ function FunctionOperator(op,
155172
156173 isinplace = isinplace,
157174 outofplace = outofplace,
175+ has_mul5 = has_mul5,
176+ ifcache = ifcache,
158177 T = T,
159178 size = sz,
160179 )
161180
162- cache = nothing
163-
164181 L = FunctionOperator (
165182 op,
166183 op_adjoint,
@@ -172,7 +189,11 @@ function FunctionOperator(op,
172189 cache,
173190 )
174191
175- ifcache ? cache_operator (L, input, output) : L
192+ if ifcache & isnothing (L. cache)
193+ L = cache_operator (L, input, output)
194+ end
195+
196+ L
176197end
177198
178199function update_coefficients (L:: FunctionOperator , u, p, t)
@@ -204,7 +225,13 @@ function update_coefficients!(L::FunctionOperator, u, p, t)
204225 nothing
205226end
206227
228+ function iscached (L:: FunctionOperator )
229+ L. traits. ifcache ? ! isnothing (L. cache) : ! L. traits. ifcache
230+ ! isnothing (L. cache)
231+ end
232+
207233function cache_self (L:: FunctionOperator , u:: AbstractVecOrMat , v:: AbstractVecOrMat )
234+ L. traits. ifcache && @warn " you are allocating cache for a FunctionOperator for which ifcache = false."
208235 @set! L. cache = zero .((u, v))
209236 L
210237end
@@ -365,7 +392,7 @@ function LinearAlgebra.mul!(v::AbstractVecOrMat, L::FunctionOperator{false}, u::
365392 @error " LinearAlgebra.mul! not defined for out-of-place FunctionOperators"
366393end
367394
368- function LinearAlgebra. mul! (v:: AbstractVecOrMat , L:: FunctionOperator{true} , u:: AbstractVecOrMat , α, β)
395+ function LinearAlgebra. mul! (v:: AbstractVecOrMat , L:: FunctionOperator{true, oop, false } , u:: AbstractVecOrMat , α, β) where {oop}
369396 _, co = L. cache
370397
371398 copy! (co, v)
@@ -374,6 +401,10 @@ function LinearAlgebra.mul!(v::AbstractVecOrMat, L::FunctionOperator{true}, u::A
374401 axpy! (β, co, v)
375402end
376403
404+ function LinearAlgebra. mul! (v:: AbstractVecOrMat , L:: FunctionOperator{true, oop, true} , u:: AbstractVecOrMat , α, β) where {oop}
405+ L. op (v, u, L. p, L. t, α, β)
406+ end
407+
377408function LinearAlgebra. ldiv! (v:: AbstractVecOrMat , L:: FunctionOperator{true} , u:: AbstractVecOrMat )
378409 L. op_inverse (v, u, L. p, L. t)
379410end
0 commit comments