Функции построения графиков
Построение стандартных графиков с использованием шаблона
Функциональность построения графиков реализуется за счет шаблонов в 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
.