Skip to content

Commit dbc8634

Browse files
authored
Merge branch 'master' into iscached
2 parents 27feda9 + f0c96d8 commit dbc8634

File tree

13 files changed

+120
-51
lines changed

13 files changed

+120
-51
lines changed

src/SciMLOperators.jl

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,7 @@ abstract type AbstractSciMLOperator{T} end
2626
"""
2727
$(TYPEDEF)
2828
"""
29-
abstract type AbstractSciMLLinearOperator{T} <: AbstractSciMLOperator{T} end
30-
31-
"""
32-
$(TYPEDEF)
33-
"""
34-
abstract type AbstractSciMLScalarOperator{T} <: AbstractSciMLLinearOperator{T} end
29+
abstract type AbstractSciMLScalarOperator{T} <: AbstractSciMLOperator{T} end
3530

3631
include("utils.jl")
3732
include("interface.jl")
@@ -59,6 +54,9 @@ export update_coefficients!,
5954
iscached,
6055
cache_operator,
6156

57+
issquare,
58+
islinear,
59+
6260
has_adjoint,
6361
has_expmv,
6462
has_expmv!,

src/basic.jl

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"""
22
$(TYPEDEF)
33
"""
4-
struct IdentityOperator{N} <: AbstractSciMLLinearOperator{Bool} end
4+
struct IdentityOperator{N} <: AbstractSciMLOperator{Bool} end
55

66
# constructors
77
IdentityOperator(u::AbstractArray) = IdentityOperator{size(u,1)}()
@@ -28,7 +28,7 @@ end
2828

2929
getops(::IdentityOperator) = ()
3030
isconstant(::IdentityOperator) = true
31-
islinear(L::IdentityOperator) = true
31+
islinear(::IdentityOperator) = true
3232
has_adjoint(::IdentityOperator) = true
3333
has_mul!(::IdentityOperator) = true
3434
has_ldiv(::IdentityOperator) = true
@@ -92,7 +92,7 @@ end
9292
"""
9393
$(TYPEDEF)
9494
"""
95-
struct NullOperator{N} <: AbstractSciMLLinearOperator{Bool} end
95+
struct NullOperator{N} <: AbstractSciMLOperator{Bool} end
9696

9797
# constructors
9898
NullOperator(u::AbstractArray) = NullOperator{size(u,1)}()
@@ -120,7 +120,7 @@ LinearAlgebra.isposdef(::NullOperator) = false
120120

121121
getops(::NullOperator) = ()
122122
isconstant(::NullOperator) = true
123-
islinear(L::NullOperator) = true
123+
islinear(::NullOperator) = true
124124
Base.iszero(::NullOperator) = true
125125
has_adjoint(::NullOperator) = true
126126
has_mul!(::NullOperator) = true
@@ -229,8 +229,8 @@ Base.conj(L::ScaledOperator) = conj(L.λ) * conj(L.L)
229229
LinearAlgebra.opnorm(L::ScaledOperator, p::Real=2) = abs(L.λ) * opnorm(L.L, p)
230230

231231
getops(L::ScaledOperator) = (L.λ, L.L,)
232-
islinear(L::ScaledOperator) = all(islinear, L.ops)
233232
isconstant(L::ScaledOperator) = isconstant(L.L) & isconstant(L.λ)
233+
islinear(L::ScaledOperator) = islinear(L.L)
234234
Base.iszero(L::ScaledOperator) = iszero(L.L) | iszero(L.λ)
235235
has_adjoint(L::ScaledOperator) = has_adjoint(L.L)
236236
has_mul(L::ScaledOperator) = has_mul(L.L)
@@ -375,6 +375,7 @@ end
375375
Base.conj(L::AddedOperator) = AddedOperator(conj.(L.ops))
376376

377377
getops(L::AddedOperator) = L.ops
378+
islinear(L::AddedOperator) = all(islinear, getops(L))
378379
Base.iszero(L::AddedOperator) = all(iszero, getops(L))
379380
has_adjoint(L::AddedOperator) = all(has_adjoint, L.ops)
380381

