Функции построения графиков
Построение стандартных графиков с использованием шаблона
Функциональность построения графиков реализуется за счет шаблонов в Plots.jl. Для построения графиков решений достаточно вызвать plot(type) после импорта Plots.jl, и построитель сгенерирует соответствующие графики.
#]add Plots # Перед первым использованием пакета Plots.jl его необходимо установить!
using Plots
plot(sol) # Строит график решения
Многие типы, определенные в экосистеме DiffEq, такие как ODESolution, ConvergenceSimulation, WorkPrecision и т. д., имеют шаблоны графиков для поддержки различных способов построения графиков. Для настройки графиков можно использовать все именованные аргументы, доступные в Plots.jl. Например, можно изменить бэкенд построения графиков на пакет GR и добавить к графику заголовок:
gr()
plot(sol, title = "I Love DiffEqs!")
Затем, чтобы сохранить график, используйте функцию savefig, например:
savefig("myplot.png")
Плотность
Если задача была решена с параметром dense=true, то параметр denseplot определяет, следует ли использовать функцию dense для создания графика, а plotdensity — это количество равномерно распределенных (во времени) точек для построения. Например:
plot(sol, denseplot = false)
означает «строить только точки, которые вычислил решатель», а:
plot(sol, plotdensity = 1000)
означает «строить 1000 точек с помощью функции dense» (так как по умолчанию denseplot=true).
Выбор переменных
В команде plot можно выбрать переменные, которые будут отрисованы на каждом графике. Главная форма имеет следующий вид:
idxs = [(f1, 0, 1), (f2, 1, 3), (f3, 4, 5)]
Ее можно использовать для построения кривых функций f1(var₀, var₁), f2(var₁, var₃) и f3(var₄, var₅) на одном графике (0 считается временем или независимой переменной). Функции f1, f2 и f3 должны принимать скалярные значения и возвращать кортеж. Если функция не передана, например:
idxs = [(0, 1), (1, 3), (4, 5)]
это означает «построить кривую var₁(t) в зависимости от t (времени), кривую var₃(var₁) в зависимости от var₁ и кривую var₅(var₄) в зависимости от var₄ на одном графике, поместив независимые переменные (t, var₁ и var₄) на оси x». Хотя такая форма универсальна, для удобства приняты следующие правила:
-
Если в какой либо позиции кортежа находится просто целое число, строится кривая соответствующей переменной как функции от времени. Например, приведенный выше список эквивалентен следующему:
idxs = [1, (1, 3), (4, 5)]
и
idxs = [1, 3, 4]
является самым лаконичным способом построения кривых переменных 1, 3 и 4 как функций от времени.
-
Если требуется только один график, список можно опустить:
(2,3)и4эквивалентно[(2,3)]и[(0,4)]соответственно. -
Кортеж, содержащий один или несколько списков, раскрывается путем связывания соответствующих элементов списков друг с другом:
idxs = ([1, 2, 3], [4, 5, 6])
эквивалентно
idxs = [(1, 4), (2, 5), (3, 6)]
а выражение
idxs = (1, [2, 3, 4])
эквивалентно
idxs = [(1, 2), (1, 3), (1, 4)]
-
Вместо целых чисел можно использовать символы из
ParameterizedFunction. Например, в выраженииidxs=(:x,:y)символы заменяются целочисленными значениями для компонентов:xи:y. -
Допускаются n-мерные группы. Например,
(1,2,3,4,5)представляет 5-мерный график связанных переменных.
Комплексные числа и высокоразмерные графики
Для дополнительных возможностей работы с числами высокой размерности (комплексными числами) и другими графиками высокой размерности предоставляется библиотека шаблонов DimensionalPlotRecipes.jl. Дополнительные сведения о доступных параметрах см. в файле сведений.
Временной диапазон
Временной диапазон графика можно выбрать с помощью аргумента tspan функции plot. Например:
plot(sol, tspan = (0.0, 40.0))
строит график от t=0.0 до t=40.0. Если denseplot=true, эти границы соблюдаются в точности. В противном случае строятся первая и последняя точка внутри интервала, то есть точки вне интервала не строятся.
Пример
using DifferentialEquations, Plots
function lorenz(du, u, p, t)
du[1] = p[1] * (u[2] - u[1])
du[2] = u[1] * (p[2] - u[3]) - u[2]
du[3] = u[1] * u[2] - p[3] * u[3]
end
u0 = [1.0, 5.0, 10.0]
tspan = (0.0, 100.0)
p = (10.0, 28.0, 8 / 3)
prob = ODEProblem(lorenz, u0, tspan, p)
sol = solve(prob)
xyzt = plot(sol, plotdensity = 10000, lw = 1.5)
xy = plot(sol, plotdensity = 10000, idxs = (1, 2))
xz = plot(sol, plotdensity = 10000, idxs = (1, 3))
yz = plot(sol, plotdensity = 10000, idxs = (2, 3))
xyz = plot(sol, plotdensity = 10000, idxs = (1, 2, 3))
plot(plot(xyzt, xyz), plot(xy, xz, yz, layout = (1, 3), w = 1), layout = (2, 1))
Пример использования функций:
f(x, y, z) = (sqrt(x^2 + y^2 + z^2), x)
plot(sol, idxs = (f, 1, 2, 3))
Нормализация по времени:
f(t, x, y, z) = (t, sqrt(x^2 + y^2 + z^2))
plot(sol, idxs = (f, 0, 1, 2, 3))
Анимация
Используя интерфейс итератора по решениям, можно генерировать анимации с помощью команды animate(sol). Вы можете выбрать имя файла (filename), в котором будет сохранена анимация, посредством вызова animate(sol,filename). С помощью именованных аргументов можно также задать число кадров в секунду (fps) и плотность шагов (every). Остальные аргументы передаются непосредственно в шаблон графика для обработки обычным способом. Например, можно анимировать решение с большей толщиной линии и сохранением каждого 4-го кадра:
#]add ImageMagick # Перед первым использованием пакета ImageMagick.jl его может потребоваться установить!
#using ImageMagick # В некоторых системах для получения качественных анимаций требуется оператор using ImageMagick
animate(sol, lw = 3, every = 4)
Дополнительные сведения о доступных атрибутах см. в документации по Plots.jl.
Построение графиков без шаблона
Что если вы не хотите использовать Plots.jl? Странное решение, но можно и так! Если дифференциальное уравнение описано вектором значений, то объект решения представляет собой матрицу AbstractMatrix элементов sol[i,j] для i-й переменной в точке времени j. Это можно использовать для построения графиков решений. Например, в PyPlot, Gadfly, GR и т. д. для построения графиков временных рядов можно использовать следующее выражение:
plot(sol.t, sol')
так как в данном случае график строится по столбцам, а в sol' столбец содержит временной ряд. Фазовые графики можно строить аналогичным образом, например:
plot(sol[i, :], sol[j, :], sol[k, :])
это трехмерный фазовый график переменных i, j и k.
Обратите внимание, что интерполяция при этом не применяется. Если шаблон графика не используется, интерполяция должна осуществляться вручную. Например:
n = 101 #число временных точек
ts = range(0, stop = 1, length = n)
plot(sol(ts, idxs = i), sol(ts, idxs = j), sol(ts, idxs = k))
это фазовое пространство со значениями, разделенными во времени на 0.01.