Skip to content

Commit d29431c

Browse files
Fix operator algebras tutorial
1 parent 03320b8 commit d29431c

File tree

2 files changed

+57
-13
lines changed

2 files changed

+57
-13
lines changed

docs/src/tutorials/operator_algebras.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,15 @@
33
Let `M`, `D`, `F` be matrix-based, diagonal-matrix-based, and function-based
44
`SciMLOperators` respectively.
55

6-
```julia
6+
```@example operator_algebra
7+
using SciMLOperators, LinearAlgebra
78
N = 4
8-
f = (v, u, p, t) -> u .* v
9+
function f(v, u, p, t)
10+
u .* v
11+
end
12+
function f(w, v, u, p, t)
13+
w .= u .* v
14+
end
915
1016
M = MatrixOperator(rand(N, N))
1117
D = DiagonalOperator(rand(N))
@@ -14,32 +20,34 @@ F = FunctionOperator(f, zeros(N), zeros(N))
1420

1521
Then, the following codes just work.
1622

17-
```julia
23+
```@example operator_algebra
1824
L1 = 2M + 3F + LinearAlgebra.I + rand(N, N)
1925
L2 = D * F * M'
2026
L3 = kron(M, D, F)
21-
L4 = M \ D
27+
L4 = lu(M) \ D
2228
L5 = [M; D]' * [M F; F D] * [F; D]
2329
```
2430

2531
Each `L#` can be applied to `AbstractVector`s of appropriate sizes:
2632

27-
```julia
33+
```@example operator_algebra
2834
p = nothing # parameter struct
2935
t = 0.0 # time
3036
3137
u = rand(N)
3238
v = rand(N)
3339
w = L1(v, u, p, t) # == L1 * v
3440
41+
L3 = cache_operator(L3, v)
42+
3543
v_kron = rand(N^3)
3644
w_kron = L3(v_kron, u, p, t) # == L3 * v_kron
3745
```
3846

3947
For mutating operator evaluations, call `cache_operator` to generate an
4048
in-place cache, so the operation is nonallocating.
4149

42-
```julia
50+
```@example operator_algebra
4351
α, β = rand(2)
4452
4553
# allocate cache

src/func.jl

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,17 @@ function Base.:*(L::FunctionOperator{iip, true}, v::AbstractArray) where {iip}
734734
vec_output ? vec(W) : W
735735
end
736736

737+
function Base.:*(L::FunctionOperator{iip, false}, v::AbstractArray) where {iip}
738+
_sizecheck(L, v, nothing)
739+
V, _, vec_output = _unvec(L, v, nothing)
740+
741+
W, _ = L.cache
742+
W = copy(W)
743+
L.op(W, V, L.u, L.p, L.t; L.traits.kwargs...)
744+
745+
vec_output ? vec(W) : W
746+
end
747+
737748
function Base.:\(L::FunctionOperator{iip, true}, v::AbstractArray) where {iip}
738749
_sizecheck(L, nothing, v)
739750
_, V, vec_output = _unvec(L, nothing, v)
@@ -743,16 +754,30 @@ function Base.:\(L::FunctionOperator{iip, true}, v::AbstractArray) where {iip}
743754
vec_output ? vec(W) : W
744755
end
745756

757+
function Base.:\(L::FunctionOperator{iip, false}, v::AbstractArray) where {iip}
758+
_sizecheck(L, nothing, v)
759+
_, V, vec_output = _unvec(L, nothing, v)
760+
761+
W, _ = L.cache
762+
W = copy(W)
763+
L.op_inverse(W, V, L.u, L.p, L.t; L.traits.kwargs...)
764+
765+
vec_output ? vec(W) : W
766+
end
767+
746768
function LinearAlgebra.mul!(w::AbstractArray, L::FunctionOperator{true}, v::AbstractArray)
747769
_sizecheck(L, v, w)
748770
V, W, vec_output = _unvec(L, v, w)
749771
L.op(W, V, L.u, L.p, L.t; L.traits.kwargs...)
750772
vec_output ? vec(W) : W
751773
end
752774

753-
function LinearAlgebra.mul!(::AbstractArray, L::FunctionOperator{false}, ::AbstractArray,
775+
function LinearAlgebra.mul!(w::AbstractArray, L::FunctionOperator{false}, ::AbstractArray,
754776
args...)
755-
@error "LinearAlgebra.mul! not defined for out-of-place operator $L"
777+
_sizecheck(L, v, w)
778+
V, W, vec_output = _unvec(L, v, w)
779+
W .= L.op(V, L.u, L.p, L.t; L.traits.kwargs...)
780+
vec_output ? vec(W) : W
756781
end
757782

758783
function LinearAlgebra.mul!(w::AbstractArray, L::FunctionOperator{true, oop, false},
@@ -797,15 +822,26 @@ function LinearAlgebra.ldiv!(L::FunctionOperator{true}, v::AbstractArray)
797822
copy!(W, V)
798823
L.op_inverse(W, V, L.u, L.p, L.t; L.traits.kwargs...) # ldiv!(U, L, V)
799824

800-
vec_output ? vec(W) : W
825+
V .= W
826+
vec_output ? vec(V) : V
801827
end
802828

803-
function LinearAlgebra.ldiv!(v::AbstractArray, L::FunctionOperator{false}, u::AbstractArray)
804-
@error "LinearAlgebra.ldiv! not defined for out-of-place $L"
829+
function LinearAlgebra.ldiv!(w::AbstractArray, L::FunctionOperator{false}, v::AbstractArray)
830+
_sizecheck(L, v, w)
831+
W, V, _ = _unvec(L, w, v)
832+
833+
W .= L.op_inverse(V, L.u, L.p, L.t; L.traits.kwargs...)
834+
835+
w
805836
end
806837

807-
function LinearAlgebra.ldiv!(L::FunctionOperator{false}, u::AbstractArray)
808-
@error "LinearAlgebra.ldiv! not defined for out-of-place $L"
838+
function LinearAlgebra.ldiv!(L::FunctionOperator{false}, v::AbstractArray)
839+
_sizecheck(L, nothing, v)
840+
V, _, vec_output = _unvec(L, v, nothing)
841+
842+
V .= L.op_inverse(V, L.u, L.p, L.t; L.traits.kwargs...) # ldiv!(W, L, V)
843+
844+
vec_output ? vec(V) : V
809845
end
810846

811847
# Out-of-place: v is action vector, u is update vector

0 commit comments

Comments
 (0)