You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/Reactor.jl
+129-9Lines changed: 129 additions & 9 deletions
Original file line number
Diff line number
Diff line change
@@ -3,38 +3,68 @@ using DiffEqBase
3
3
using ForwardDiff
4
4
using Sundials
5
5
using ModelingToolkit
6
+
using IncompleteLU
7
+
using LinearAlgebra
8
+
using SparseArrays
6
9
abstract type AbstractReactor end
7
10
export AbstractReactor
8
11
9
-
struct Reactor{D,Q} <:AbstractReactor
12
+
struct Reactor{D,Q,F1,F2,F3} <:AbstractReactor
10
13
domain::D
11
14
ode::ODEProblem
12
15
recommendedsolver::Q
13
16
forwardsensitivities::Bool
17
+
precsundials::F1#function to calculate preconditioner for Sundials solvers
18
+
psetupsundials::F2#function to compute preconditioner \ residue for Sundials solvers
19
+
precsjulia::F3#function to calculate preconditioner for Julia solvers
14
20
end
15
21
16
-
functionReactor(domain::T,y0::Array{W,1},tspan::Tuple,interfaces::Z=[];p::X=DiffEqBase.NullParameters(),forwardsensitivities=false,forwarddiff=false,modelingtoolkit=false) where {T<:AbstractDomain,W<:Real,Z<:AbstractArray,X}
22
+
functionReactor(domain::T,y0::Array{T1,1},tspan::Tuple,interfaces::Z=[];p::X=DiffEqBase.NullParameters(),forwardsensitivities=false,forwarddiff=false,modelingtoolkit=false,tau=1e-3) where {T<:AbstractDomain,T1<:Real,Z<:AbstractArray,X}
17
23
dydt(dy::X,y::T,p::V,t::Q) where {X,T,Q,V} =dydtreactor!(dy,y,t,domain,interfaces,p=p)
18
24
jacy!(J::Q2,y::T,p::V,t::Q) where {Q2,T,Q,V} =jacobiany!(J,y,p,t,domain,interfaces,nothing)
19
25
jacyforwarddiff!(J::Q2,y::T,p::V,t::Q) where {Q2,T,Q,V} =jacobianyforwarddiff!(J,y,p,t,domain,interfaces,nothing)
20
26
jacp!(J::Q2,y::T,p::V,t::Q) where {Q2,T,Q,V} =jacobianp!(J,y,p,t,domain,interfaces,nothing)
21
27
jacpforwarddiff!(J::Q2,y::T,p::V,t::Q) where {Q2,T,Q,V} =jacobianpforwarddiff!(J,y,p,t,domain,interfaces,nothing)
22
28
29
+
psetupsundials(p::T1, t::T2, u::T3, du::T4, jok::Bool, jcurPtr::T5, gamma::T6) where {T1,T2,T3,T4,T5,T6} =_psetup(p, t, u, du, jok, jcurPtr, gamma, jacy!, W::SparseMatrixCSC{Float64, Int64}, preccache::Base.RefValue{IncompleteLU.ILUFactorization{Float64, Int64}}, tau::Float64)
precsjulia(W::T1,du::T2,u::T3,p::T4,t::T5,newW::T6,Plprev::T7,Prprev::T8,solverdata::T9) where {T1,T2,T3,T4,T5,T6,T7,T8,T9} =_precsjulia(W,du,u,p,t,newW,Plprev,Prprev,solverdata,tau)
32
+
33
+
# determine worst sparsity
34
+
y0length =length(y0)
35
+
J =spzeros(y0length,y0length)
36
+
jacyforwarddiff!(J,NaN*ones(y0length),p,0.0)
37
+
@. J.nzval =1.0
38
+
sparsity =1.0-length(J.nzval)/(y0length*y0length)
39
+
40
+
# preconditioner caches for Sundials solver
41
+
W =spzeros(y0length,y0length)
42
+
jacyforwarddiff!(W,y0,p,0.0)
43
+
@. W.nzval =-1.0*W.nzval
44
+
idxs =diagind(W)
45
+
@inbounds@views@. W[idxs] = W[idxs] +1
46
+
prectmp =ilu(W, τ = tau)
47
+
preccache =Ref(prectmp)
48
+
23
49
if (forwardsensitivities ||!forwarddiff) && domain isa Union{ConstantTPDomain,ConstantVDomain,ConstantPDomain,ParametrizedTPDomain,ParametrizedVDomain,ParametrizedPDomain,ConstantTVDomain,ParametrizedTConstantVDomain,ConstantTAPhiDomain}
odefcn =ODEFunction(dydt;jac=jacyforwarddiff!,paramjac=jacpforwarddiff!,jac_prototype=float.(J)) #jac_prototype is not needed/used for Sundials solvers but maybe needed for Julia solvers
functionReactor(domains::T,y0s::W,tspan::W2,interfaces::Z=Tuple(),ps::X=DiffEqBase.NullParameters();forwardsensitivities=false,modelingtoolkit=false) where {T<:Tuple,W<:Tuple,Z,X,W2}
85
+
functionReactor(domains::T,y0s::W1,tspan::W2,interfaces::Z=Tuple(),ps::X=DiffEqBase.NullParameters();forwardsensitivities=false,modelingtoolkit=false,tau=1e-3) where {T<:Tuple,W1<:Tuple,Z,X,W2}
56
86
#adjust indexing
57
87
y0 =zeros(sum(length(y) for y in y0s))
58
88
Nvars =0
@@ -137,6 +167,25 @@ function Reactor(domains::T,y0s::W,tspan::W2,interfaces::Z=Tuple(),ps::X=DiffEqB
137
167
jacy!(J::Q2,y::T,p::V,t::Q) where {Q2,T,Q,V} =jacobianyforwarddiff!(J,y,p,t,domains,interfaces,nothing)
138
168
jacp!(J::Q2,y::T,p::V,t::Q) where {Q2,T,Q,V} =jacobianpforwarddiff!(J,y,p,t,domains,interfaces,nothing)
139
169
170
+
psetupsundials(p::T1, t::T2, u::T3, du::T4, jok::Bool, jcurPtr::T5, gamma::T6) where {T1,T2,T3,T4,T5,T6} =_psetup(p, t, u, du, jok, jcurPtr, gamma, jacy!, W::SparseMatrixCSC{Float64, Int64}, preccache::Base.RefValue{IncompleteLU.ILUFactorization{Float64, Int64}}, tau::Float64)
precsjulia(W::T1,du::T2,u::T3,p::T4,t::T5,newW::T6,Plprev::T7,Prprev::T8,solverdata::T9) where {T1,T2,T3,T4,T5,T6,T7,T8,T9} =_precsjulia(W,du,u,p,t,newW,Plprev,Prprev,solverdata,tau)
173
+
174
+
# determine worst sparsity
175
+
y0length =length(y0)
176
+
J =spzeros(y0length,y0length)
177
+
jacy!(J,NaN*ones(y0length),p,0.0)
178
+
@. J.nzval =1.0
179
+
sparsity =1.0-length(J.nzval)/(y0length*y0length)
180
+
181
+
# preconditioner caches for Sundials solver
182
+
W =spzeros(y0length,y0length)
183
+
jacy!(W,y0,p,0.0)
184
+
@. W.nzval =-1.0*W.nzval
185
+
idxs =diagind(W)
186
+
@inbounds@views@. W[idxs] = W[idxs] +1
187
+
prectmp =ilu(W, τ = tau)
188
+
preccache =Ref(prectmp)
140
189
141
190
if forwardsensitivities
142
191
odefcn =ODEFunction(dydt;paramjac=jacp!)
@@ -149,20 +198,91 @@ function Reactor(domains::T,y0s::W,tspan::W2,interfaces::Z=Tuple(),ps::X=DiffEqB
Update preconditioner when Jacobian needs to be updated for Sundials solvers. Credit to tutorial of DifferentialEquations.jl.
223
+
p: the parameters
224
+
t: the current independent variable
225
+
u: the current state
226
+
du: the current f(u,p,t)
227
+
jok: a bool indicating whether the Jacobian needs to be updated
228
+
jcurPtr: a reference to an Int for whether the Jacobian was updated. jcurPtr[]=true should be set if the Jacobian was updated, and jcurPtr[]=false should be set if the Jacobian was not updated.
Compute preccache \\ r in-place and store the result in z for Sundials solver. Credit to tutorial of DifferentialEquations.jl.
249
+
z: the computed output vector
250
+
r: the right-hand side vector of the linear system
251
+
p: the parameters
252
+
t: the current independent variable
253
+
du: the current value of f(u,p,t)
254
+
gamma: the gamma of W = M - gamma*J
255
+
delta: the iterative method tolerance
256
+
lr: a flag for whether lr=1 (left) or lr=2 (right) preconditioning
257
+
preccache: preconditioner cache
258
+
"""
259
+
ldiv!(z,preccache[],r)
260
+
end
261
+
@inlinefunction_precsjulia(W::T1,du::T2,u::T3,p::T4,t::T5,newW::T6,Plprev::T7,Prprev::T8,solverdata::T9,tau::T10) where {T1,T2,T3,T4,T5,T6,T7,T8,T9,T10}
262
+
"""
263
+
Update preconditioner when Jacobian needs to be updated for Julia solvers. Credit to tutorial of DifferentialEquations.jl.
264
+
W: I - gamma*J or I/gamma - J depending on the algorithm.
265
+
Commonly be a WOperator type defined by OrdinaryDiffEq.jl. It is a lazy representation of the operator
266
+
Users can construct the W-matrix on demand by calling convert(AbstractMatrix,W) to receive an AbstractMatrix matching the jac_prototype.
267
+
du: the current ODE derivative
268
+
u: the current ODE state
269
+
p: the ODE parameters
270
+
t: the current ODE time
271
+
newW: a Bool which specifies whether the W matrix has been updated since the last call to precs.
272
+
It is recommended that this is checked to only update the preconditioner when newW == true.
273
+
Plprev: the previous Pl.
274
+
Prprev: the previous Pr.
275
+
solverdata: Optional extra data the solvers can give to the precs function. Solver-dependent and subject to change.
276
+
"""
277
+
if newW ===nothing|| newW
278
+
Pl =ilu(convert(AbstractMatrix,W), τ = tau)
279
+
else
280
+
Pl = Plprev
281
+
end
282
+
Pl,nothing
283
+
end
284
+
285
+
166
286
@inlinefunctiongetrate(rxn::T,cs::Array{W,1},kfs::Array{Q,1},krevs::Array{Q,1}) where {T<:AbstractReaction,Q,W<:Real}
0 commit comments