Output and Saving Controls
These callbacks extend the output and saving controls available during time stepping.
DiffEqCallbacks.SavingCallback
— FunctionSavingCallback(save_func, saved_values::SavedValues;
saveat = Vector{eltype(saved_values.t)}(),
save_everystep = isempty(saveat),
save_start = true,
tdir = 1)
The saving callback lets you define a function save_func(u, t, integrator)
which returns quantities of interest that shall be saved.
Arguments
save_func(u, t, integrator)
returns the quantities which shall be saved. Note that this should allocate the output (not as a view tou
).saved_values::SavedValues
is the types thatsave_func
will return, i.e.save_func(t, u, integrator)::savevalType
. It's specified viaSavedValues(typeof(t),savevalType)
, i.e. give the type for time and the type thatsave_func
will output (or higher compatible type).
Keyword Arguments
saveat
mimicssaveat
insolve
fromsolve
.save_everystep
mimicssave_everystep
fromsolve
.save_start
mimicssave_start
fromsolve
.save_end
mimicssave_end
fromsolve
.tdir
should besign(tspan[end]-tspan[1])
. It defaults to1
and should be adapted iftspan[1] > tspan[end]
.
The outputted values are saved into saved_values
. Time points are found via saved_values.t
and the values are saved_values.saveval
.
DiffEqCallbacks.FunctionCallingCallback
— FunctionFunctionCallingCallback(func;
funcat = Vector{Float64}(),
func_everystep = isempty(funcat),
func_start = true,
tdir = 1)
The function calling callback lets you define a function func(u,t,integrator)
which gets called at the time points of interest. The constructor is:
func(u, t, integrator)
is the function to be called.funcat
values or interval that the function is sure to be evaluated at.func_everystep
whether to call the function after each integrator step.func_start
whether the function is called at the initial condition.tdir
should besign(tspan[end]-tspan[1])
. It defaults to1
and should be adapted iftspan[1] > tspan[end]
.
Saving Example
In this example, we will solve a matrix equation and at each step save a tuple of values which contains the current trace and the norm of the matrix. We build the SavedValues
cache to use Float64
for time and Tuple{Float64,Float64}
for the saved values, and then call the solver with the callback.
using DiffEqCallbacks, OrdinaryDiffEq, LinearAlgebra
prob = ODEProblem((du, u, p, t) -> du .= u, rand(4, 4), (0.0, 1.0))
saved_values = SavedValues(Float64, Tuple{Float64, Float64})
cb = SavingCallback((u, t, integrator) -> (tr(u), norm(u)), saved_values)
sol = solve(prob, Tsit5(), callback = cb)
print(saved_values.saveval)
[(1.0349491310551144, 2.463061195103233), (1.144070454368923, 2.722757530843471), (1.4668529752069177, 3.4909432103880706), (2.0519383810453564, 4.883379916405404), (2.8132832928916605, 6.695294195270635)]
Note that the values are retrieved from the cache as .saveval
, and the time points are found as .t
. If we want to control the saved times, we use saveat
in the callback. The save controls like saveat
act analogously to how they act in the solve
function.
saved_values = SavedValues(Float64, Tuple{Float64, Float64})
cb = SavingCallback((u, t, integrator) -> (tr(u), norm(u)), saved_values,
saveat = 0.0:0.1:1.0)
sol = solve(prob, Tsit5(), callback = cb)
print(saved_values.saveval)
print(saved_values.t)
[(1.0349491310551144, 2.463061195103233), (1.1437956813538837, 2.7221036023261185), (1.2640897690057182, 3.0083898461664482), (1.3970351148045892, 3.3247846451774357), (1.5439629538704818, 3.674456187502061), (1.7063425635918639, 4.06090118617847), (1.8857995299298036, 4.487988350865783), (2.0841316089534296, 4.959996136494067), (2.303321835413382, 5.481643940177907), (2.5455632935997343, 6.058151053040301), (2.8132832928916605, 6.695294195270635)][0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]