@@ -69,6 +69,27 @@ function LinearAlgebra.ldiv!(ii::IdentityOperator, u::AbstractVecOrMat)
6969 u
7070end
7171
72+ # Out-of-place: v is action vector, u is update vector
73+ function (ii:: IdentityOperator )(v:: AbstractVecOrMat , u, p, t; kwargs... )
74+ @assert size (v, 1 ) == ii. len
75+ update_coefficients (ii, u, p, t; kwargs... )
76+ copy (v)
77+ end
78+
79+ # In-place: w is destination, v is action vector, u is update vector
80+ function (ii:: IdentityOperator )(w:: AbstractVecOrMat , v:: AbstractVecOrMat , u, p, t; kwargs... )
81+ @assert size (v, 1 ) == ii. len
82+ update_coefficients! (ii, u, p, t; kwargs... )
83+ copy! (w, v)
84+ end
85+
86+ # In-place with scaling: w = α*(ii*v) + β*w
87+ function (ii:: IdentityOperator )(w:: AbstractVecOrMat , v:: AbstractVecOrMat , u, p, t, α, β; kwargs... )
88+ @assert size (v, 1 ) == ii. len
89+ update_coefficients! (ii, u, p, t; kwargs... )
90+ mul! (w, I, v, α, β)
91+ end
92+
7293# operator fusion with identity returns operator itself
7394for op in (:* , :∘ )
7495 @eval function Base. $op (ii:: IdentityOperator , A:: AbstractSciMLOperator )
@@ -146,6 +167,29 @@ function LinearAlgebra.mul!(v::AbstractVecOrMat,
146167 lmul! (β, v)
147168end
148169
170+ # Out-of-place: v is action vector, u is update vector
171+ function (nn:: NullOperator )(v:: AbstractVecOrMat , u, p, t; kwargs... )
172+ @assert size (v, 1 ) == nn. len
173+ update_coefficients (nn, u, p, t; kwargs... )
174+ zero (v)
175+ end
176+
177+ # In-place: w is destination, v is action vector, u is update vector
178+ function (nn:: NullOperator )(w:: AbstractVecOrMat , v:: AbstractVecOrMat , u, p, t; kwargs... )
179+ @assert size (v, 1 ) == nn. len
180+ update_coefficients! (nn, u, p, t; kwargs... )
181+ lmul! (false , w)
182+ w
183+ end
184+
185+ # In-place with scaling: w = α*(nn*v) + β*w
186+ function (nn:: NullOperator )(w:: AbstractVecOrMat , v:: AbstractVecOrMat , u, p, t, α, β; kwargs... )
187+ @assert size (v, 1 ) == nn. len
188+ update_coefficients! (nn, u, p, t; kwargs... )
189+ lmul! (β, w)
190+ w
191+ end
192+
149193# operator fusion, composition
150194for op in (:* , :∘ )
151195 @eval function Base. $op (nn:: NullOperator , A:: AbstractSciMLOperator )
@@ -336,6 +380,43 @@ function LinearAlgebra.ldiv!(L::ScaledOperator, u::AbstractVecOrMat)
336380 ldiv! (L. L, u)
337381end
338382
383+ # Out-of-place: v is action vector, u is update vector
384+ function (L:: ScaledOperator )(v:: AbstractVecOrMat , u, p, t; kwargs... )
385+ L = update_coefficients (L, u, p, t; kwargs... )
386+ if iszero (L. λ)
387+ return zero (v)
388+ else
389+ return L. λ * (L. L * v)
390+ end
391+ end
392+
393+ # In-place: w is destination, v is action vector, u is update vector
394+ function (L:: ScaledOperator )(w:: AbstractVecOrMat , v:: AbstractVecOrMat , u, p, t; kwargs... )
395+ update_coefficients! (L, u, p, t; kwargs... )
396+ if iszero (L. λ)
397+ lmul! (false , w)
398+ return w
399+ else
400+ a = convert (Number, L. λ)
401+ mul! (w, L. L, v, a, false )
402+ return w
403+ end
404+ end
405+
406+ # In-place with scaling: w = α*(L*v) + β*w
407+ function (L:: ScaledOperator )(w:: AbstractVecOrMat , v:: AbstractVecOrMat , u, p, t, α, β; kwargs... )
408+ update_coefficients! (L, u, p, t; kwargs... )
409+ if iszero (L. λ)
410+ lmul! (β, w)
411+ return w
412+ else
413+ a = convert (Number, L. λ * α)
414+ mul! (w, L. L, v, a, β)
415+ return w
416+ end
417+ end
418+
419+
339420"""
340421Lazy operator addition
341422
538619 v
539620 end
540621end
622+ # Out-of-place: v is action vector, u is update vector
623+ function (L:: AddedOperator )(v:: AbstractVecOrMat , u, p, t; kwargs... )
624+ L = update_coefficients (L, u, p, t; kwargs... )
625+ sum (op -> iszero (op) ? zero (v) : op (v, u, p, t; kwargs... ), L. ops)
626+ end
627+
628+ # In-place: w is destination, v is action vector, u is update vector
629+ function (L:: AddedOperator )(w:: AbstractVecOrMat , v:: AbstractVecOrMat , u, p, t; kwargs... )
630+ update_coefficients! (L, u, p, t; kwargs... )
631+ L. ops[1 ](w, v, u, p, t; kwargs... )
632+ for i in 2 : length (L. ops)
633+ if ! iszero (L. ops[i])
634+ L. ops[i](w, v, u, p, t, 1.0 , 1.0 ; kwargs... )
635+ end
636+ end
637+ w
638+ end
639+
640+ # In-place with scaling: w = α*(L*v) + β*w
641+ function (L:: AddedOperator )(w:: AbstractVecOrMat , v:: AbstractVecOrMat , u, p, t, α, β; kwargs... )
642+ update_coefficients! (L, u, p, t; kwargs... )
643+ lmul! (β, w)
644+ for op in L. ops
645+ if ! iszero (op)
646+ op (w, v, u, p, t, α, 1.0 ; kwargs... )
647+ end
648+ end
649+ w
650+ end
541651
542652"""
543653 Lazy operator composition
@@ -792,6 +902,41 @@ function LinearAlgebra.ldiv!(L::ComposedOperator, u::AbstractVecOrMat)
792902 u
793903end
794904
905+ # Out-of-place: v is action vector, u is update vector
906+ function (L:: ComposedOperator )(v:: AbstractVecOrMat , u, p, t; kwargs... )
907+ L = update_coefficients (L, u, p, t; kwargs... )
908+ result = v
909+ for op in reverse (L. ops)
910+ result = op (result, u, p, t; kwargs... )
911+ end
912+ result
913+ end
914+
915+ # In-place: w is destination, v is action vector, u is update vector
916+ function (L:: ComposedOperator )(w:: AbstractVecOrMat , v:: AbstractVecOrMat , u, p, t; kwargs... )
917+ update_coefficients! (L, u, p, t; kwargs... )
918+ @assert iscached (L) " Cache needs to be set up for ComposedOperator. Call cache_operator(L, u) first."
919+
920+ vecs = (w, L. cache[1 : (end - 1 )]. .. , v)
921+ for i in reverse (1 : length (L. ops))
922+ L. ops[i](vecs[i], vecs[i+ 1 ], u, p, t; kwargs... )
923+ end
924+ w
925+ end
926+
927+ # In-place with scaling: w = α*(L*v) + β*w
928+ function (L:: ComposedOperator )(w:: AbstractVecOrMat , v:: AbstractVecOrMat , u, p, t, α, β; kwargs... )
929+ update_coefficients! (L, u, p, t; kwargs... )
930+ @assert iscached (L) " Cache needs to be set up for ComposedOperator. Call cache_operator(L, u) first."
931+
932+ cache = L. cache[end ]
933+ copy! (cache, w)
934+
935+ L (w, v, u, p, t; kwargs... )
936+ lmul! (α, w)
937+ axpy! (β, cache, w)
938+ end
939+
795940"""
796941 Lazy Operator Inverse
797942"""
@@ -909,4 +1054,29 @@ function LinearAlgebra.ldiv!(L::InvertedOperator, u::AbstractVecOrMat)
9091054 copy! (L. cache, u)
9101055 mul! (u, L. L, L. cache)
9111056end
1057+
1058+ # Out-of-place: v is action vector, u is update vector
1059+ function (L:: InvertedOperator )(v:: AbstractVecOrMat , u, p, t; kwargs... )
1060+ L = update_coefficients (L, u, p, t; kwargs... )
1061+ L. L \ v
1062+ end
1063+
1064+ # In-place: w is destination, v is action vector, u is update vector
1065+ function (L:: InvertedOperator )(w:: AbstractVecOrMat , v:: AbstractVecOrMat , u, p, t; kwargs... )
1066+ update_coefficients! (L, u, p, t; kwargs... )
1067+ ldiv! (w, L. L, v)
1068+ w
1069+ end
1070+
1071+ # In-place with scaling: w = α*(L*v) + β*w
1072+ function (L:: InvertedOperator )(w:: AbstractVecOrMat , v:: AbstractVecOrMat , u, p, t, α, β; kwargs... )
1073+ update_coefficients! (L, u, p, t; kwargs... )
1074+ @assert iscached (L) " Cache needs to be set up for InvertedOperator. Call cache_operator(L, u) first."
1075+
1076+ copy! (L. cache, w)
1077+ ldiv! (w, L. L, v)
1078+ lmul! (α, w)
1079+ axpy! (β, L. cache, w)
1080+ w
1081+ end
9121082#
0 commit comments