Skip to content

Commit c0a3ce6

Browse files
SKopeczranochaJoshuaLampert
authored
Some benchmarks for the documentation (#123)
* Added structure for benchmarks * bugfix and first benchmark * typo * extended npzd benchmark * bugfix * additional npzd benchmark * Added Robertson benchmark * bugfix * Stratospheric reaction benchmark * Added benchmark convergence order * added PrettyTables to toml file and bugfix * ??? * ??? * ??? * debugging * last try ... * cont. debugging * more debugging * more debugging * last try * bugfix * fingers crossed * Update docs/src/npzd_model_benchmark.md Co-authored-by: Hendrik Ranocha <[email protected]> * some test * added workprecision functions * skip some parts of docs * revised npzd benchmarks * add benchmarks with fixed time step size * bugfix * bugfix * revised npzd benchmark * typo * revised robertson benchmark * revised stratospheric reaction benchmark * revision of benchmarks * revised functions for work-precision diagrams and revised nzpd benchmark * robertson_benchmark is running (but needs revision) * stratospheric reaction benchmark is running (but needs revision) * typo * typos and additional explanations in npzd benchmark * revised converenge tutorial * use non-autonomous tests in convergence benchmark * revised convergence benchmark * revised robertson benchmark * revised robertson benchmark * typo * revised benchmarks * format * bugfix * benchmarks finished * bugfix * revised benchmark npzd * revised benchmarks once more * bugfix * added MPRK 0.5 to comparison * benchmark robertson mprk comparison changed axis * fix implicit imports test * add compat entry for statistics * hopefully fix Aqua CI error * fix typo * robertson bechnmark comparison mprk xticks * robertson benchmark use MPRK22(0.5) in all comparisons * added tests for utility functions * revised robertson benchmark with respect to MPRK22(0.5) * using median in runtests.jl * additional output in tests * set n=1000 in work_precision_XXX * set n=10000 in work_precision_XXX * Added Statistics in docs/Project.toml * Removed Statitstics from docs/Project.toml * Update src/utilities.jl Co-authored-by: Hendrik Ranocha <[email protected]> * Update src/utilities.jl Co-authored-by: Hendrik Ranocha <[email protected]> * Update src/utilities.jl Co-authored-by: Hendrik Ranocha <[email protected]> * Update src/utilities.jl Co-authored-by: Hendrik Ranocha <[email protected]> * Update src/utilities.jl Co-authored-by: Hendrik Ranocha <[email protected]> * added additional output to debug tests for work_precision functions * Improved tests for work_precision functions * format * removed autodiff=false since it is no longer necessary * use autodiff=false for problems that don't provide an extra ODEFunction * back to autodiff=false * added test for work_precision_adaptive with adaptively computed reference solution * no modification * added RecipesBase * added dependencies * format * use OrdinaryDiffEq in tutorials * corrections in convergence, npzd and robertson benchmark * corrections stratreac benchmark * add compat entry for Statistics * fix downgrade tests * Update docs/src/convergence.md Co-authored-by: Joshua Lampert <[email protected]> * Update docs/src/npzd_model_benchmark.md Co-authored-by: Joshua Lampert <[email protected]> * removed OrdinaryDiffEq from docs * Update docs/src/convergence.md Co-authored-by: Hendrik Ranocha <[email protected]> * Update src/utilities.jl Co-authored-by: Hendrik Ranocha <[email protected]> * Update src/utilities.jl Co-authored-by: Hendrik Ranocha <[email protected]> * Update src/utilities.jl Co-authored-by: Hendrik Ranocha <[email protected]> * Update docs/src/convergence.md Co-authored-by: Hendrik Ranocha <[email protected]> * Update docs/src/convergence.md Co-authored-by: Hendrik Ranocha <[email protected]> * Update docs/src/convergence.md Co-authored-by: Hendrik Ranocha <[email protected]> * Update docs/src/convergence.md Co-authored-by: Hendrik Ranocha <[email protected]> * Apply suggestions from code review Co-authored-by: Hendrik Ranocha <[email protected]> * Update docs/src/convergence.md Co-authored-by: Hendrik Ranocha <[email protected]> * Apply suggestions from code review Co-authored-by: Hendrik Ranocha <[email protected]> * discussion about changing small_constant for fixed step sizes * Apply suggestions from code review * show solutions for different values of small_constant * fixed problem in stratospheric benchmark * try to fix Aqua in Downgrade CI * skip persistent task test in Downgrade CI * fix * fix * Increased error tolerance in work_precision tests Co-authored-by: Hendrik Ranocha <[email protected]> --------- Co-authored-by: Hendrik Ranocha <[email protected]> Co-authored-by: Hendrik Ranocha <[email protected]> Co-authored-by: Joshua Lampert <[email protected]>
1 parent 00ed81f commit c0a3ce6

15 files changed

+1612
-10
lines changed

.github/workflows/Downgrade.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,4 @@ jobs:
5151
env:
5252
PYTHON: ""
5353
GKSwstype: "100" # for Plots/GR
54+
POSITIVEINTEGRATORS_DOWNGRADE_CI: "true"

Project.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
99
LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae"
1010
MuladdMacro = "46d2c3a1-f734-5fdb-9937-b9b9aeba4221"
1111
OrdinaryDiffEqCore = "bbf590c4-e513-4bbe-9b18-05decba2e5d8"
12+
RecipesBase = "3cdcf5f2-1ef4-517c-9805-6587b60abb01"
1213
Reexport = "189a3867-3050-52da-a836-e630ba90ab69"
1314
SciMLBase = "0bca4576-84f4-4d90-8ffe-ffa030f20462"
1415
SimpleUnPack = "ce78b400-467f-4804-87d8-8f486da07d0a"
1516
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
1617
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
18+
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
1719
SymbolicIndexingInterface = "2efcf032-c050-4f8e-a9bb-153293bab1f5"
1820

1921
[compat]
@@ -22,10 +24,12 @@ LinearAlgebra = "1"
2224
LinearSolve = "2.32"
2325
MuladdMacro = "0.2.4"
2426
OrdinaryDiffEqCore = "1.16"
27+
RecipesBase = "1.3.4"
2528
Reexport = "1.2.2"
2629
SciMLBase = "2.68"
2730
SimpleUnPack = "1"
2831
SparseArrays = "1"
2932
StaticArrays = "1.9.7"
33+
Statistics = "1"
3034
SymbolicIndexingInterface = "0.3.36"
3135
julia = "1.10"

docs/Project.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,40 @@
22
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
33
DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e"
44
DiffEqCallbacks = "459566f4-90b8-5000-8ac3-15dfb0a30def"
5+
DiffEqDevTools = "f3b72e0c-5b89-59e1-b016-84e28bfd966d"
56
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
67
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
78
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
89
LinearSolve = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae"
10+
OrdinaryDiffEqFIRK = "5960d6e9-dd7a-4743-88e7-cf307b64f125"
11+
OrdinaryDiffEqLowOrderRK = "1344f307-1e59-4825-a18e-ace9aa3fa4c6"
912
OrdinaryDiffEqRosenbrock = "43230ef6-c299-4910-a778-202eb28ce4ce"
13+
OrdinaryDiffEqSDIRK = "2d112036-d095-4a1e-ab9a-08536f3ecdbf"
14+
OrdinaryDiffEqTsit5 = "b1df2697-797e-41e3-8120-5422d3b24e4a"
15+
OrdinaryDiffEqVerner = "79d7bb75-1356-48c1-b8c0-6832512096c2"
1016
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
1117
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
18+
PrettyTables = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
1219
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
1320
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
1421

1522
[compat]
1623
BenchmarkTools = "1"
1724
DiffEqBase = "6.160"
1825
DiffEqCallbacks = "4"
26+
DiffEqDevTools = "2.45.1"
1927
Documenter = "1"
2028
InteractiveUtils = "1"
2129
LinearAlgebra = "1"
2230
LinearSolve = "2.32"
31+
OrdinaryDiffEqFIRK = "1.7"
32+
OrdinaryDiffEqLowOrderRK = "1.2"
2333
OrdinaryDiffEqRosenbrock = "1.4"
34+
OrdinaryDiffEqSDIRK = "1.2"
35+
OrdinaryDiffEqTsit5 = "1.1"
36+
OrdinaryDiffEqVerner = "1.1"
2437
Pkg = "1"
2538
Plots = "1"
39+
PrettyTables = "2.4.0"
2640
SparseArrays = "1"
2741
StaticArrays = "1.9.7"

docs/make.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ makedocs(modules = [PositiveIntegrators],
8282
"Heat Equation, Dirichlet BCs" => "heat_equation_dirichlet.md",
8383
"Scalar equation" => "scalar_pds.md"
8484
],
85+
"Benchmarks" => [
86+
"Experimental order of convergence" => "convergence.md",
87+
"NPZD model" => "npzd_model_benchmark.md",
88+
"Robertson problem" => "robertson_benchmark.md",
89+
"Stratospheric reaction problem" => "stratospheric_reaction_benchmark.md"
90+
],
8591
"Troubleshooting, FAQ" => "faq.md",
8692
"API reference" => "api_reference.md",
8793
"Contributing" => "contributing.md",

docs/src/api_reference.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,12 @@ SSPMPRK43
4242
```@docs
4343
isnegative
4444
isnonnegative
45+
rel_max_error_tend
46+
rel_max_error_overall
47+
rel_l1_error_tend
48+
rel_l2_error_tend
49+
work_precision_adaptive
50+
work_precision_adaptive!
51+
work_precision_fixed
52+
work_precision_fixed!
4553
```

docs/src/convergence.md

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
# [Experimental convergence order of MPRK schemes](@id convergence_mprk)
2+
3+
In this tutorial, we check that the implemented MPRK schemes have the expected order of convergence.
4+
5+
## Conservative production-destruction systems
6+
7+
First, we consider conservative production-destruction systems (PDS). To investigate the convergence order, we define the non-autonomous test problem
8+
9+
```math
10+
\begin{aligned}
11+
u_1' &= \cos(\pi t)^2 u_2 - \sin(2\pi t)^2 u_1, & u_1(0)&=0.9, \\
12+
u_2' & = \sin(2\pi t)^2 u_1 - \cos(\pi t)^2 u_2, & u_2(0)&=0.1,
13+
\end{aligned}
14+
```
15+
for ``0≤ t≤ 1``.
16+
The PDS is conservative since the sum of the right-hand side terms equals zero.
17+
An implementation of the problem is given next.
18+
19+
20+
```@example eoc
21+
using PositiveIntegrators
22+
23+
# define problem
24+
P(u, p, t) = [0.0 cos.(π * t) .^ 2 * u[2]; sin.(2 * π * t) .^ 2 * u[1] 0.0]
25+
prob = ConservativePDSProblem(P, [0.9; 0.1], (0.0, 1.0))
26+
27+
nothing # hide
28+
```
29+
30+
To use `analyticless_test_convergence` from [DiffEqDevTools.jl](https://github.com/SciML/DiffEqDevTools.jl), we need to pick a solver to compute the reference solution and specify tolerances.
31+
Since the problem is not stiff, we use the high-order explicit solver `Vern9()` from [OrdinaryDiffEqVerner.jl](https://docs.sciml.ai/OrdinaryDiffEq/stable/).
32+
Moreover, we choose time step sizes to investigate the convergence behavior.
33+
34+
```@example eoc
35+
using OrdinaryDiffEqVerner
36+
using DiffEqDevTools: analyticless_test_convergence
37+
38+
# solver and tolerances to compute reference solution
39+
test_setup = Dict(:alg => Vern9(), :reltol => 1e-14, :abstol => 1e-14)
40+
41+
# choose step sizes
42+
dts = 0.5 .^ (5:10)
43+
44+
nothing # hide
45+
```
46+
47+
### Second-order MPRK schemes
48+
49+
First, we test several second-order MPRK schemes.
50+
51+
```@example eoc
52+
# select schemes
53+
algs2 = [MPRK22(0.5); MPRK22(2.0 / 3.0); MPRK22(1.0); SSPMPRK22(0.5, 1.0)]
54+
labels2 = ["MPRK22(0.5)"; "MPRK22(2.0/3.0)"; "MPRK22(1.0)"; "SSPMPRK22(0.5, 1.0)"]
55+
56+
# compute errors and experimental order of convergence
57+
err_eoc = []
58+
for i in eachindex(algs2)
59+
sim = analyticless_test_convergence(dts, prob, algs2[i], test_setup)
60+
61+
err = sim.errors[:l∞]
62+
eoc = [NaN; -log2.(err[2:end] ./ err[1:(end - 1)])]
63+
64+
push!(err_eoc, tuple.(err, eoc))
65+
end
66+
```
67+
68+
Next, we print a table with the computed data.
69+
The table lists the errors obtained with the respective time step size ``Δ t`` as well as the estimated order of convergence in parentheses.
70+
71+
```@example eoc
72+
using Printf: @sprintf
73+
using PrettyTables: pretty_table
74+
75+
# gather data for table
76+
data = hcat(dts, reduce(hcat,err_eoc))
77+
78+
# print table
79+
formatter = (v, i, j) -> (j>1) ? (@sprintf "%5.2e (%4.2f) " v[1] v[2]) : (@sprintf "%5.2e " v)
80+
pretty_table(data, formatters = formatter, header = ["Δt"; labels2])
81+
```
82+
83+
The table shows that all schemes converge as expected.
84+
85+
### Third-order MPRK schemes
86+
87+
In this section, we proceed as above, but consider third-order MPRK schemes instead.
88+
89+
```@example eoc
90+
# select 3rd order schemes
91+
algs3 = [MPRK43I(1.0, 0.5); MPRK43I(0.5, 0.75); MPRK43II(0.5); MPRK43II(2.0 / 3.0);
92+
SSPMPRK43()]
93+
labels3 = ["MPRK43I(1.0,0.5)"; "MPRK43I(0.5, 0.75)"; "MPRK43II(0.5)"; "MPRK43II(2.0/3.0)";
94+
"SSPMPRK43()"]
95+
96+
# compute errors and experimental order of convergence
97+
err_eoc = []
98+
for i in eachindex(algs3)
99+
sim = analyticless_test_convergence(dts, prob, algs3[i], test_setup)
100+
101+
err = sim.errors[:l∞]
102+
eoc = [NaN; -log2.(err[2:end] ./ err[1:(end - 1)])]
103+
104+
push!(err_eoc, tuple.(err, eoc))
105+
end
106+
107+
# gather data for table
108+
data = hcat(dts, reduce(hcat,err_eoc))
109+
110+
# print table
111+
formatter = (v, i, j) -> (j>1) ? (@sprintf "%5.2e (%4.2f) " v[1] v[2]) : (@sprintf "%5.2e " v)
112+
pretty_table(data, formatters = formatter, header = ["Δt"; labels3])
113+
```
114+
115+
As above, the table shows that all schemes converge as expected.
116+
117+
## Non-conservative PDS
118+
119+
In this section we consider the non-autonomous but non-conservative test problem
120+
121+
```math
122+
\begin{aligned}
123+
u_1' &= \cos(\pi t)^2 u_2 - \sin(2\pi t)^2 u_1 - \cos(2\pi t)^2 u_1, & u_1(0)&=0.9,\\
124+
u_2' & = \sin(2\pi t)^2 u_1 - \cos(\pi t)^2 u_2 - \sin(\pi t)^2 u_2, & u_2(0)&=0.1,
125+
\end{aligned}
126+
```
127+
128+
for ``0≤ t≤ 1``.
129+
Since the sum of the right-hand side terms does not cancel, the PDS is indeed non-conservative.
130+
Hence, we need to use [`PDSProblem`](@ref) for its implementation.
131+
132+
```@example eoc
133+
# choose problem
134+
P(u, p, t) = [0.0 cos.(π * t) .^ 2 * u[2]; sin.(2 * π * t) .^ 2 * u[1] 0.0]
135+
D(u, p, t) = [cos.(2 * π * t) .^ 2 * u[1]; sin.(π * t) .^ 2 * u[2]]
136+
prob = PDSProblem(P, D, [0.9; 0.1], (0.0, 1.0))
137+
138+
nothing # hide
139+
```
140+
141+
The following sections will show that the selected MPRK schemes show the expected convergence order also for this non-conservative PDS.
142+
143+
### Second-order MPRK schemes
144+
145+
```@example eoc
146+
# compute errors and experimental order of convergence
147+
err_eoc = []
148+
for i in eachindex(algs2)
149+
sim = analyticless_test_convergence(dts, prob, algs2[i], test_setup)
150+
151+
err = sim.errors[:l∞]
152+
eoc = [NaN; -log2.(err[2:end] ./ err[1:(end - 1)])]
153+
154+
push!(err_eoc, tuple.(err, eoc))
155+
end
156+
157+
# gather data for table
158+
data = hcat(dts, reduce(hcat,err_eoc))
159+
160+
# print table
161+
formatter = (v, i, j) -> (j>1) ? (@sprintf "%5.2e (%4.2f) " v[1] v[2]) : (@sprintf "%5.2e " v)
162+
pretty_table(data, formatters = formatter, header = ["Δt"; labels2])
163+
```
164+
165+
### Third-order MPRK schemes
166+
167+
```@example eoc
168+
# compute errors and experimental order of convergence
169+
err_eoc = []
170+
for i in eachindex(algs3)
171+
sim = analyticless_test_convergence(dts, prob, algs3[i], test_setup)
172+
173+
err = sim.errors[:l∞]
174+
eoc = [NaN; -log2.(err[2:end] ./ err[1:(end - 1)])]
175+
176+
push!(err_eoc, tuple.(err, eoc))
177+
end
178+
179+
# gather data for table
180+
data = hcat(dts, reduce(hcat,err_eoc))
181+
182+
# print table
183+
formatter = (v, i, j) -> (j>1) ? (@sprintf "%5.2e (%4.2f) " v[1] v[2]) : (@sprintf "%5.2e " v)
184+
pretty_table(data, formatters = formatter, header = ["Δt"; labels3])
185+
```

docs/src/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ The application of MPRK schemes requires the ODE system to be represented as a p
3737
```math
3838
u_i'(t) = \sum_{j=1}^N \bigl(p_{ij}(t,\boldsymbol u) - d_{ij}(t,\boldsymbol u)\bigr),\quad i=1,\dots,N,
3939
```
40-
where ``\boldsymbol u=(u_1,\dots,u_n)^T`` is the vector of unknowns and both production terms ``p_{ij}(t,\boldsymbol u)`` and destruction terms ``d_{ij}(t,\boldsymbol u)`` must be nonnegative for all ``i,j=1,\dots,N``. The meaning behind ``p_{ij}`` and ``d_{ij}`` is as follows:
40+
where ``\boldsymbol u=(u_1,\dots,u_N)^T`` is the vector of unknowns and both production terms ``p_{ij}(t,\boldsymbol u)`` and destruction terms ``d_{ij}(t,\boldsymbol u)`` must be nonnegative for all ``i,j=1,\dots,N``. The meaning behind ``p_{ij}`` and ``d_{ij}`` is as follows:
4141
* ``p_{ij}`` with ``i\ne j`` represents the sum of all nonnegative terms which
4242
appear in equation ``i`` with a positive sign and in equation ``j`` with a negative sign.
4343
* ``d_{ij}`` with ``i\ne j`` represents the sum of all nonnegative terms which

0 commit comments

Comments
 (0)