Output and Saving Controls

These callbacks extend the output and saving controls available during time stepping.

DiffEqCallbacks.SavingCallbackFunction
SavingCallback(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 to u).
  • saved_values::SavedValues is the types that save_func will return, i.e. save_func(t, u, integrator)::savevalType. It's specified via SavedValues(typeof(t),savevalType), i.e. give the type for time and the type that save_func will output (or higher compatible type).

Keyword Arguments

  • saveat mimics saveat in solve from solve.
  • save_everystep mimics save_everystep from solve.
  • save_start mimics save_start from solve.
  • save_end mimics save_end from solve.
  • tdir should be sign(tspan[end]-tspan[1]). It defaults to 1 and should be adapted if tspan[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.

source
DiffEqCallbacks.FunctionCallingCallbackFunction
FunctionCallingCallback(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 be sign(tspan[end]-tspan[1]). It defaults to 1 and should be adapted if tspan[1] > tspan[end].
source

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]