Output and Saving Controls
These callbacks extend the output and saving controls available during time stepping.
DiffEqCallbacks.SavedValues — Type
SavedValues{tType<:Real, savevalType}Container used by SavingCallback to store saved time points and user-defined values.
Fields
t::Vector{tType}: saved time points.saveval::Vector{savevalType}: values returned by the saving function.
Construct empty storage with SavedValues(tType, savevalType). The callback appends to both vectors in place; do not mutate them while a solve is active.
DiffEqCallbacks.SavingCallback — Function
SavingCallback(save_func, saved_values::SavedValues;
saveat = Vector{eltype(saved_values.t)}(),
save_everystep = isempty(saveat),
save_start = save_everystep || isempty(saveat) || saveat isa Number,
save_end = save_everystep || isempty(saveat) || saveat isa Number,
tdir = 1) -> DiscreteCallbackThe saving callback lets you define a function save_func(u, t, integrator) which returns quantities of interest that shall be saved.
Arguments
save_func: function called assave_func(u, t, integrator). It must return a value compatible witheltype(saved_values.saveval)and must not return a view ofu.saved_values::SavedValues: storage whose time and value element types match the integration time and the output ofsave_func.
Keywords
saveat = Vector{eltype(saved_values.t)}(): selected integration times, or a scalar interval at which to evaluatesave_functhroughout the problem time span.save_everystep::Bool = isempty(saveat): whether to save after every accepted step.save_start::Bool = ...: whether to save at the initial condition.save_end::Bool = ...: whether to save at the final time.tdir = 1: integration direction used to ordersaveat. Set this tosign(tspan[end] - tspan[1])for reverse-time problems.
The output values are saved into saved_values. Time points are found via saved_values.t and the values are saved_values.saveval.
Returns
DiscreteCallback: a callback that evaluatessave_funcat the requested times and appends the results tosaved_values.
Examples
using DiffEqCallbacks, OrdinaryDiffEq
prob = ODEProblem((u, p, t) -> -u, 1.0, (0.0, 1.0))
saved_values = SavedValues(Float64, Float64)
cb = SavingCallback((u, t, integrator) -> u^2, saved_values; saveat = 0.0:0.25:1.0)
sol = solve(prob, Tsit5(); callback = cb)DiffEqCallbacks.FunctionCallingCallback — Function
FunctionCallingCallback(func;
funcat = Vector{Float64}(),
func_everystep = isempty(funcat),
func_start = true,
tdir = 1) -> DiscreteCallbackThe function calling callback lets you define a function func(u,t,integrator) which gets called at the time points of interest.
Arguments
func: function called asfunc(u, t, integrator)at each selected time. Its return value is ignored, and it should not modifyuor the integrator.
Keywords
funcat = Vector{Float64}(): selected integration times, or a scalar interval at which to callfuncthroughout the problem time span.func_everystep::Bool = isempty(funcat): whether to callfuncafter every accepted step.func_start::Bool = true: whether to callfuncat the initial condition.tdir = 1: integration direction used to orderfuncat. Set this tosign(tspan[end] - tspan[1])for reverse-time problems.
Returns
DiscreteCallback: a callback that callsfuncwithout modifying the integrator state.
Examples
using DiffEqCallbacks, OrdinaryDiffEq
seen = Float64[]
func = (u, t, integrator) -> push!(seen, t)
cb = FunctionCallingCallback(func; funcat = 0.0:0.25:1.0)
prob = ODEProblem((u, p, t) -> -u, 1.0, (0.0, 1.0))
sol = solve(prob, Tsit5(); callback = cb)DiffEqCallbacks.IndependentlyLinearizedSolution — Type
IndependentlyLinearizedSolution{T, S}
IndependentlyLinearizedSolution(prob::SciMLBase.AbstractDEProblem,
num_derivatives = 0) -> IndependentlyLinearizedSolutionEfficient storage for independently linearized state components obtained from LinearizingSavingCallback. It stores a single time vector with a packed BitMatrix denoting which state components were sampled at each time and implements Julia's iteration interface to reconstruct a coherent state at every stored time.
Fields
ts::Vector{T}: sorted union of the stored time points.us::Vector{Matrix{S}}: state and derivative samples. Each matrix corresponds to one state component, uses rows for the primal and requested derivatives, and stores its available time samples in columns.time_mask::BitMatrix: maps rows ofusto entries ints; use iteration rather than interpreting this packed representation directly.
The vectors and mask are storage owned by the callback. Iterate the result after the solve; do not mutate its fields while solving.
Arguments
prob: differential equation problem used to infer the time, state, and storage dimensions.num_derivatives::Int = 0: nonnegative number of derivative rows to store in addition to the primal state values.
Iteration
Iteration yields (t, values) for each stored time, where values is a matrix with one row per state component and columns containing the primal followed by the requested derivatives.
Returns
IndependentlyLinearizedSolution: storage to pass toLinearizingSavingCallback.
Examples
using DiffEqCallbacks, OrdinaryDiffEq
prob = ODEProblem((du, u, p, t) -> (du .= -u), [1.0, 2.0], (0.0, 1.0))
ils = IndependentlyLinearizedSolution(prob)
sol = solve(prob, Tsit5(); callback = LinearizingSavingCallback(ils))
first_time, first_values = first(ils)DiffEqCallbacks.LinearizingSavingCallback — Function
LinearizingSavingCallback(ils::IndependentlyLinearizedSolution;
kwargs...) -> DiscreteCallbackReturn a saving callback that inserts interpolation points so that linear interpolation of the saved values is within abstol/reltol of the integrator interpolation.
The algorithm internally checks 3 equidistant points between each time point to determine goodness of fit versus the linearly interpolated function; this should be sufficient for interpolations up to the 4th order, higher orders may need more points to ensure good fit. This has not been implemented yet.
Arguments
ils: theIndependentlyLinearizedSolutionstorage object to fill.
Keywords
interpolate_mask::BitVector: select the state indices for which the integrator interpolant can be queried. False indices are linearly interpolated from the solution time points without subdivision. By default, all indices are selected.abstol = nothing: absolute tolerance for comparing linearized and integrator interpolation. Defaults to the integrator absolute tolerance.reltol = nothing: relative tolerance for comparing linearized and integrator interpolation. Defaults to the integrator relative tolerance.
Returns
DiscreteCallback: a callback that stores independently linearized output inils.
Examples
using DiffEqCallbacks, OrdinaryDiffEq
prob = ODEProblem((du, u, p, t) -> (du .= -u), [1.0, 2.0], (0.0, 1.0))
ils = IndependentlyLinearizedSolution(prob)
sol = solve(prob, Tsit5(); callback = LinearizingSavingCallback(ils))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.2093641623702687, 2.070610270796817), (2.4419144260041548, 2.288555765051708), (3.1296422512690105, 2.9330924705708394), (4.375892248991175, 4.101074684284124), (6.0056741908513125, 5.628502025349696)]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.2093641623702687, 2.070610270796817), (2.4417250197416585, 2.288378254001625), (2.6985235775186687, 2.529049185627687), (2.9823294951679387, 2.7950313437555008), (3.2959846237721333, 3.088988103730817), (3.6426254969601297, 3.413859016605139), (4.025722420994646, 3.772896444262843), (4.449113067450856, 4.169697042391042), (4.917030758514874, 4.6082282693867995), (5.4341572116601595, 5.0928778185288515), (6.0056741908513125, 5.628502025349696)][0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0]