Документация Engee

Ввод-вывод: сохранение и загрузка данных решения

Возможность сохранения и загрузки решений важна для работы с большими наборами данных и анализа результатов в течение нескольких сеансов Julia. Здесь описываются существующие функциональные возможности для выполнения данных задач.

Табличные данные: 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)

17×5 DataFrame

Rowtimestampvalue1value2value3value4
Float64Float64Float64Float64Float64
10.00.9925830.01212010.4517220.855231
20.06251.055240.01288520.4802370.909218
30.1251.121850.01369860.5105520.966612
40.18751.192670.01456330.5427811.02763
50.251.267960.01548260.5770441.0925
60.31251.3480.01645990.613471.16146
70.3751.433090.0174990.6521951.23478
80.43751.523550.01860360.6933651.31273
90.51.619730.0197780.7371341.39559
100.56251.721970.02102640.7836651.48369
110.6251.830670.02235370.8331341.57735
120.68751.946230.02376480.8857261.67692
130.752.069090.0252650.9416371.78277
140.81252.19970.02685981.001081.89531
150.8752.338550.02855531.064272.01495
160.93752.486180.03035791.131452.14214
171.02.643120.03227421.202882.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)

17×5 DataFrame

Rowtimestampabcd
Float64Float64Float64Float64Float64
10.00.006234510.2698450.1634050.131724
20.06250.006628070.2868790.173720.140039
30.1250.007046460.3049880.1846860.148879
40.18750.007491270.3242410.1963440.158277
50.250.007964160.3447080.2087380.168268
60.31250.008466890.3664680.2219150.17889
70.3750.009001370.3896020.2359230.190182
80.43750.009569580.4141950.2508160.202188
90.50.01017370.4403410.2666480.214951
100.56250.01081590.4681380.2834810.22852
110.6250.01149860.4976890.3013750.242945
120.68750.01222450.5291060.32040.258281
130.750.01299610.5625050.3406250.274585
140.81250.01381650.5980130.3621270.291918
150.8750.01468870.6357630.3849860.310345
160.93750.01561590.6758960.4092880.329936
171.00.01660170.7185620.4351250.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 будут работать), но ни один из интерфейсов не будет доступен.

JLD

Не используйте JLD. Этот пакет не работает. Типы Julia можно сохранять с помощью JLD.jl. Однако невозможно сохранять типы, имеющие функции, что означает, что данный тип решения в настоящее время несовместим с JLD.

using JLD
JLD.save("out.jld", "sol", sol)