1- abstract type AbstractWOperator{T} <: AbstractSciMLOperator{T}
1+ abstract type AbstractWOperator{T} <: AbstractSciMLOperator{T} end
22
33struct StaticWOperator{isinv, T, F} <: AbstractWOperator{T}
44 W:: T
@@ -8,9 +8,7 @@ struct StaticWOperator{isinv, T, F} <: AbstractWOperator{T}
88 isinv = n <= 7 # cutoff where LU has noticable overhead
99
1010 F = if isinv && callinv
11- # this should be in ArrayInterface but can't be for silly reasons
12- # doing to how StaticArrays and StaticArraysCore are split up
13- StaticArrays. LU (LowerTriangular (W), UpperTriangular (W), SVector {n} (1 : n))
11+ ArrayInterface. lu_instance (W)
1412 else
1513 lu (W, check = false )
1614 end
@@ -36,18 +34,10 @@ W = \\frac{1}{\\gamma}MM - J
3634```
3735
3836where `MM` is the mass matrix (a regular `AbstractMatrix` or a `UniformScaling`),
39- `γ` is a real number proportional to the time step, and `J` is the Jacobian
40- operator (must be a `AbstractSciMLOperator`). A `WOperator` can also be
41- constructed using a `*DEFunction` directly as
42-
43- WOperator(f,gamma)
44-
45- `f` needs to have a jacobian and `jac_prototype`, but the prototype does not need
46- to be a diffeq operator --- it will automatically be converted to one.
37+ `γ` is a real number, and `J` is the Jacobian operator (must be a `AbstractSciMLOperator`).
4738
4839`WOperator` supports lazy `*` and `mul!` operations, the latter utilizing an
4940internal cache (can be specified in the constructor; default to regular `Vector`).
50- It supports all of `AbstractSciMLOperator`'s interface.
5141"""
5242mutable struct WOperator{IIP, T,
5343 MType,
@@ -64,50 +54,11 @@ mutable struct WOperator{IIP, T,
6454 jacvec:: JV
6555
6656 function WOperator {IIP} (mass_matrix, gamma, J, u, jacvec = nothing ) where {IIP}
67- # TODO : there is definitely a missing interface.
68- # Tentative interface: `has_concrete` and `concertize(A)`
69- if J isa Union{Number, ScalarOperator}
70- _concrete_form = - mass_matrix / gamma + convert (Number, J)
71- _func_cache = nothing
72- else
73- AJ = J isa MatrixOperator ? convert (AbstractMatrix, J) : J
74- if AJ isa AbstractMatrix
75- mm = mass_matrix isa MatrixOperator ?
76- convert (AbstractMatrix, mass_matrix) : mass_matrix
77- if is_sparse (AJ)
78-
79- # If gamma is zero, then it's just an initialization and we want to make sure
80- # we get the right sparsity pattern. If gamma is not zero, then it's a case where
81- # a new W is created (as part of an out-of-place solve) and thus the actual
82- # values actually matter!
83- #
84- # Constant operators never refactorize so always use the correct values there
85- # as well
86- if gamma == 0 && ! (J isa MatrixOperator && isconstant (J))
87- # Workaround https://github.com/JuliaSparse/SparseArrays.jl/issues/190
88- # Hopefully `rand()` does not match any value in the array (prob ~ 0, with a check)
89- # Then `one` is required since gamma is zero
90- # Otherwise this will not pick up the union sparsity pattern
91- # But instead drop the runtime zeros (i.e. all values) of the AJ pattern!
92- AJn = nonzeros (AJ)
93- x = rand ()
94- @assert all (! isequal (x), AJn)
95-
96- fill! (AJn, rand ())
97- _concrete_form = - mm / one (gamma) + AJ
98- fill! (_concrete_form, false ) # safety measure, throw singular error if not filled
99- else
100- _concrete_form = - mm / gamma + AJ
101- end
102- else
103- _concrete_form = - mm / gamma + AJ
104- end
105-
106- else
107- _concrete_form = nothing
108- end
109- _func_cache = zero (u)
110- end
57+ AJ = J isa MatrixOperator ? convert (AbstractMatrix, J) : J
58+ mm = mass_matrix isa MatrixOperator ?
59+ convert (AbstractMatrix, mass_matrix) : mass_matrix
60+ _concrete_form = - mm / gamma + AJ
61+ _func_cache = zero (u)
11162 T = eltype (_concrete_form)
11263 MType = typeof (mass_matrix)
11364 GType = typeof (gamma)
@@ -116,52 +67,42 @@ mutable struct WOperator{IIP, T,
11667 C = typeof (_concrete_form)
11768 JV = typeof (jacvec)
11869 return new {IIP, T, MType, GType, JType, F, C, JV} (mass_matrix, gamma, J,
119- _func_cache, _concrete_form,
120- jacvec)
70+ _func_cache, _concrete_form, jacvec)
12171 end
12272
12373 function Base. copy (W:: WOperator{IIP, T, MType, GType, JType, F, C, JV} ) where {IIP, T, MType, GType, JType, F, C, JV}
12474 return new {IIP, T, MType, GType, JType, F, C, JV} (
12575 W. mass_matrix,
12676 W. gamma,
12777 W. J,
128- W . _func_cache === nothing ? nothing : copy (W. _func_cache),
129- W . _concrete_form === nothing ? nothing : copy (W. _concrete_form),
78+ copy (W. _func_cache),
79+ copy (W. _concrete_form),
13080 W. jacvec
13181 )
13282 end
13383end
13484Base. eltype (W:: WOperator ) = eltype (W. J)
13585
136- # In WOperator update_coefficients!, accept both missing u/p/t and missing dtgamma and don't update them in that case.
86+ # In WOperator update_coefficients!, accept both missing u/p/t and missing gamma and don't update them in that case.
13787# This helps support partial updating logic used with Newton solvers.
13888function update_coefficients! (W:: WOperator ,
13989 u = nothing ,
14090 p = nothing ,
14191 t = nothing ;
142- dtgamma = nothing )
92+ gamma = nothing )
14393 if (u != = nothing ) && (p != = nothing ) && (t != = nothing )
14494 update_coefficients! (W. J, u, p, t)
14595 update_coefficients! (W. mass_matrix, u, p, t)
14696 ! isnothing (W. jacvec) && update_coefficients! (W. jacvec, u, p, t)
14797 end
148- dtgamma != = nothing && (W. gamma = dtgamma )
98+ gamma != = nothing && (W. gamma = gamma )
14999 W
150100end
151101
152- function update_coefficients! (J:: UJacobianWrapper , u, p, t)
153- J. p = p
154- J. t = t
155- end
156-
157102function Base. convert (:: Type{AbstractMatrix} , W:: WOperator{IIP} ) where {IIP}
158103 if ! IIP
159104 # Allocating
160105 W. _concrete_form = - W. mass_matrix / W. gamma + convert (AbstractMatrix, W. J)
161- else
162- # Non-allocating already updated
163- # _W = W._concrete_form
164- # jacobian2W!(_W, W.mass_matrix, W.gamma, W.J)
165106 end
166107 return W. _concrete_form
167108end
@@ -202,19 +143,18 @@ function LinearAlgebra.mul!(Y::AbstractVecOrMat, W::WOperator, B::AbstractVecOrM
202143 # Compute mass_matrix * B
203144 if isa (W. mass_matrix, UniformScaling)
204145 a = - W. mass_matrix. λ / W. gamma
205- @. . broadcast = false Y= a* B
146+ @. Y= a* B
206147 else
207148 mul! (_vec (Y), W. mass_matrix, _vec (B))
208149 lmul! (- inv (W. gamma), Y)
209150 end
210151 # Compute J * B and add
211- if W. jacvec != = nothing
212- mul! (_vec (W. _func_cache), W. jacvec, _vec (B))
213- else
152+ if isnothing (W. jacvec)
214153 mul! (_vec (W. _func_cache), W. J, _vec (B))
154+ else
155+ mul! (_vec (W. _func_cache), W. jacvec, _vec (B))
215156 end
216157 _vec (Y) .+ = _vec (W. _func_cache)
217158end
218159
219-
220160has_concretization (:: AbstractWOperator ) = true
0 commit comments