|
1 | 1 | ### SSPMPRK ##################################################################################### |
2 | 2 | """ |
3 | | - SSPMPRK22(α, β; [linsolve = ...]) |
| 3 | + SSPMPRK22(α, β; [linsolve = ..., small_constant = ...]) |
4 | 4 |
|
5 | 5 | A family of second-order modified Patankar-Runge-Kutta algorithms for |
6 | 6 | production-destruction systems. Each member of this family is a one-step, two-stage method which is |
@@ -36,16 +36,25 @@ to avoid divisions by zero. |
36 | 36 | ESAIM: Mathematical Modelling and Numerical Analysis 57 (2023):1063–1086 |
37 | 37 | [DOI: 10.1051/m2an/2023005](https://doi.org/10.1051/m2an/2023005) |
38 | 38 | """ |
39 | | -struct SSPMPRK22{T, F} <: OrdinaryDiffEqAdaptiveAlgorithm |
| 39 | +struct SSPMPRK22{T, F, T2} <: OrdinaryDiffEqAdaptiveAlgorithm |
40 | 40 | alpha::T |
41 | 41 | beta::T |
42 | 42 | linsolve::F |
43 | | - small_constant::T |
| 43 | + small_constant_function::T2 |
44 | 44 | end |
45 | 45 |
|
46 | 46 | function SSPMPRK22(alpha, beta; linsolve = LUFactorization(), |
47 | | - small_constant = floatmin(alpha)) |
48 | | - SSPMPRK22{typeof(alpha), typeof(linsolve)}(alpha, beta, linsolve, small_constant) |
| 47 | + small_constant = nothing) |
| 48 | + if isnothing(small_constant) |
| 49 | + small_constant_function = floatmin |
| 50 | + elseif small_constant isa Number |
| 51 | + small_constant_function = Returns(small_constant) |
| 52 | + else # assume small_constant isa Function |
| 53 | + small_constant_function = small_constant |
| 54 | + end |
| 55 | + SSPMPRK22{typeof(alpha), typeof(linsolve), typeof(small_constant_function)}(alpha, beta, |
| 56 | + linsolve, |
| 57 | + small_constant_function) |
49 | 58 | end |
50 | 59 |
|
51 | 60 | alg_order(::SSPMPRK22) = 2 |
@@ -95,8 +104,8 @@ function alg_cache(alg::SSPMPRK22, u, rate_prototype, ::Type{uEltypeNoUnits}, |
95 | 104 | end |
96 | 105 |
|
97 | 106 | a21, a10, a20, b10, b20, b21, s = get_constant_parameters(alg) |
98 | | - small_constant = alg.small_constant |
99 | | - SSPMPRK22ConstantCache(a21, a10, a20, b10, b20, b21, s, small_constant) |
| 107 | + SSPMPRK22ConstantCache(a21, a10, a20, b10, b20, b21, s, |
| 108 | + alg.small_constant_function(uEltypeNoUnits)) |
100 | 109 | end |
101 | 110 |
|
102 | 111 | function initialize!(integrator, cache::SSPMPRK22ConstantCache) |
@@ -204,8 +213,8 @@ function alg_cache(alg::SSPMPRK22, u, rate_prototype, ::Type{uEltypeNoUnits}, |
204 | 213 | uprev, uprev2, f, t, dt, reltol, p, calck, |
205 | 214 | ::Val{true}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} |
206 | 215 | a21, a10, a20, b10, b20, b21, s = get_constant_parameters(alg) |
207 | | - small_constant = alg.small_constant |
208 | | - tab = SSPMPRK22ConstantCache(a21, a10, a20, b10, b20, b21, s, small_constant) |
| 216 | + tab = SSPMPRK22ConstantCache(a21, a10, a20, b10, b20, b21, s, |
| 217 | + alg.small_constant_function(uEltypeNoUnits)) |
209 | 218 | tmp = zero(u) |
210 | 219 | P = p_prototype(u, f) |
211 | 220 | # We use P2 to store the last evaluation of the PDS |
@@ -378,7 +387,7 @@ function perform_step!(integrator, cache::SSPMPRK22ConservativeCache, repeat_ste |
378 | 387 | end |
379 | 388 |
|
380 | 389 | """ |
381 | | - SSPMPRK43([linsolve = ...]) |
| 390 | + SSPMPRK43([linsolve = ..., small_constant = ...]) |
382 | 391 |
|
383 | 392 | A third-order modified Patankar-Runge-Kutta algorithm for |
384 | 393 | production-destruction systems. This scheme is a one-step, two-stage method which is |
@@ -415,11 +424,19 @@ to avoid divisions by zero. |
415 | 424 | """ |
416 | 425 | struct SSPMPRK43{F, T} <: OrdinaryDiffEqAlgorithm |
417 | 426 | linsolve::F |
418 | | - small_constant::T |
| 427 | + small_constant_function::T |
419 | 428 | end |
420 | 429 |
|
421 | 430 | function SSPMPRK43(; linsolve = LUFactorization(), small_constant = 1e-50) |
422 | | - SSPMPRK43{typeof(linsolve), typeof(small_constant)}(linsolve, small_constant) |
| 431 | + if isnothing(small_constant) |
| 432 | + small_constant_function = floatmin |
| 433 | + elseif small_constant isa Number |
| 434 | + small_constant_function = Returns(small_constant) |
| 435 | + else # assume small_constant isa Function |
| 436 | + small_constant_function = small_constant |
| 437 | + end |
| 438 | + SSPMPRK43{typeof(linsolve), typeof(small_constant_function)}(linsolve, |
| 439 | + small_constant_function) |
423 | 440 | end |
424 | 441 |
|
425 | 442 | alg_order(::SSPMPRK43) = 3 |
@@ -496,11 +513,10 @@ function alg_cache(alg::SSPMPRK43, u, rate_prototype, ::Type{uEltypeNoUnits}, |
496 | 513 | throw(ArgumentError("SSPMPRK43 can only be applied to production-destruction systems")) |
497 | 514 | end |
498 | 515 | n1, n2, z, η1, η2, η3, η4, η5, η6, s, α10, α20, α21, α30, α31, α32, β10, β20, β21, β30, β31, β32, c3 = get_constant_parameters(alg) |
499 | | - small_constant = alg.small_constant |
500 | 516 | SSPMPRK43ConstantCache(n1, n2, z, η1, η2, η3, η4, η5, η6, s, α10, α20, α21, α30, α31, |
501 | 517 | α32, β10, |
502 | 518 | β20, β21, β30, |
503 | | - β31, β32, c3, small_constant) |
| 519 | + β31, β32, c3, alg.small_constant_function(uEltypeNoUnits)) |
504 | 520 | end |
505 | 521 |
|
506 | 522 | function initialize!(integrator, cache::SSPMPRK43ConstantCache) |
@@ -662,10 +678,10 @@ function alg_cache(alg::SSPMPRK43, u, rate_prototype, ::Type{uEltypeNoUnits}, |
662 | 678 | uprev, uprev2, f, t, dt, reltol, p, calck, |
663 | 679 | ::Val{true}) where {uEltypeNoUnits, uBottomEltypeNoUnits, tTypeNoUnits} |
664 | 680 | n1, n2, z, η1, η2, η3, η4, η5, η6, s, α10, α20, α21, α30, α31, α32, β10, β20, β21, β30, β31, β32, c3 = get_constant_parameters(alg) |
665 | | - small_constant = alg.small_constant |
666 | 681 | tab = SSPMPRK43ConstantCache(n1, n2, z, η1, η2, η3, η4, η5, η6, s, α10, α20, α21, α30, |
667 | 682 | α31, α32, |
668 | | - β10, β20, β21, β30, β31, β32, c3, small_constant) |
| 683 | + β10, β20, β21, β30, β31, β32, c3, |
| 684 | + alg.small_constant_function(uEltypeNoUnits)) |
669 | 685 | tmp = zero(u) |
670 | 686 | tmp2 = zero(u) |
671 | 687 | P = p_prototype(u, f) |
|
0 commit comments