@@ -19,7 +19,14 @@ Base.similar(L::MatrixOperator, ::Type{T}, dims::Dims) where{T} = MatrixOperator
1919
2020# traits
2121@forward MatrixOperator. A (
22- issquare, has_ldiv, has_ldiv!
22+ LinearAlgebra. isreal,
23+ LinearAlgebra. issymmetric,
24+ LinearAlgebra. ishermitian,
25+ LinearAlgebra. isposdef,
26+
27+ issquare,
28+ has_ldiv,
29+ has_ldiv!,
2330 )
2431Base. size (L:: MatrixOperator ) = size (L. A)
2532Base. adjoint (L:: MatrixOperator ) = MatrixOperator (L. A' ; update_func= (A,u,p,t)-> L. update_func (L. A,u,p,t)' )
@@ -118,6 +125,13 @@ for op in (
118125 end
119126end
120127
128+ for op in (
129+ :* , :∘
130+ )
131+ @eval Base.$ op (A:: AbstractMatrix , B:: AbstractSciMLOperator ) = $ op (MatrixOperator (A), B)
132+ @eval Base.$ op (A:: AbstractSciMLOperator , B:: AbstractMatrix ) = $ op (A, MatrixOperator (B))
133+ end
134+
121135""" Diagonal Operator """
122136DiagonalOperator (u:: AbstractVector ) = MatrixOperator (Diagonal (u))
123137LinearAlgebra. Diagonal (L:: MatrixOperator ) = MatrixOperator (Diagonal (L. A))
252266"""
253267 Matrix free operators (given by a function)
254268"""
255- struct FunctionOperator{isinplace,T,F,Fa,Fi,Fai,Tr,P,Tt} <: AbstractSciMLOperator{T}
269+ struct FunctionOperator{isinplace,T,F,Fa,Fi,Fai,Tr,P,Tt,C } <: AbstractSciMLOperator{T}
256270 """ Function with signature op(u, p, t) and (if isinplace) op(du, u, p, t) """
257271 op:: F
258272 """ Adjoint operator"""
@@ -267,11 +281,27 @@ struct FunctionOperator{isinplace,T,F,Fa,Fi,Fai,Tr,P,Tt} <: AbstractSciMLOperato
267281 p:: P
268282 """ Time """
269283 t:: Tt
284+ """ Is cache set? """
285+ isset:: Bool
286+ """ Cache """
287+ cache:: C
288+
289+ function FunctionOperator (op,
290+ op_adjoint,
291+ op_inverse,
292+ op_adjoint_inverse,
293+ traits,
294+ p,
295+ t,
296+ isset,
297+ cache
298+ )
270299
271- function FunctionOperator (op, op_adjoint, op_inverse, op_adjoint_inverse, traits, p, t)
272300 iip = traits. isinplace
273301 T = traits. T
274302
303+ isset = cache != = nothing
304+
275305 new{iip,
276306 T,
277307 typeof (op),
@@ -281,11 +311,19 @@ struct FunctionOperator{isinplace,T,F,Fa,Fi,Fai,Tr,P,Tt} <: AbstractSciMLOperato
281311 typeof (traits),
282312 typeof (p),
283313 typeof (t),
314+ typeof (cache),
284315 }(
285- op, op_adjoint, op_inverse, op_adjoint_inverse, traits, p, t,
316+ op,
317+ op_adjoint,
318+ op_inverse,
319+ op_adjoint_inverse,
320+ traits,
321+ p,
322+ t,
323+ isset,
324+ cache,
286325 )
287326 end
288-
289327end
290328
291329function FunctionOperator (op;
@@ -303,6 +341,8 @@ function FunctionOperator(op;
303341 p= nothing ,
304342 t= nothing ,
305343
344+ cache= nothing ,
345+
306346 # traits
307347 opnorm= nothing ,
308348 isreal= true ,
@@ -331,6 +371,8 @@ function FunctionOperator(op;
331371 op_adjoint_inverse = op_inverse
332372 end
333373
374+ t = t isa Nothing ? zero (T) : t
375+
334376 traits = (;
335377 opnorm = opnorm,
336378 isreal = isreal,
@@ -343,6 +385,8 @@ function FunctionOperator(op;
343385 size = size,
344386 )
345387
388+ isset = cache != = nothing
389+
346390 FunctionOperator (
347391 op,
348392 op_adjoint,
@@ -351,6 +395,8 @@ function FunctionOperator(op;
351395 traits,
352396 p,
353397 t,
398+ isset,
399+ cache,
354400 )
355401end
356402
@@ -361,7 +407,7 @@ function update_coefficients!(L::FunctionOperator, u, p, t)
361407end
362408
363409Base. size (L:: FunctionOperator ) = L. traits. size
364- function Base. adjoint (L:: FunctionOperator{iip,T} ) where {iip,T}
410+ function Base. adjoint (L:: FunctionOperator )
365411
366412 if ishermitian (L) | (isreal (L) & issymmetric (L))
367413 return L
@@ -382,7 +428,20 @@ function Base.adjoint(L::FunctionOperator{iip,T}) where{iip,T}
382428 p = L. p
383429 t = L. t
384430
385- FuncitonOperator (op, op_adjoint, op_inverse, op_adjoint_inverse, traits, p, t)
431+ cache = issquare (L) ? cache : nothing
432+ isset = cache != = nothing
433+
434+
435+ FuncitonOperator (op,
436+ op_adjoint,
437+ op_inverse,
438+ op_adjoint_inverse,
439+ traits,
440+ p,
441+ t,
442+ isset,
443+ cache
444+ )
386445end
387446
388447function LinearAlgebra. opnorm (L:: FunctionOperator , p)
@@ -409,11 +468,30 @@ has_ldiv!(L::FunctionOperator{iip}) where{iip} = iip & !(L.op_inverse isa Nothin
409468Base.:* (L:: FunctionOperator , u:: AbstractVector ) = L. op (u, L. p, L. t)
410469Base.:\ (L:: FunctionOperator , u:: AbstractVector ) = L. op_inverse (u, L. p, L. t)
411470
471+ function cache_operator (L:: FunctionOperator , u:: AbstractVector )
472+ @set! L. cache = similar (u)
473+ L
474+ end
475+
412476function LinearAlgebra. mul! (v:: AbstractVector , L:: FunctionOperator , u:: AbstractVector )
413477 L. op (v, u, L. p, L. t)
414478end
415479
480+ function LinearAlgebra. mul! (v:: AbstractVector , L:: FunctionOperator , u:: AbstractVector , α, β)
481+ @assert L. isset " set up cache by calling cache_operator($L , $u )"
482+ copy! (L. cache, v)
483+ mul! (v, L, u)
484+ lmul! (α, v)
485+ axpy! (β, L. cache, v)
486+ end
487+
416488function LinearAlgebra. ldiv! (v:: AbstractVector , L:: FunctionOperator , u:: AbstractVector )
417489 L. op_inverse (v, u, L. p, L. t)
418490end
491+
492+ function LinearAlgebra. ldiv! (L:: FunctionOperator , u:: AbstractVector )
493+ @assert L. isset " set up cache by calling cache_operator($L , $u )"
494+ copy! (L. cache, u)
495+ ldiv! (u, L, L. cache)
496+ end
419497#
0 commit comments