Skip to content

Commit d415eac

Browse files
Merge pull request #129 from nathanaelbosch/plotrecipe_update
Update the plotting recipe to flexibly plot some x against some y
2 parents d640594 + 5f3b20e commit d415eac

File tree

3 files changed

+77
-11
lines changed

3 files changed

+77
-11
lines changed

src/DiffEqDevTools.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ const WEAK_TIMESERIES_ERRORS = Set([:weak_l2, :weak_l∞])
2323
const WEAK_DENSE_ERRORS = Set([:weak_L2, :weak_L∞])
2424
const WEAK_ERRORS = union(Set([:weak_final]),
2525
WEAK_TIMESERIES_ERRORS, WEAK_DENSE_ERRORS)
26+
const ALL_ERRORS = union([:final],
27+
TIMESERIES_ERRORS, DENSE_ERRORS, WEAK_TIMESERIES_ERRORS, WEAK_DENSE_ERRORS, WEAK_ERRORS)
2628

2729
include("benchmark.jl")
2830
include("convergence.jl")

src/plotrecipes.jl

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,80 @@ end
3838
return errors, wp.times
3939
end
4040

41-
@recipe function f(wp_set::WorkPrecisionSet; view = :benchmark, color = nothing)
41+
function get_val_from_wp(wp::WorkPrecision, key::Symbol)
42+
if key == :abstols
43+
return wp.abstols
44+
elseif key == :reltols
45+
return wp.reltols
46+
elseif key == :times
47+
return wp.times
48+
elseif key == :dts
49+
return wp.dts
50+
elseif !isnothing(wp.stats) && key in propertynames(wp.stats[1])
51+
return [getproperty(s, key) for s in wp.stats]
52+
elseif key in propertynames(wp.errors)
53+
return getproperty(wp.errors, key)
54+
else
55+
throw(ArgumentError("Key $key does not specify a valid property of WorkPrecision"))
56+
end
57+
end
58+
59+
function key_to_label(key::Symbol)
60+
if key == :abstols
61+
return "Absolute tolerance"
62+
elseif key == :reltols
63+
return "Relative tolerance"
64+
elseif key == :times
65+
return "Time (s)"
66+
elseif key == :dts
67+
return "Δt"
68+
elseif key in ALL_ERRORS
69+
return "Error ($key)"
70+
# Some DEStats cases copied from SciMLBase: src/solutions/ode_solutions.jl#L43-L56
71+
elseif key == :nf
72+
return "Number of function evaluations"
73+
elseif key == :nf2
74+
return "Number of function 2 evaluations"
75+
elseif key == :nw
76+
return "Number of W matrix evaluations"
77+
elseif key == :nsolve
78+
return "Number of linear solves"
79+
elseif key == :njacs
80+
return "Number of Jacobians created"
81+
elseif key == :nnonliniter
82+
return "Number of nonlinear solver iterations"
83+
elseif key == :nnonlinconvfail
84+
return "Number of nonlinear solver convergence failures"
85+
elseif key == :ncondition
86+
return "Number of rootfind condition calls"
87+
elseif key == :naccept
88+
return "Number of accepted steps"
89+
elseif key == :nreject
90+
return "Number of rejected steps"
91+
elseif key == :maxeig
92+
return "Maximum eigenvalue recorded"
93+
else
94+
return key
95+
end
96+
end
97+
98+
@recipe function f(wp_set::WorkPrecisionSet;
99+
x::Symbol = wp_set.error_estimate,
100+
y::Symbol = :times,
101+
view = :benchmark,
102+
color = nothing)
42103
if view == :benchmark
43104
seriestype --> :path
44105
linewidth --> 3
45-
yguide --> "Time (s)"
46-
xguide --> "Error ($(wp_set.error_estimate))"
47106
xscale --> :log10
48107
yscale --> :log10
49108
markershape --> :auto
50-
errors = Vector{Any}(undef, 0)
51-
times = Vector{Any}(undef, 0)
52-
for i in 1:length(wp_set)
53-
push!(errors, getproperty(wp_set[i].errors, wp_set.error_estimate))
54-
push!(times, wp_set[i].times)
55-
end
109+
xs = [get_val_from_wp(wp, x) for wp in wp_set.wps]
110+
ys = [get_val_from_wp(wp, y) for wp in wp_set.wps]
111+
xguide --> key_to_label(x)
112+
yguide --> key_to_label(y)
56113
label --> reshape(wp_set.names, 1, length(wp_set))
57-
return errors, times
114+
return xs, ys
58115
elseif view == :dt_convergence
59116
idts = filter(i -> haskey(wp_set.setups[i], :dts), 1:length(wp_set))
60117
length(idts) > 0 ||
@@ -90,7 +147,7 @@ end
90147
seriestype --> :path
91148
linewidth --> 3
92149
color --> color
93-
yguide --> "Error"
150+
yguide --> "Error ($(wp_set.error_estimate))"
94151
xguide --> "Δt"
95152
xscale --> :log10
96153
yscale --> :log10

test/plotrecipes_tests.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ gr()
4242
@test_nowarn plot(wp, color = :blue)
4343
@test_throws ArgumentError plot(wp, view = :dt_convergence)
4444

45+
@test_nowarn plot(wp, x = :abstols, y = :final)
46+
@test_nowarn plot(wp, x = :reltols, y = :nf)
47+
@test_nowarn plot(wp, x = :naccept, y = :nreject)
48+
@test_throws ArgumentError plot(wp, x = :notakey, y = :final)
49+
4550
dts = 1.0 ./ 2.0 .^ ((1:length(reltols)) .+ 1)
4651
setups = [Dict(:alg => Euler(), :dts => dts)
4752
Dict(:alg => Heun(), :dts => dts)
@@ -56,6 +61,8 @@ gr()
5661
@test all(plt[1][i][:x] getproperty(wp[i].errors, wp[i].error_estimate) for i in 1:4)
5762
@test all(plt[1][i][:label] == wp_names[i] for i in 1:4)
5863

64+
@test_nowarn plot(wp, x = :dts, y = :final)
65+
5966
plt = @test_nowarn plot(wp, view = :dt_convergence, legend = :bottomright)
6067
@test all(plt[1][i][:x] == plt[1][i + 3][:x] == dts == wp.setups[i][:dts] for i in 1:3)
6168
@test all(plt[1][i + 3][:y] getproperty(wp[i].errors, wp[i].error_estimate) for i in 1:3)

0 commit comments

Comments
 (0)