@@ -660,6 +661,7 @@ Base.adjoint(L::InvertedOperator) = InvertedOperator(adjoint(L.L); cache = iscac
660661
Base.conj(L::InvertedOperator) = InvertedOperator(conj(L.L); cache=L.cache)
661662

662663
getops(L::InvertedOperator) = (L.L,)
664+
islinear(L::InvertedOperator) = islinear(L.L)
663665

664666
has_mul(L::InvertedOperator) = has_ldiv(L.L)
665667
has_mul!(L::InvertedOperator) = has_ldiv!(L.L)

src/batch.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ by `update_coefficients!` and is assumed to have the following signature:
88
99
update_func(diag::AbstractVector,u,p,t) -> [modifies diag]
1010
"""
11-
struct BatchedDiagonalOperator{T,D,F} <: AbstractSciMLLinearOperator{T}
11+
struct BatchedDiagonalOperator{T,D,F} <: AbstractSciMLOperator{T}
1212
diag::D
1313
update_func::F
1414

@@ -58,7 +58,7 @@ end
5858
LinearAlgebra.isposdef(L::BatchedDiagonalOperator) = isposdef(Diagonal(vec(L.diag)))
5959

6060
isconstant(L::BatchedDiagonalOperator) = L.update_func == DEFAULT_UPDATE_FUNC
61-
issquare(L::BatchedDiagonalOperator) = true
61+
islinear(::BatchedDiagonalOperator) = true
6262
has_adjoint(L::BatchedDiagonalOperator) = true
6363
has_ldiv(L::BatchedDiagonalOperator) = all(x -> !iszero(x), L.diag)
6464
has_ldiv!(L::BatchedDiagonalOperator) = has_ldiv(L)

src/func.jl

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,12 @@ function FunctionOperator(op,
9898
t::Union{Number,Nothing}=nothing,
9999

100100
# traits
101-
opnorm=nothing,
102-
issymmetric::Bool=false,
103-
ishermitian::Bool=false,
104-
isposdef::Bool=false,
101+
islinear::Bool = false,
102+
103+
opnorm = nothing,
104+
issymmetric::Bool = false,
105+
ishermitian::Bool = false,
106+
isposdef::Bool = false,
105107
)
106108

107109
sz = (size(output, 1), size(input, 1))
@@ -142,6 +144,8 @@ function FunctionOperator(op,
142144
end
143145

144146
traits = (;
147+
islinear = islinear,
148+
145149
opnorm = opnorm,
146150
issymmetric = issymmetric,
147151
ishermitian = ishermitian,
@@ -270,6 +274,7 @@ LinearAlgebra.ishermitian(L::FunctionOperator) = L.traits.ishermitian
270274
LinearAlgebra.isposdef(L::FunctionOperator) = L.traits.isposdef
271275

272276
getops(::FunctionOperator) = ()
277+
islinear(L::FunctionOperator) = L.traits.islinear
273278
has_adjoint(L::FunctionOperator) = !(L.op_adjoint isa Nothing)
274279
has_mul(L::FunctionOperator{iip}) where{iip} = true
275280
has_mul!(L::FunctionOperator{iip}) where{iip} = iip

src/interface.jl

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -94,17 +94,12 @@ Base.eltype(::AbstractSciMLOperator{T}) where T = T
9494
Base.oneunit(L::AbstractSciMLOperator) = one(L)
9595
Base.oneunit(LType::Type{<:AbstractSciMLOperator}) = one(LType)
9696

97-
issquare(L::AbstractSciMLOperator) = isequal(size(L)...)
98-
99-
Base.iszero(::AbstractSciMLOperator) = false
100-
101-
islinear(::AbstractSciMLOperator) = false
102-
islinear(::AbstractSciMLLinearOperator) = true
97+
Base.iszero(::AbstractSciMLOperator) = false # TODO
10398

10499
has_adjoint(L::AbstractSciMLOperator) = false # L', adjoint(L)
105100
has_expmv!(L::AbstractSciMLOperator) = false # expmv!(v, L, t, u)
106101
has_expmv(L::AbstractSciMLOperator) = false # v = exp(L, t, u)
107-
has_exp(L::AbstractSciMLOperator) = false # v = exp(L, t)*u
102+
has_exp(L::AbstractSciMLOperator) = islinear(L)
108103
has_mul(L::AbstractSciMLOperator) = true # du = L*u
109104
has_mul!(L::AbstractSciMLOperator) = false # mul!(du, L, u)
110105
has_ldiv(L::AbstractSciMLOperator) = false # du = L\u
@@ -116,7 +111,9 @@ isconstant(L) = true
116111
isconstant(L::AbstractSciMLOperator) = all(isconstant, getops(L))
117112
#isconstant(L::AbstractSciMLOperator) = L.update_func = DEFAULT_UPDATE_FUNC
118113

119-
islinear(L) = false
114+
#islinear(L) = false
115+
islinear(::AbstractSciMLOperator) = false
116+
120117
islinear(::Union{
121118
# LinearAlgebra
122119
AbstractMatrix,
@@ -125,23 +122,20 @@ islinear(::Union{
125122

126123
# Base
127124
Number,
128-
129-
# SciMLOperators
130-
AbstractSciMLLinearOperator,
131125
}
132126
) = true
133127

134128
has_mul(L) = false
135129
has_mul(::Union{
136-
# LinearAlgebra
137-
AbstractVecOrMat,
138-
AbstractMatrix,
139-
UniformScaling,
130+
# LinearAlgebra
131+
AbstractVecOrMat,
132+
AbstractMatrix,
133+
UniformScaling,
140134

141-
# Base
142-
Number,
143-
}
144-
) = true
135+
# Base
136+
Number,
137+
}
138+
) = true
145139

146140
has_mul!(L) = false
147141
has_mul!(::Union{
@@ -171,7 +165,7 @@ has_ldiv!(::Union{
171165
}
172166
) = true
173167

174-
has_adjoint(L) = false
168+
has_adjoint(L) = islinear(L)
175169
has_adjoint(::Union{
176170
# LinearAlgebra
177171
AbstractMatrix,
@@ -180,13 +174,10 @@ has_adjoint(::Union{
180174

181175
# Base
182176
Number,
183-
184-
# SciMLOperators
185-
AbstractSciMLLinearOperator,
186177
}
187178
) = true
188179

189-
issquare(A) = size(A,1) === size(A,2)
180+
issquare(L) = isequal(size(L)...)
190181
issquare(::Union{
191182
# LinearAlgebra
192183
UniformScaling,
@@ -201,7 +192,6 @@ Base.isreal(L::AbstractSciMLOperator{T}) where{T} = T <: Real
201192
Base.Matrix(L::AbstractSciMLOperator) = Matrix(convert(AbstractMatrix, L))
202193

203194
LinearAlgebra.exp(L::AbstractSciMLOperator,t) = exp(t*L)
204-
has_exp(L::AbstractSciMLLinearOperator) = true
205195
expmv(L::AbstractSciMLOperator,u,p,t) = exp(L,t)*u
206196
expmv!(v,L::AbstractSciMLOperator,u,p,t) = mul!(v,exp(L,t),u)
207197

src/left.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ AbstractAdjointVecOrMat = Adjoint{ T,<:AbstractVecOrMat} where{T}
6060
AbstractTransposedVecOrMat = Transpose{T,<:AbstractVecOrMat} where{T}
6161

6262
has_adjoint(::AdjointOperator) = true
63+
#has_adjoint(::TransposedOperator) = ??
64+
65+
islinear(L::AdjointOperator) = islinear(L.L)
66+
islinear(L::TransposedOperator) = islinear(L.L)
6367

6468
Base.transpose(L::AdjointOperator) = conj(L.L)
6569
Base.adjoint(L::TransposedOperator) = conj(L.L)

src/matrix.jl

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ the following signature:
88
99
update_func(A::AbstractMatrix,u,p,t) -> [modifies A]
1010
"""
11-
struct MatrixOperator{T,AType<:AbstractMatrix{T},F} <: AbstractSciMLLinearOperator{T}
11+
struct MatrixOperator{T,AType<:AbstractMatrix{T},F} <: AbstractSciMLOperator{T}
1212
A::AType
1313
update_func::F
1414
MatrixOperator(A::AType; update_func=DEFAULT_UPDATE_FUNC) where{AType} =
@@ -28,6 +28,8 @@ Base.similar(L::MatrixOperator, ::Type{T}, dims::Dims) where{T} = MatrixOperator
2828
has_ldiv,
2929
has_ldiv!,
3030
)
31+
islinear(::MatrixOperator) = true
32+
3133
Base.size(L::MatrixOperator) = size(L.A)
3234
for op in (
3335
:adjoint,
@@ -121,7 +123,7 @@ Like MatrixOperator, but stores a Factorization instead.
121123
122124
Supports left division and `ldiv!` when applied to an array.
123125
"""
124-
struct InvertibleOperator{T,FType} <: AbstractSciMLLinearOperator{T}
126+
struct InvertibleOperator{T,FType} <: AbstractSciMLOperator{T}
125127
F::FType
126128

127129
function InvertibleOperator(F)
@@ -131,7 +133,7 @@ struct InvertibleOperator{T,FType} <: AbstractSciMLLinearOperator{T}
131133
end
132134

133135
# constructor
134-
function LinearAlgebra.factorize(L::AbstractSciMLLinearOperator)
136+
function LinearAlgebra.factorize(L::AbstractSciMLOperator)
135137
fact = factorize(convert(AbstractMatrix, L))
136138
InvertibleOperator(fact)
137139
end
@@ -172,6 +174,7 @@ LinearAlgebra.opnorm(L::InvertibleOperator{T}, p=2) where{T} = one(T) / opnorm(L
172174
LinearAlgebra.issuccess(L::InvertibleOperator) = issuccess(L.F)
173175

174176
getops(L::InvertibleOperator) = (L.F,)
177+
islinear(L::InvertibleOperator) = islinear(L.F)
175178

176179
@forward InvertibleOperator.F (
177180
# LinearAlgebra

src/scalar.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ Base.adjoint(α::AbstractSciMLScalarOperator) = conj(α)
2626
Base.transpose::AbstractSciMLScalarOperator) = α
2727

2828
has_mul!(::AbstractSciMLScalarOperator) = true
29-
issquare(L::AbstractSciMLScalarOperator) = true
29+
issquare(::AbstractSciMLScalarOperator) = true
30+
islinear(::AbstractSciMLScalarOperator) = true
3031
has_adjoint(::AbstractSciMLScalarOperator) = true
3132

3233
Base.:*::AbstractSciMLScalarOperator, u::AbstractVecOrMat) = convert(Number, α) * u

test/basic.jl

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ K = 12
2727
β = rand()
2828
Id = IdentityOperator{N}()
2929

30+
@test issquare(Id)
31+
@test islinear(Id)
3032
@test IdentityOperator(u) isa IdentityOperator{N}
3133
@test one(A) isa IdentityOperator{N}
3234
@test convert(AbstractMatrix, Id) == Matrix(I, N, N)
@@ -62,6 +64,8 @@ end
6264
β = rand()
6365
Z = NullOperator{N}()
6466

67+
@test issquare(Z)
68+
@test islinear(Z)
6569
@test NullOperator(u) isa NullOperator{N}
6670
@test zero(A) isa NullOperator{N}
6771
@test convert(AbstractMatrix, Z) == zeros(size(Z))
@@ -102,6 +106,8 @@ end
102106

103107
@test op isa ScaledOperator
104108
@test iscached(op)
109+
@test issquare(op)
110+
@test islinear(op)
105111

106112
@test α * A * u op * u
107113
@test* op) * u β * α * A * u
@@ -170,10 +176,14 @@ end
170176

171177
@test op isa ComposedOperator
172178
@test *(op.ops...) isa ComposedOperator
179+
@test issquare(op)
180+
@test islinear(op)
173181

174182
opF = factorize(op)
175183

176184
@test opF isa ComposedOperator
185+
@test issquare(opF)
186+
@test islinear(opF)
177187

178188
@test ABCmulu op * u
179189
@test ABCdivu op \ u opF \ u
@@ -215,10 +225,14 @@ end
215225

216226
@testset "Adjoint, Transpose" begin
217227

218-
for (op, LType, VType) in (
219-
(adjoint, AdjointOperator, AbstractAdjointVecOrMat ),
220-
(transpose, TransposedOperator, AbstractTransposedVecOrMat),
221-
)
228+
for (op,
229+
LType,
230+
VType
231+
) in (
232+
(adjoint, AdjointOperator, AbstractAdjointVecOrMat ),
233+
(transpose, TransposedOperator, AbstractTransposedVecOrMat),
234+
)
235+
222236
A = rand(N,N)
223237
D = Bidiagonal(rand(N,N), :L)
224238
u = rand(N,K)
@@ -228,7 +242,13 @@ end
228242
b = rand()
229243

230244
At = op(A)
231-
Dt = op(A)
245+
Dt = op(D)
246+
247+
@test issquare(At)
248+
@test issquare(Dt)
249+
250+
@test islinear(At)
251+
@test islinear(Dt)
232252

233253
AA = MatrixOperator(A)
234254
DD = MatrixOperator(D)
@@ -262,6 +282,9 @@ end
262282
Di = cache_operator(Di, u)
263283
@test iscached(Di)
264284

285+
@test issquare(Di)
286+
@test islinear(Di)
287+
265288
@test Di * u u ./ s
266289
v=rand(N); @test mul!(v, Di, u) u ./ s
267290
v=rand(N); w=copy(v); @test mul!(v, Di, u, α, β) α *(u ./ s) + β*w

0 commit comments

Comments
 (0)