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)
[(2.84349782800085, 2.647864790614429), (3.142747649550029, 2.9265261837320766), (4.027711473765332, 3.7506043764538393), (5.631345690023896, 5.243908340480762), (7.729428135040847, 7.197642427864407)]
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)
[(2.84349782800085, 2.647864790614429), (3.142551105184029, 2.926343161645195), (3.473056213040243, 3.2341094731200886), (3.8383203580282355, 3.5742433952435912), (4.242001060514921, 3.9501508104838163), (4.688135102982258, 4.365590770138813), (5.181188850960785, 4.82472235318303), (5.726101456473323, 5.332144897308211), (6.328321296440062, 5.892931930361259), (6.9938738412434915, 6.512694369542664), (7.729428135040847, 7.197642427864407)][0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]