@@ -62,8 +62,6 @@ function alg_cache(alg::MPLM22, u, rate_prototype, ::Type{uEltypeNoUnits},
6262 :: Val{true} ,
6363 verbose) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits}
6464 uprevprev = zero (u)
65- uprevprev[1 ] = 111.0
66- uprevprev[2 ] = 222.0
6765
6866 step = 1
6967 small_constant = alg. small_constant_function (uEltypeNoUnits)
@@ -111,6 +109,7 @@ struct MPLM33{F, T} <: OrdinaryDiffEqAlgorithm
111109end
112110
113111alg_order (alg:: MPLM33 ) = 3
112+ isfsal (:: MPLM33 ) = false
114113alg_extrapolates (alg:: MPLM33 ) = true # TODO : Should probably be false
115114
116115@cache mutable struct MPLM33oopCache{uType, PType, dType, T, T2} < :
@@ -157,13 +156,90 @@ function alg_cache(alg::MPLM33, u, rate_prototype, ::Type{uEltypeNoUnits},
157156 MPLM33oopCache (u, u, P, P, d, d, αβ, 1 , alg. small_constant_function (uEltypeNoUnits))
158157end
159158
159+ @cache mutable struct MPLM33Cache{uType, dType, T, PType, F, TabType} <: MPLMMutableCache
160+ uprevprev:: uType
161+ uprev3:: uType
162+ v:: uType
163+ vprev:: uType
164+ vprev2:: uType
165+ step:: Int
166+ small_constant:: T
167+ b:: uType # rhs of the linear system
168+ P:: PType
169+ P2:: PType
170+ P3:: PType
171+ A:: PType # system matrix of the linear system
172+ d:: dType
173+ d2:: dType
174+ d3:: dType
175+ d_sys:: dType
176+ σ:: uType
177+ linsolve:: F
178+ αβ:: TabType
179+ end
180+
181+ function alg_cache (alg:: MPLM33 , u, rate_prototype, :: Type{uEltypeNoUnits} ,
182+ :: Type{uBottomEltypeNoUnits} , :: Type{tTypeNoUnits} ,
183+ uprev, uprev2, f, t, dt, reltol, p, calck,
184+ :: Val{true} ,
185+ verbose) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits}
186+ uprevprev = zero (u)
187+ uprev3 = zero (u)
188+ v = zero (u)
189+ vprev = zero (u)
190+ vprev2 = zero (u)
191+ step = 1
192+ small_constant = alg. small_constant_function (uEltypeNoUnits)
193+ b = zero (u)
194+ P = p_prototype (u, f)
195+ P2 = p_prototype (u, f)
196+ P3 = p_prototype (u, f)
197+ A = p_prototype (u, f)
198+ σ = zero (u)
199+
200+ # MPLM33 coefficients
201+ α1 = zero (uEltypeNoUnits)
202+ α2 = zero (uEltypeNoUnits)
203+ α3 = one (uEltypeNoUnits)
204+ β1 = 9 / 4 * one (uEltypeNoUnits)
205+ β2 = zero (uEltypeNoUnits)
206+ β3 = 3 / 4 * one (uEltypeNoUnits)
207+ αβ = (α1, α2, α3, β1, β2, β3)
208+
209+ if f isa ConservativePDSFunction
210+ linprob = LinearProblem (A, _vec (b))
211+ linsolve = init (linprob, alg. linsolve,
212+ alias = LinearSolve. LinearAliasSpecifier (; alias_A = true ,
213+ alias_b = true ),
214+ assumptions = LinearSolve. OperatorAssumptions (true ))
215+
216+ MPLM33Cache (uprevprev, uprev3, v, vprev, vprev2, step, small_constant, b, P, P2, P3,
217+ A, nothing , nothing , nothing , nothing , σ,
218+ linsolve, αβ)
219+ elseif f isa PDSFunction
220+ linprob = LinearProblem (A, _vec (b))
221+ linsolve = init (linprob, alg. linsolve,
222+ alias = LinearSolve. LinearAliasSpecifier (; alias_A = true ,
223+ alias_b = true ),
224+ assumptions = LinearSolve. OperatorAssumptions (true ))
225+
226+ MPLM33Cache (uprevprev, uprev3, v, vprev, vprev2, step, small_constant, b, P, P2, P3,
227+ A,
228+ similar (u), similar (u), similar (u), similar (u),
229+ σ, linsolve, αβ)
230+ else
231+ throw (ArgumentError (" MPLM33 can only be applied to production-destruction systems" ))
232+ end
233+ end
234+
160235# ### MPLM43 ############################################################################
161236struct MPLM43{F, T} <: OrdinaryDiffEqAlgorithm
162237 linsolve:: F
163238 small_constant_function:: T
164239end
165240
166241alg_order (alg:: MPLM43 ) = 3
242+ isfsal (:: MPLM43 ) = false
167243alg_extrapolates (alg:: MPLM43 ) = true # TODO : Should probably be false
168244
169245@cache mutable struct MPLM43oopCache{uType, PType, dType, T, T2} < :
@@ -222,6 +298,7 @@ struct MPLM54{F, T} <: OrdinaryDiffEqAlgorithm
222298end
223299
224300alg_order (alg:: MPLM54 ) = 4
301+ isfsal (:: MPLM54 ) = false
225302alg_extrapolates (alg:: MPLM54 ) = true # TODO : Should probably be false
226303
227304@cache mutable struct MPLM54oopCache{uType, PType, dType, T, T2} < :
@@ -285,6 +362,7 @@ struct MPLM75{F, T} <: OrdinaryDiffEqAlgorithm
285362end
286363
287364alg_order (alg:: MPLM75 ) = 5
365+ isfsal (:: MPLM75 ) = false
288366alg_extrapolates (alg:: MPLM75 ) = true # TODO : Should probably be false
289367
290368@cache mutable struct MPLM75oopCache{uType, PType, dType, T, T2} < :
@@ -357,6 +435,7 @@ struct MPLM106{F, T} <: OrdinaryDiffEqAlgorithm
357435end
358436
359437alg_order (alg:: MPLM106 ) = 6
438+ isfsal (:: MPLM106 ) = false
360439alg_extrapolates (alg:: MPLM106 ) = true # TODO : Should probably be false
361440
362441@cache mutable struct MPLM106oopCache{uType, PType, dType, T, T2} < :
493572# TODO Use αβ in MPLM22
494573@muladd function perform_step_MPLM22_oop (P, d, dt, uprev, uprevprev, linsolve,
495574 small_constant)
575+
496576 # First σ approximation
497577 σ = add_small_constant (uprev, small_constant)
498578
502582 σ = add_small_constant (σ, small_constant)
503583
504584 u = basic_patankar_step (uprevprev, P, σ, 2 * dt, linsolve, d)
505-
506585 # statistics: 2 nsolve
507586
508587 return u
@@ -514,18 +593,16 @@ end
514593 @. . broadcast= false σ= uprev + small_constant
515594
516595 # use lincomb! to handle cases in which d2 is nothing
517- P2 .= P
518- lincomb! (d2, 1 , d)
596+ # P2 .= P
597+ # lincomb!(d2, 1, d)
519598
520- basic_patankar_step! (σ, uprev, P2, d2, σ, dt, linsolve)
599+ # basic_patankar_step!(σ, uprev, P2, d2, linsolve.A, σ, dt, linsolve)
600+ basic_patankar_step! (σ, uprev, P, d, linsolve. A, σ, dt, linsolve)
521601
522602 # Main step
523603 @. . broadcast= false σ= σ + small_constant
524604
525- P2 .= P
526- lincomb! (d2, 1 , d)
527-
528- basic_patankar_step! (u, uprevprev, P2, d2, σ, 2 * dt, linsolve)
605+ basic_patankar_step! (u, uprevprev, P, d, linsolve. A, σ, 2 * dt, linsolve)
529606
530607 # statistics: 2 nsolve
531608
555632 integrator. stats. nf += nf
556633 integrator. stats. nsolve += ns
557634 else
635+ # increase step counter
636+ cache. step += 1
637+
558638 # evaluate production matrix
559639 P, d = evaluate_pds (f, uprev, p, t)
560640 integrator. stats. nf += 1
593673 integrator. stats. nsolve += ns
594674 else
595675
676+ # increase step counter
677+ cache. step += 1
678+
596679 # evaluate production matrix
597680 evaluate_pds! (P, D, f, uprev, p, t)
598681 integrator. stats. nf += 1
647730
648731 return (v, u), t, nf, ns
649732end
733+
734+ @muladd function start_MPLM33! (v, tmp, P, P2, d, d2, t, dt, vprev, vprev2, σ, f, p,
735+ small_constant, linsolve)
736+
737+ # 1 macro step consists of 4 substeps
738+ dts = dt / 4
739+
740+ # ## first macro step ###############################################################
741+ # substep 1
742+ nf, ns = start_MPLM22! (v, P, d, t, dts, vprev, σ, f, p, small_constant, linsolve)
743+
744+ # substeps 2 - 4
745+ for _ in 1 : 3
746+ vprev2 .= vprev
747+ vprev .= v
748+
749+ evaluate_pds! (P, d, f, vprev, p, t)
750+ nf += 1
751+
752+ perform_step_MPLM22! (v, P, P2, d, d2, dts, vprev, vprev2, σ, linsolve,
753+ small_constant)
754+ t += dts
755+ ns += 2
756+ end
757+
758+ tmp .= v
759+
760+ # ## second macro step ############################################################
761+ for _ in 1 : 4
762+ vprev2 .= vprev
763+ vprev .= v
764+
765+ evaluate_pds! (P, d, f, vprev, p, t)
766+ nf += 1
767+
768+ perform_step_MPLM22! (v, P, P2, d, d2, dts, vprev, vprev2, σ, linsolve,
769+ small_constant)
770+ t += dts
771+ ns += 2
772+ end
773+
774+ return nf, ns
775+ end
776+
650777@muladd function perform_step_MPLM33_oop (P_tup, d_tup, dt, u_tup, linsolve, αβ,
651778 small_constant)
652779 P, P2, P3 = P_tup
@@ -668,14 +795,48 @@ end
668795 σ = add_small_constant (σ, small_constant)
669796
670797 Ptmp, dtmp = lincomb (β1, P, d, β2, P2, d2, β3, P3, d3)
798+
671799 v = α1 * uprev + α2 * uprevprev + α3 * uprev3
800+
672801 u = basic_patankar_step (v, Ptmp, σ, dt, linsolve, dtmp)
673802
674803 # statistics: 3 nsolve
675804
676805 return u
677806end
678807
808+ @muladd function perform_step_MPLM33! (u, P_tup, d_tup, dt, u_tup, σ, linsolve, αβ,
809+ small_constant)
810+ P, P2, P3 = P_tup
811+ d, d2, d3 = d_tup
812+ uprev, uprevprev, uprev3 = u_tup
813+ α1, α2, α3, β1, β2, β3 = αβ
814+
815+ # First σ approximation
816+ @. . broadcast= false σ= uprev + small_constant
817+
818+ basic_patankar_step! (σ, uprev, P, d, linsolve. A, σ, dt, linsolve)
819+
820+ # Second σ approximation
821+ @. . broadcast= false σ= σ + small_constant
822+
823+ basic_patankar_step! (σ, uprevprev, P, d, linsolve. A, σ, 2 * dt, linsolve)
824+
825+ # Main step
826+ @. . broadcast= false σ= σ + small_constant
827+
828+ lincomb! (P3, β1, P, β2, P2, β3, P3)
829+ lincomb! (d3, β1, d, β2, d2, β3, d3)
830+
831+ @. . broadcast= false linsolve. b= α1 * uprev + α2 * uprevprev + α3 * uprev3
832+
833+ basic_patankar_step! (u, linsolve. b, P3, d3, linsolve. A, σ, dt, linsolve)
834+
835+ # statistics: 3 nsolve
836+
837+ return nothing
838+ end
839+
679840@muladd function perform_step! (integrator, cache:: MPLM33oopCache , repeat_step = false )
680841 (; alg, t, dt, uprev, uprev2, f, p) = integrator
681842 (; uprevprev, uprev3, P2, P3, d2, d3, αβ, small_constant) = cache
720881
721882 cache. uprev3 = uprevprev
722883 cache. uprevprev = uprev
884+
723885 else
886+ # increase step count
887+ cache. step += 1
724888
725889 # evaluate production matrix
726890 P, d = evaluate_pds (f, uprev, p, t)
746910 cache. d2 = d
747911end
748912
913+ @muladd function perform_step! (integrator, cache:: MPLM33Cache , repeat_step = false )
914+ (; alg, t, dt, uprev, uprev2, u, f, p) = integrator
915+ (; uprevprev, uprev3, v, vprev, vprev2, P, P2, P3, d, d2, d3, σ, αβ, small_constant, linsolve) = cache
916+
917+ # TODO : is this necessary?
918+ if integrator. u_modified
919+ cache. step = 1
920+ end
921+
922+ if cache. step == 1
923+ # increase step count
924+ cache. step += 1
925+
926+ # initilialze vprev
927+ vprev .= uprev
928+
929+ # evaluate production matrix at tspan[1]
930+ evaluate_pds! (P, d, f, uprev, p, t)
931+ integrator. stats. nf += 1
932+
933+ # save current P
934+ P3 .= P
935+
936+ # compute initial values for MPLM33
937+
938+ # we use uprev3 as temporary storage for the value of u needed in step 1.
939+ nf, ns = start_MPLM33! (v, uprev3, P, P2, d, d2, t, dt, vprev, vprev2, σ, f, p,
940+ small_constant,
941+ linsolve)
942+ integrator. stats. nf += nf
943+ integrator. stats. nsolve += ns
944+
945+ # reset P
946+ P .= P3
947+
948+ # u at time tspan[1] + dt
949+ u .= uprev3
950+
951+ # we use uprev3 as temporary storage for the value of u needed in step 2.
952+ uprev3 .= v
953+
954+ uprevprev .= uprev
955+
956+ elseif cache. step == 2
957+ # increase step count
958+ cache. step += 1
959+
960+ # evaluate production matrix at tspan[1] + dt
961+ evaluate_pds! (P, d, f, uprev, p, t)
962+ integrator. stats. nf += 1
963+
964+ # u at time tspan[1] + 2*dt (this was computed in step 1)
965+ u .= uprev3
966+
967+ uprev3 .= uprevprev
968+ uprevprev .= uprev
969+
970+ else
971+ # increase step count
972+ cache. step += 1
973+
974+ # evaluate production matrix
975+ evaluate_pds! (P, d, f, uprev, p, t)
976+ integrator. stats. nf += 1
977+
978+ P_tup = (P, P2, P3)
979+ d_tup = (d, d2, d3)
980+ u_tup = (uprev, uprevprev, uprev3)
981+
982+ perform_step_MPLM33! (u, P_tup, d_tup, dt, u_tup, σ, linsolve, αβ,
983+ small_constant)
984+ integrator. stats. nsolve += 3
985+
986+ uprev3 .= uprevprev
987+ uprevprev .= uprev
988+ end
989+
990+ P3 .= P2
991+ P2 .= P
992+ ! isnothing (d2) && (d3 .= d2)
993+ ! isnothing (d) && (d2 .= d)
994+ end
995+
749996# ### MPLM43 ############################################################################
750997@muladd function start_MPLM43_oop (P, d, t, dt, uprev, f, p, small_constant, linsolve)
751998 αβ33 = (0 , 0 , 1 , 9 / 4 , 0 , 3 / 4 )
0 commit comments