I/O: Saving and Loading Solution Data
Tabular Data: IterableTables
An interface to IterableTables.jl is provided. This IterableTables link allows you to use a solution type as the data source to convert to other tabular data formats. For example, let’s solve a 4x2 system of ODEs and get the DataFrame:
using OrdinaryDiffEq, DataFrames
f_2dlinear = (du, u, p, t) -> du .= 1.01u;
tspan = (0.0, 1.0)
prob = ODEProblem(f_2dlinear, rand(2, 2), tspan);
sol = solve(prob, Euler(); dt = 1 // 2^(4));
df = DataFrame(sol)
Row | timestamp | value1 | value2 | value3 | value4 |
---|---|---|---|---|---|
Float64 | Float64 | Float64 | Float64 | Float64 | |
1 | 0.0 | 0.662565 | 0.203607 | 0.435484 | 0.800465 |
2 | 0.0625 | 0.704389 | 0.216459 | 0.462974 | 0.850994 |
3 | 0.125 | 0.748854 | 0.230123 | 0.492199 | 0.904713 |
4 | 0.1875 | 0.796125 | 0.24465 | 0.52327 | 0.961823 |
5 | 0.25 | 0.84638 | 0.260094 | 0.556301 | 1.02254 |
6 | 0.3125 | 0.899808 | 0.276512 | 0.591417 | 1.08709 |
7 | 0.375 | 0.956609 | 0.293967 | 0.628751 | 1.15571 |
8 | 0.4375 | 1.01699 | 0.312523 | 0.66844 | 1.22866 |
9 | 0.5 | 1.08119 | 0.332251 | 0.710636 | 1.30622 |
10 | 0.5625 | 1.14944 | 0.353225 | 0.755495 | 1.38868 |
11 | 0.625 | 1.222 | 0.375522 | 0.803185 | 1.47634 |
12 | 0.6875 | 1.29914 | 0.399227 | 0.853886 | 1.56953 |
13 | 0.75 | 1.38115 | 0.424428 | 0.907788 | 1.66861 |
14 | 0.8125 | 1.46833 | 0.45122 | 0.965092 | 1.77394 |
15 | 0.875 | 1.56102 | 0.479704 | 1.02601 | 1.88592 |
16 | 0.9375 | 1.65956 | 0.509985 | 1.09078 | 2.00497 |
17 | 1.0 | 1.76432 | 0.542178 | 1.15964 | 2.13153 |
If we set syms
in the DiffEqFunction, then those names will be used:
f = ODEFunction(f_2dlinear, syms = [:a, :b, :c, :d])
prob = ODEProblem(f, rand(2, 2), (0.0, 1.0));
sol = solve(prob, Euler(); dt = 1 // 2^(4));
df = DataFrame(sol)
Row | timestamp | a | b | c | d |
---|---|---|---|---|---|
Float64 | Float64 | Float64 | Float64 | Float64 | |
1 | 0.0 | 0.288818 | 0.411299 | 0.549192 | 0.356189 |
2 | 0.0625 | 0.30705 | 0.437262 | 0.583859 | 0.378673 |
3 | 0.125 | 0.326432 | 0.464865 | 0.620715 | 0.402577 |
4 | 0.1875 | 0.347038 | 0.494209 | 0.659898 | 0.42799 |
5 | 0.25 | 0.368945 | 0.525406 | 0.701554 | 0.455006 |
6 | 0.3125 | 0.392235 | 0.558572 | 0.74584 | 0.483729 |
7 | 0.375 | 0.416995 | 0.593832 | 0.792921 | 0.514264 |
8 | 0.4375 | 0.443317 | 0.631318 | 0.842974 | 0.546727 |
9 | 0.5 | 0.471302 | 0.67117 | 0.896187 | 0.581239 |
10 | 0.5625 | 0.501053 | 0.713537 | 0.952759 | 0.61793 |
11 | 0.625 | 0.532682 | 0.758579 | 1.0129 | 0.656937 |
12 | 0.6875 | 0.566307 | 0.806465 | 1.07684 | 0.698406 |
13 | 0.75 | 0.602055 | 0.857373 | 1.14482 | 0.742493 |
14 | 0.8125 | 0.64006 | 0.911495 | 1.21708 | 0.789362 |
15 | 0.875 | 0.680464 | 0.969033 | 1.29391 | 0.839191 |
16 | 0.9375 | 0.723418 | 1.0302 | 1.37559 | 0.892165 |
17 | 1.0 | 0.769084 | 1.09523 | 1.46242 | 0.948483 |
Many modeling frameworks will automatically set syms
for this feature. Additionally, this data can be saved to a CSV:
using CSV
CSV.write("out.csv", df)
"out.csv"
JLD2 and BSON.jl
JLD2.jl and BSON.jl will work with the full solution type if you bring the required functions back into scope before loading. For example, if we save the solution:
sol = solve(prob, Euler(); dt = 1 // 2^(4))
using JLD2
@save "out.jld2" sol
then we can get the full solution type back, interpolations and all, if we load the dependent functions first:
# New session
using JLD2
using OrdinaryDiffEq
JLD2.@load "out.jld2" sol
1-element Vector{Symbol}:
:sol
The example with BSON.jl is:
sol = solve(prob, Euler(); dt = 1 // 2^(4))
using BSON
bson("test.bson", Dict(:sol => sol))
# New session
using OrdinaryDiffEq
using BSON
# BSON.load("test.bson") # currently broken: https://github.com/JuliaIO/BSON.jl/issues/109
If you load it without the DE function then for some algorithms the interpolation may not work, and for all algorithms you’ll need at least a solver package or SciMLBase.jl in scope in order for the solution interface (plot recipes, array indexing, etc.) to work. If none of these are put into scope, the solution type will still load and hold all of the values (so sol.u
and sol.t
will work), but none of the interface will be available.