@@ -25,7 +25,7 @@ function build_mprk_matrix(P, sigma, dt, d = nothing)
2525end
2626
2727# in-place for dense arrays
28- function build_mprk_matrix! (M, P, sigma, dt, d = nothing )
28+ @muladd function build_mprk_matrix! (M, P, sigma, dt, d = nothing )
2929 # M[i,i] = (sigma[i] + dt * sum_j P[j,i]) / sigma[i]
3030 # M[i,j] = -dt * P[i,j] / sigma[j]
3131 # TODO : the performance of this can likely be improved
@@ -45,7 +45,7 @@ function build_mprk_matrix!(M, P, sigma, dt, d = nothing)
4545 # Add nonconservative destruction terms to diagonal (PDSFunctions only!)
4646 if ! isnothing (d)
4747 @inbounds for i in eachindex (d)
48- M[i, i] += dt * d[i]
48+ M[i, i] = M[i, i] + dt * d[i]
4949 end
5050 end
5151
@@ -72,7 +72,7 @@ function build_mprk_matrix!(M, P, sigma, dt, d = nothing)
7272end
7373
7474# optimized versions for Tridiagonal matrices
75- function build_mprk_matrix! (M:: Tridiagonal , P:: Tridiagonal , σ, dt, d = nothing )
75+ @muladd function build_mprk_matrix! (M:: Tridiagonal , P:: Tridiagonal , σ, dt, d = nothing )
7676 # M[i,i] = (sigma[i] + dt * sum_j P[j,i]) / sigma[i]
7777 # M[i,j] = -dt * P[i,j] / sigma[j]
7878 Base. require_one_based_indexing (M. dl, M. d, M. du,
@@ -122,7 +122,7 @@ The first-order modified Patankar-Euler algorithm for production-destruction sys
122122first-order accurate, unconditionally positivity-preserving, and
123123linearly implicit.
124124
125- The scheme was introduced by Burchard et al for conservative production-destruction systems.
125+ The scheme was introduced by Burchard et al for conservative production-destruction systems.
126126For nonconservative production–destruction systems we use the straight forward extension
127127
128128``u_i^{n+1} = u_i^n + Δt \\ sum_{j, j≠i} \\ biggl(p_{ij}^n \\ frac{u_j^{n+1}}{u_j^n}-d_{ij}^n \\ frac{u_i^{n+1}}{u_i^n}\\ biggr) + {\\ Delta}t p_{ii}^n - Δt d_{ii}^n\\ frac{u_i^{n+1}}{u_i^n}``.
@@ -133,7 +133,7 @@ The modified Patankar-Euler method requires the special structure of a
133133You can optionally choose the linear solver to be used by passing an
134134algorithm from [LinearSolve.jl](https://github.com/SciML/LinearSolve.jl)
135135as keyword argument `linsolve`.
136- You can also choose the parameter `small_constant` which is added to all Patankar-weight denominators
136+ You can also choose the parameter `small_constant` which is added to all Patankar-weight denominators
137137to avoid divisions by zero. You can pass a value explicitly, otherwise `small_constant` is set to
138138`floatmin` of the floating point type used.
139139
182182function initialize! (integrator, cache:: MPEConstantCache )
183183end
184184
185- function perform_step! (integrator, cache:: MPEConstantCache , repeat_step = false )
185+ @muladd function perform_step! (integrator, cache:: MPEConstantCache , repeat_step = false )
186186 @unpack alg, t, dt, uprev, f, p = integrator
187187 @unpack small_constant = cache
188188
@@ -241,7 +241,7 @@ function alg_cache(alg::MPE, u, rate_prototype, ::Type{uEltypeNoUnits},
241241 tab = MPEConstantCache (alg. small_constant_function (uEltypeNoUnits))
242242
243243 if f isa ConservativePDSFunction
244- # We use P to store the evaluation of the PDS
244+ # We use P to store the evaluation of the PDS
245245 # as well as to store the system matrix of the linear system
246246 # Right hand side of linear system is always uprev
247247 linprob = LinearProblem (P, _vec (uprev))
@@ -251,7 +251,7 @@ function alg_cache(alg::MPE, u, rate_prototype, ::Type{uEltypeNoUnits},
251251 MPEConservativeCache (P, σ, tab, linsolve)
252252 elseif f isa PDSFunction
253253 linsolve_rhs = zero (u)
254- # We use P to store the evaluation of the PDS
254+ # We use P to store the evaluation of the PDS
255255 # as well as to store the system matrix of the linear system
256256 linprob = LinearProblem (P, _vec (linsolve_rhs))
257257 linsolve = init (linprob, alg. linsolve, alias_A = true , alias_b = true ,
@@ -266,13 +266,13 @@ end
266266function initialize! (integrator, cache:: Union{MPECache, MPEConservativeCache} )
267267end
268268
269- function perform_step! (integrator, cache:: MPECache , repeat_step = false )
269+ @muladd function perform_step! (integrator, cache:: MPECache , repeat_step = false )
270270 @unpack t, dt, uprev, u, f, p = integrator
271271 @unpack P, D, σ, linsolve, linsolve_rhs = cache
272272 @unpack small_constant = cache. tab
273273
274- # We use P to store the evaluation of the PDS
275- # as well as to store the system matrix of the linear system
274+ # We use P to store the evaluation of the PDS
275+ # as well as to store the system matrix of the linear system
276276
277277 # We require the users to set unused entries to zero!
278278
@@ -298,13 +298,13 @@ function perform_step!(integrator, cache::MPECache, repeat_step = false)
298298 integrator. stats. nsolve += 1
299299end
300300
301- function perform_step! (integrator, cache:: MPEConservativeCache , repeat_step = false )
301+ @muladd function perform_step! (integrator, cache:: MPEConservativeCache , repeat_step = false )
302302 @unpack t, dt, uprev, u, f, p = integrator
303303 @unpack P, σ, linsolve = cache
304304 @unpack small_constant = cache. tab
305305
306- # We use P to store the evaluation of the PDS
307- # as well as to store the system matrix of the linear system
306+ # We use P to store the evaluation of the PDS
307+ # as well as to store the system matrix of the linear system
308308
309309 # We require the users to set unused entries to zero!
310310
@@ -328,14 +328,14 @@ end
328328"""
329329 MPRK22(α; [linsolve = ..., small_constant = ...])
330330
331- A family of second-order modified Patankar-Runge-Kutta algorithms for
331+ A family of second-order modified Patankar-Runge-Kutta algorithms for
332332production-destruction systems. Each member of this family is an one-step, two-stage method which is
333333second-order accurate, unconditionally positivity-preserving, and linearly
334334implicit. The parameter `α` is described by Kopecz and Meister (2018) and
335335studied by Izgin, Kopecz and Meister (2022) as well as
336336Torlo, Öffner and Ranocha (2022).
337337
338- The scheme was introduced by Kopecz and Meister for conservative production-destruction systems.
338+ The scheme was introduced by Kopecz and Meister for conservative production-destruction systems.
339339For nonconservative production–destruction systems we use the straight forward extension
340340analogous to [`MPE`](@ref).
341341
@@ -345,7 +345,7 @@ This modified Patankar-Runge-Kutta method requires the special structure of a
345345You can optionally choose the linear solver to be used by passing an
346346algorithm from [LinearSolve.jl](https://github.com/SciML/LinearSolve.jl)
347347as keyword argument `linsolve`.
348- You can also choose the parameter `small_constant` which is added to all Patankar-weight denominators
348+ You can also choose the parameter `small_constant` which is added to all Patankar-weight denominators
349349to avoid divisions by zero. You can pass a value explicitly, otherwise `small_constant` is set to
350350`floatmin` of the floating point type used.
351351
432432function initialize! (integrator, cache:: MPRK22ConstantCache )
433433end
434434
435- function perform_step! (integrator, cache:: MPRK22ConstantCache , repeat_step = false )
435+ @muladd function perform_step! (integrator, cache:: MPRK22ConstantCache , repeat_step = false )
436436 @unpack alg, t, dt, uprev, f, p = integrator
437437 @unpack a21, b1, b2, small_constant = cache
438438
@@ -537,7 +537,7 @@ function alg_cache(alg::MPRK22, u, rate_prototype, ::Type{uEltypeNoUnits},
537537 tab = MPRK22ConstantCache (a21, b1, b2, alg. small_constant_function (uEltypeNoUnits))
538538 tmp = zero (u)
539539 P = p_prototype (u, f)
540- # We use P2 to store the last evaluation of the PDS
540+ # We use P2 to store the last evaluation of the PDS
541541 # as well as to store the system matrix of the linear system
542542 P2 = p_prototype (u, f)
543543 σ = zero (u)
@@ -546,7 +546,7 @@ function alg_cache(alg::MPRK22, u, rate_prototype, ::Type{uEltypeNoUnits},
546546 # The right hand side of the linear system is always uprev. But using
547547 # tmp instead of uprev for the rhs we allow `alias_b=true`. uprev must
548548 # not be altered, since it is needed to compute the adaptive time step
549- # size.
549+ # size.
550550 linprob = LinearProblem (P2, _vec (tmp))
551551 linsolve = init (linprob, alg. linsolve, alias_A = true , alias_b = true ,
552552 assumptions = LinearSolve. OperatorAssumptions (true ))
@@ -563,7 +563,7 @@ function alg_cache(alg::MPRK22, u, rate_prototype, ::Type{uEltypeNoUnits},
563563 zero (u), # D
564564 zero (u), # D2
565565 σ,
566- tab, # MPRK22ConstantCache
566+ tab, # MPRK22ConstantCache
567567 linsolve)
568568 else
569569 throw (ArgumentError (" MPRK22 can only be applied to production-destruction systems" ))
@@ -573,12 +573,12 @@ end
573573function initialize! (integrator, cache:: Union{MPRK22Cache, MPRK22ConservativeCache} )
574574end
575575
576- function perform_step! (integrator, cache:: MPRK22Cache , repeat_step = false )
576+ @muladd function perform_step! (integrator, cache:: MPRK22Cache , repeat_step = false )
577577 @unpack t, dt, uprev, u, f, p = integrator
578578 @unpack tmp, P, P2, D, D2, σ, linsolve = cache
579579 @unpack a21, b1, b2, small_constant = cache. tab
580580
581- # We use P2 to store the last evaluation of the PDS
581+ # We use P2 to store the last evaluation of the PDS
582582 # as well as to store the system matrix of the linear system
583583
584584 f. p (P, uprev, p, t) # evaluate production terms
@@ -646,15 +646,16 @@ function perform_step!(integrator, cache::MPRK22Cache, repeat_step = false)
646646 integrator. EEst = integrator. opts. internalnorm (tmp, t)
647647end
648648
649- function perform_step! (integrator, cache:: MPRK22ConservativeCache , repeat_step = false )
649+ @muladd function perform_step! (integrator, cache:: MPRK22ConservativeCache ,
650+ repeat_step = false )
650651 @unpack t, dt, uprev, u, f, p = integrator
651652 @unpack tmp, P, P2, σ, linsolve = cache
652653 @unpack a21, b1, b2, small_constant = cache. tab
653654
654655 # Set right hand side of linear system
655656 tmp .= uprev
656657
657- # We use P2 to store the last evaluation of the PDS
658+ # We use P2 to store the last evaluation of the PDS
658659 # as well as to store the system matrix of the linear system
659660 f. p (P, uprev, p, t) # evaluate production terms
660661 integrator. stats. nf += 1
@@ -714,10 +715,10 @@ production-destruction systems, which is based on the two-parameter family of th
714715Each member of this family is a one-step method with four-stages which is
715716third-order accurate, unconditionally positivity-preserving, conservative and linearly
716717implicit. In this implementation the stage-values are conservative as well.
717- The parameters `α` and `β` must be chosen such that the Runge--Kutta coefficients are nonnegative,
718- see Kopecz and Meister (2018) for details.
718+ The parameters `α` and `β` must be chosen such that the Runge--Kutta coefficients are nonnegative,
719+ see Kopecz and Meister (2018) for details.
719720
720- The scheme was introduced by Kopecz and Meister for conservative production-destruction systems.
721+ The scheme was introduced by Kopecz and Meister for conservative production-destruction systems.
721722For nonconservative production–destruction systems we use the straight forward extension
722723analogous to [`MPE`](@ref).
723724
@@ -727,14 +728,14 @@ These modified Patankar-Runge-Kutta methods require the special structure of a
727728You can optionally choose the linear solver to be used by passing an
728729algorithm from [LinearSolve.jl](https://github.com/SciML/LinearSolve.jl)
729730as keyword argument `linsolve`.
730- You can also choose the parameter `small_constant` which is added to all Patankar-weight denominators
731+ You can also choose the parameter `small_constant` which is added to all Patankar-weight denominators
731732to avoid divisions by zero. You can pass a value explicitly, otherwise `small_constant` is set to
732733`floatmin` of the floating point type used.
733734
734735## References
735736
736737- Stefan Kopecz and Andreas Meister.
737- "Unconditionally positive and conservative third order modified Patankar–Runge–Kutta
738+ "Unconditionally positive and conservative third order modified Patankar–Runge–Kutta
738739 discretizations of production–destruction systems."
739740 BIT Numerical Mathematics 58 (2018): 691–728.
740741 [DOI: 10.1007/s10543-018-0705-1](https://doi.org/10.1007/s10543-018-0705-1)
@@ -809,15 +810,15 @@ end
809810 MPRK43II(γ; [linsolve = ..., small_constant = ...])
810811
811812A family of third-order modified Patankar-Runge-Kutta schemes for (conservative)
812- production-destruction systems, which is based on the one-parameter family of third order explicit Runge--Kutta schemes with
813+ production-destruction systems, which is based on the one-parameter family of third order explicit Runge--Kutta schemes with
813814non-negative Runge--Kutta coefficients.
814815Each member of this family is a one-step method with four stages which is
815816third-order accurate, unconditionally positivity-preserving, conservative and linearly
816817implicit. In this implementation the stage-values are conservative as well. The parameter `γ` must satisfy
817- `3/8 ≤ γ ≤ 3/4`.
818- Further details are given in Kopecz and Meister (2018).
818+ `3/8 ≤ γ ≤ 3/4`.
819+ Further details are given in Kopecz and Meister (2018).
819820
820- The scheme was introduced by Kopecz and Meister for conservative production-destruction systems.
821+ The scheme was introduced by Kopecz and Meister for conservative production-destruction systems.
821822For nonconservative production–destruction systems we use the straight forward extension
822823analogous to [`MPE`](@ref).
823824
@@ -827,14 +828,14 @@ These modified Patankar-Runge-Kutta methods require the special structure of a
827828You can optionally choose the linear solver to be used by passing an
828829algorithm from [LinearSolve.jl](https://github.com/SciML/LinearSolve.jl)
829830as keyword argument `linsolve`.
830- You can also choose the parameter `small_constant` which is added to all Patankar-weight denominators
831+ You can also choose the parameter `small_constant` which is added to all Patankar-weight denominators
831832to avoid divisions by zero. You can pass a value explicitly, otherwise `small_constant` is set to
832833`floatmin` of the floating point type used.
833834
834835## References
835836
836837- Stefan Kopecz and Andreas Meister.
837- "Unconditionally positive and conservative third order modified Patankar–Runge–Kutta
838+ "Unconditionally positive and conservative third order modified Patankar–Runge–Kutta
838839 discretizations of production–destruction systems."
839840 BIT Numerical Mathematics 58 (2018): 691–728.
840841 [DOI: 10.1007/s10543-018-0705-1](https://doi.org/10.1007/s10543-018-0705-1)
920921function initialize! (integrator, cache:: MPRK43ConstantCache )
921922end
922923
923- function perform_step! (integrator, cache:: MPRK43ConstantCache , repeat_step = false )
924+ @muladd function perform_step! (integrator, cache:: MPRK43ConstantCache , repeat_step = false )
924925 @unpack alg, t, dt, uprev, f, p = integrator
925926 @unpack a21, a31, a32, b1, b2, b3, c2, c3, beta1, beta2, q1, q2, small_constant = cache
926927
@@ -1078,7 +1079,7 @@ function alg_cache(alg::Union{MPRK43I, MPRK43II}, u, rate_prototype, ::Type{uElt
10781079 tmp2 = zero (u)
10791080 P = p_prototype (u, f)
10801081 P2 = p_prototype (u, f)
1081- # We use P3 to store the last evaluation of the PDS
1082+ # We use P3 to store the last evaluation of the PDS
10821083 # as well as to store the system matrix of the linear system
10831084 P3 = p_prototype (u, f)
10841085 σ = zero (u)
@@ -1087,7 +1088,7 @@ function alg_cache(alg::Union{MPRK43I, MPRK43II}, u, rate_prototype, ::Type{uElt
10871088 # The right hand side of the linear system is always uprev. But using
10881089 # tmp instead of uprev for the rhs we allow `alias_b=true`. uprev must
10891090 # not be altered, since it is needed to compute the adaptive time step
1090- # size.
1091+ # size.
10911092 linprob = LinearProblem (P3, _vec (tmp))
10921093 linsolve = init (linprob, alg. linsolve, alias_A = true , alias_b = true ,
10931094 assumptions = LinearSolve. OperatorAssumptions (true ))
@@ -1110,12 +1111,12 @@ end
11101111function initialize! (integrator, cache:: Union{MPRK43Cache, MPRK43ConservativeCache} )
11111112end
11121113
1113- function perform_step! (integrator, cache:: MPRK43Cache , repeat_step = false )
1114+ @muladd function perform_step! (integrator, cache:: MPRK43Cache , repeat_step = false )
11141115 @unpack t, dt, uprev, u, f, p = integrator
11151116 @unpack tmp, tmp2, P, P2, P3, D, D2, D3, σ, linsolve = cache
11161117 @unpack a21, a31, a32, b1, b2, b3, c2, c3, beta1, beta2, q1, q2, small_constant = cache. tab
11171118
1118- # We use P3 to store the last evaluation of the PDS
1119+ # We use P3 to store the last evaluation of the PDS
11191120 # as well as to store the system matrix of the linear system
11201121
11211122 f. p (P, uprev, p, t) # evaluate production terms
@@ -1225,15 +1226,16 @@ function perform_step!(integrator, cache::MPRK43Cache, repeat_step = false)
12251226 integrator. EEst = integrator. opts. internalnorm (tmp2, t)
12261227end
12271228
1228- function perform_step! (integrator, cache:: MPRK43ConservativeCache , repeat_step = false )
1229+ @muladd function perform_step! (integrator, cache:: MPRK43ConservativeCache ,
1230+ repeat_step = false )
12291231 @unpack t, dt, uprev, u, f, p = integrator
12301232 @unpack tmp, tmp2, P, P2, P3, σ, linsolve = cache
12311233 @unpack a21, a31, a32, b1, b2, b3, c2, c3, beta1, beta2, q1, q2, small_constant = cache. tab
12321234
12331235 # Set right hand side of linear system
12341236 tmp .= uprev
12351237
1236- # We use P3 to store the last evaluation of the PDS
1238+ # We use P3 to store the last evaluation of the PDS
12371239 # as well as to store the system matrix of the linear system
12381240 f. p (P, uprev, p, t) # evaluate production terms
12391241 @. . broadcast= false P3= a21 * P
0 commit comments