@@ -5,7 +5,8 @@ abstract type AbstractPDSProblem end
55 PDSProblem(P, D, u0, tspan, p = NullParameters();
66 p_prototype = nothing,
77 analytic = nothing,
8- std_rhs = nothing)
8+ std_rhs = nothing,
9+ linear_invariants = nothing)
910
1011A structure describing a system of ordinary differential equations in form of a production-destruction system (PDS).
1112`P` denotes the function defining the production matrix ``P``.
@@ -31,6 +32,9 @@ The functions `P` and `D` can be used either in the out-of-place form with signa
3132 the production-destruction representation of the ODE, will use this function
3233 instead to compute the solution. If not specified,
3334 a default implementation calling `P` and `D` is used.
35+ -`linear_invariants`: The rows of this matrix contain the linear invariants of the ODE.
36+ Certain solvers or callbacks require this matrix.
37+ Note that this feature is experimental and its API may change in future releases.
3438
3539## References
3640
@@ -43,14 +47,15 @@ The functions `P` and `D` can be used either in the out-of-place form with signa
4347struct PDSProblem{iip} <: AbstractPDSProblem end
4448
4549# New ODE function PDSFunction
46- struct PDSFunction{iip, specialize, P, D, PrototypeP, PrototypeD, StdRHS, Ta} < :
50+ struct PDSFunction{iip, specialize, P, D, PrototypeP, PrototypeD, StdRHS, Ta, LI } < :
4751 AbstractODEFunction{iip}
4852 p:: P
4953 d:: D
5054 p_prototype:: PrototypeP
5155 d_prototype:: PrototypeD
5256 std_rhs:: StdRHS
5357 analytic:: Ta
58+ linear_invariants:: LI
5459end
5560
5661# define behavior of PDSFunctions for non-existing fields
@@ -73,8 +78,7 @@ function Base.getproperty(obj::PDSFunction, sym::Symbol)
7378end
7479
7580# Most general constructor for PDSProblems
76- function PDSProblem (P, D, u0, tspan, p = NullParameters ();
77- kwargs... )
81+ function PDSProblem (P, D, u0, tspan, p = NullParameters (); kwargs... )
7882 Piip = isinplace (P, 4 )
7983 Diip = isinplace (D, 4 )
8084 if Piip == Diip
8791
8892# Specialized constructor for PDSProblems setting `iip` manually
8993# (arbitrary functions)
90- function PDSProblem {iip} (P, D, u0, tspan, p = NullParameters ();
94+ function PDSProblem {iip} (P,
95+ D,
96+ u0,
97+ tspan,
98+ p = NullParameters ();
9199 p_prototype = nothing ,
92100 analytic = nothing ,
93101 std_rhs = nothing ,
94- kwargs... ) where {iip}
102+ linear_invariants = nothing ,
103+ kwargs... ,) where {iip}
95104
96105 # p_prototype is used to store evaluations of P, if P is in-place.
97106 if isnothing (p_prototype) && iip
@@ -101,8 +110,8 @@ function PDSProblem{iip}(P, D, u0, tspan, p = NullParameters();
101110 # evaluations of D.
102111 d_prototype = similar (u0 ./ oneunit (first (tspan)))
103112
104- PD = PDSFunction {iip} (P, D; p_prototype, d_prototype,
105- analytic, std_rhs )
113+ PD = PDSFunction {iip} (P, D; p_prototype, d_prototype, analytic, std_rhs,
114+ linear_invariants )
106115 PDSProblem {iip} (PD, u0, tspan, p; kwargs... )
107116end
108117
@@ -119,18 +128,26 @@ function PDSFunction{iip}(P, D; kwargs...) where {iip}
119128end
120129
121130# Most specific constructor for PDSFunction
122- function PDSFunction {iip, FullSpecialize} (P, D;
131+ function PDSFunction {iip, FullSpecialize} (P,
132+ D;
123133 p_prototype = nothing ,
124134 d_prototype = nothing ,
125135 analytic = nothing ,
126- std_rhs = nothing ) where {iip}
136+ std_rhs = nothing ,
137+ linear_invariants = nothing ,) where {iip}
127138 if std_rhs === nothing
128139 std_rhs = PDSStdRHS (P, D, p_prototype, d_prototype)
129140 end
130- PDSFunction{iip, FullSpecialize, typeof (P), typeof (D), typeof (p_prototype),
141+ PDSFunction{iip,
142+ FullSpecialize,
143+ typeof (P),
144+ typeof (D),
145+ typeof (p_prototype),
131146 typeof (d_prototype),
132- typeof (std_rhs), typeof (analytic)}(P, D, p_prototype, d_prototype, std_rhs,
133- analytic)
147+ typeof (std_rhs),
148+ typeof (analytic),
149+ typeof (linear_invariants)}(P, D, p_prototype, d_prototype, std_rhs,
150+ analytic, linear_invariants)
134151end
135152
136153# Evaluation of a PDSFunction
165182function (PD:: PDSStdRHS )(u, p, t)
166183 P = PD. p (u, p, t)
167184 D = PD. d (u, p, t)
168- diag (P) + vec (sum (P, dims = 2 )) -
169- vec (sum (P, dims = 1 )) - vec (D)
185+ diag (P) + vec (sum (P; dims = 2 )) - vec (sum (P; dims = 1 )) - vec (D)
170186end
171187
172188# Evaluation of a PDSStdRHS (in-place)
203219 ConservativePDSProblem(P, u0, tspan, p = NullParameters();
204220 p_prototype = nothing,
205221 analytic = nothing,
206- std_rhs = nothing)
222+ std_rhs = nothing,
223+ linear_invariants = nothing)
207224
208225A structure describing a conservative system of ordinary differential equation in form of a production-destruction system (PDS).
209226`P` denotes the function defining the production matrix ``P``.
@@ -227,7 +244,10 @@ The function `P` can be given either in the out-of-place form with signature
227244 as `std_rhs(du, u, p, t)` for the in-place form. Solvers that do not rely on
228245 the production-destruction representation of the ODE, will use this function
229246 instead to compute the solution. If not specified,
230- a default implementation calling `P` is used.
247+ a default implementation calling `P` is used
248+ -`linear_invariants`: The rows of this matrix contain the linear invariants of the ODE.
249+ Certain solvers or callbacks require this matrix.
250+ Note that this feature is experimental and its API may change in future releases.
231251
232252## References
233253
@@ -240,12 +260,13 @@ The function `P` can be given either in the out-of-place form with signature
240260struct ConservativePDSProblem{iip} <: AbstractPDSProblem end
241261
242262# New ODE function ConservativePDSFunction
243- struct ConservativePDSFunction{iip, specialize, P, PrototypeP, StdRHS, Ta} < :
263+ struct ConservativePDSFunction{iip, specialize, P, PrototypeP, StdRHS, Ta, LI } < :
244264 AbstractODEFunction{iip}
245265 p:: P # production terms
246266 p_prototype:: PrototypeP # prototype for production terms
247267 std_rhs:: StdRHS # standard right-hand side evaluation function
248268 analytic:: Ta # analytic solution (or nothing)
269+ linear_invariants:: LI
249270end
250271
251272# define behavior of ConservativePDSFunction for non-existing fields
@@ -268,26 +289,29 @@ function Base.getproperty(obj::ConservativePDSFunction, sym::Symbol)
268289end
269290
270291# Most general constructor for ConservativePDSProblems
271- function ConservativePDSProblem (P, u0, tspan, p = NullParameters ();
272- kwargs... )
292+ function ConservativePDSProblem (P, u0, tspan, p = NullParameters (); kwargs... )
273293 iip = isinplace (P, 4 )
274294 return ConservativePDSProblem {iip} (P, u0, tspan, p; kwargs... )
275295end
276296
277297# Specialized constructor for ConservativePDSProblems setting `iip` manually
278- # (arbitrary function)
279- function ConservativePDSProblem {iip} (P, u0, tspan, p = NullParameters ();
298+ # (arbitrary function)
299+ function ConservativePDSProblem {iip} (P,
300+ u0,
301+ tspan,
302+ p = NullParameters ();
280303 p_prototype = nothing ,
281304 analytic = nothing ,
282305 std_rhs = nothing ,
283- kwargs... ) where {iip}
306+ linear_invariants = nothing ,
307+ kwargs... ,) where {iip}
284308
285309 # p_prototype is used to store evaluations of P, if P is in-place.
286310 if isnothing (p_prototype) && iip
287311 p_prototype = zeros (eltype (u0), (length (u0), length (u0))) / oneunit (first (tspan))
288312 end
289313
290- PD = ConservativePDSFunction {iip} (P; p_prototype, analytic, std_rhs)
314+ PD = ConservativePDSFunction {iip} (P; p_prototype, analytic, std_rhs, linear_invariants )
291315 ConservativePDSProblem {iip} (PD, u0, tspan, p; kwargs... )
292316end
293317
@@ -304,16 +328,20 @@ function ConservativePDSFunction{iip}(P; kwargs...) where {iip}
304328end
305329
306330# Most specific constructor for ConservativePDSFunction
307- function ConservativePDSFunction {iip, FullSpecialize} (P;
308- p_prototype = nothing ,
309- analytic = nothing ,
310- std_rhs = nothing ) where {iip}
331+ function ConservativePDSFunction {iip, FullSpecialize} (P; p_prototype = nothing ,
332+ analytic = nothing , std_rhs = nothing ,
333+ linear_invariants = nothing ) where {iip}
311334 if std_rhs === nothing
312335 std_rhs = ConservativePDSStdRHS (P, p_prototype)
313336 end
314- ConservativePDSFunction{iip, FullSpecialize, typeof (P), typeof (p_prototype),
315- typeof (std_rhs), typeof (analytic)}(P, p_prototype, std_rhs,
316- analytic)
337+ ConservativePDSFunction{iip,
338+ FullSpecialize,
339+ typeof (P),
340+ typeof (p_prototype),
341+ typeof (std_rhs),
342+ typeof (analytic),
343+ typeof (linear_invariants)}(P, p_prototype, std_rhs, analytic,
344+ linear_invariants)
317345end
318346
319347# Evaluation of a ConservativePDSFunction
0 commit comments