Ввод-вывод: сохранение и загрузка данных решения
Табличные данные: IterableTables
Доступен интерфейс для IterableTables.jl. Перейдя по этой ссылке на IterableTables, вы можете использовать тип решения в качестве источника данных для преобразования в другие табличные форматы. Например, решим систему 4x2 уравнений ODE и получим 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.992583 | 0.0121201 | 0.451722 | 0.855231 |
2 | 0.0625 | 1.05524 | 0.0128852 | 0.480237 | 0.909218 |
3 | 0.125 | 1.12185 | 0.0136986 | 0.510552 | 0.966612 |
4 | 0.1875 | 1.19267 | 0.0145633 | 0.542781 | 1.02763 |
5 | 0.25 | 1.26796 | 0.0154826 | 0.577044 | 1.0925 |
6 | 0.3125 | 1.348 | 0.0164599 | 0.61347 | 1.16146 |
7 | 0.375 | 1.43309 | 0.017499 | 0.652195 | 1.23478 |
8 | 0.4375 | 1.52355 | 0.0186036 | 0.693365 | 1.31273 |
9 | 0.5 | 1.61973 | 0.019778 | 0.737134 | 1.39559 |
10 | 0.5625 | 1.72197 | 0.0210264 | 0.783665 | 1.48369 |
11 | 0.625 | 1.83067 | 0.0223537 | 0.833134 | 1.57735 |
12 | 0.6875 | 1.94623 | 0.0237648 | 0.885726 | 1.67692 |
13 | 0.75 | 2.06909 | 0.025265 | 0.941637 | 1.78277 |
14 | 0.8125 | 2.1997 | 0.0268598 | 1.00108 | 1.89531 |
15 | 0.875 | 2.33855 | 0.0285553 | 1.06427 | 2.01495 |
16 | 0.9375 | 2.48618 | 0.0303579 | 1.13145 | 2.14214 |
17 | 1.0 | 2.64312 | 0.0322742 | 1.20288 | 2.27737 |
Если задать syms
в DiffEqFunction, будут использоваться именно эти имена:
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.00623451 | 0.269845 | 0.163405 | 0.131724 |
2 | 0.0625 | 0.00662807 | 0.286879 | 0.17372 | 0.140039 |
3 | 0.125 | 0.00704646 | 0.304988 | 0.184686 | 0.148879 |
4 | 0.1875 | 0.00749127 | 0.324241 | 0.196344 | 0.158277 |
5 | 0.25 | 0.00796416 | 0.344708 | 0.208738 | 0.168268 |
6 | 0.3125 | 0.00846689 | 0.366468 | 0.221915 | 0.17889 |
7 | 0.375 | 0.00900137 | 0.389602 | 0.235923 | 0.190182 |
8 | 0.4375 | 0.00956958 | 0.414195 | 0.250816 | 0.202188 |
9 | 0.5 | 0.0101737 | 0.440341 | 0.266648 | 0.214951 |
10 | 0.5625 | 0.0108159 | 0.468138 | 0.283481 | 0.22852 |
11 | 0.625 | 0.0114986 | 0.497689 | 0.301375 | 0.242945 |
12 | 0.6875 | 0.0122245 | 0.529106 | 0.3204 | 0.258281 |
13 | 0.75 | 0.0129961 | 0.562505 | 0.340625 | 0.274585 |
14 | 0.8125 | 0.0138165 | 0.598013 | 0.362127 | 0.291918 |
15 | 0.875 | 0.0146887 | 0.635763 | 0.384986 | 0.310345 |
16 | 0.9375 | 0.0156159 | 0.675896 | 0.409288 | 0.329936 |
17 | 1.0 | 0.0166017 | 0.718562 | 0.435125 | 0.350763 |
Многие платформы моделирования автоматически задают syms
для этой функции. Кроме того, эти данные могут быть сохранены в CSV-файл:
using CSV
CSV.write("out.csv", df)
"out.csv"
JLD2 и BSON.jl
JLD2.jl и BSON.jl будут работать с полным типом решения, если перед загрузкой вернуть необходимые функции в область действия. Например, если сохранить решение:
sol = solve(prob, Euler(); dt = 1 // 2^(4))
using JLD2
@save "out.jld2" sol
можно получить обратно полный тип решения, интерполяции и все остальное, если сначала загрузить зависимые функции:
# Новый сеанс
using JLD2
using OrdinaryDiffEq
JLD2.@load "out.jld2" sol
1-element Vector{Symbol}:
:sol
Пример с BSON.jl имеет следующий вид:
sol = solve(prob, Euler(); dt = 1 // 2^(4))
using BSON
bson("test.bson", Dict(:sol => sol))
# Новый сеанс
using OrdinaryDiffEq
using BSON
# BSON.load("test.bson") # сейчас не работает: https://github.com/JuliaIO/BSON.jl/issues/109
Если загрузить его без функции DE, для некоторых алгоритмов интерполяция может не работать, а для всех алгоритмов для работы интерфейса решения (шаблонов графиков, индексирования массивов и т. д.) потребуется как минимум пакет решателя или SciMLBase.jl в области действия. Если ничто из этого не будет помещено в область действия, тип решения все равно загрузится и будет содержать все значения (поэтому sol.u
и sol.t
будут работать), но ни один из интерфейсов не будет доступен.