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.3304426481770166, 2.274693045462265), (2.5763262914890723, 2.51469458073814), (3.303728030182394, 3.224695179790503), (4.622412906084299, 4.5118340496171285), (6.334799625114206, 6.18325649975391)]
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.3304426481770166, 2.274693045462265), (2.5755374410625906, 2.5139246014466816), (2.846409182127877, 2.7783164611199687), (3.145768341081635, 3.0705142534579255), (3.476612526339016, 3.393443877117744), (3.842250184289253, 3.7503346327641527), (4.2463416883723, 4.14475932919988), (4.692935172498543, 4.580669259566708), (5.186495915003302, 5.062422882367509), (5.731962178512552, 5.59484032551264), (6.334799625114206, 6.18325649975391)][0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]