I’m currently using Functional Mockup Units (fmus) in my work and have been combining it with DifferentialEquations.jl in simulations. An FMU consists of an input, state and output, where the state comprises all variables that must be integrated. I use p
as a buffer to write fmu io signals to and use u
to integrate the state variables of the fmu.
A DifferentialEquations.jl simulation does not keep track of p
automatically, so I use a SavingCallback
from the DiffEqCallback library to do that. The recorded p
vector is not always correct though. Why is this, and is there a better way to do this?
MWE (without fmu)
using DifferentialEquations
using DiffEqCallbacks
using Plots
start = 1.0
stop = 100.0
save_period = 1.0
control_period = 10.0
# 1. store the fmu output in p[2] (here output = state, but that is not always so)
# 2. use the input p[1] (and the fmu state u) to calculate derivatives
f(u, p, t) = (p[2] = u; 1e-2.*p[1])
# controller providing fmu input
control_cb = PeriodicCallback(control_period) do integrator
integrator.p[1] = (0.5 - integrator.p[2])
end
# save output of the fmu for later use
# note that the output of an fmu is not always a state variable
plog = SavedValues(Float64, Vector{Float64})
save_cb = SavingCallback((_, _, int) -> copy(int.p), plog, saveat=start:save_period:stop)
u0 = 0.0
p0 = [0.0, 0.0] # [input, output], ideally p[2] is always equal to u
sol = solve(ODEProblem(f, u0, (start, stop), p0), callback=CallbackSet(control_cb, save_cb))
plot(sol) # nice continuous solution
scatter!(plog.t, last.(plog.saveval)) # should be the same as sol, but isn't
vline!(sol.t) # end of each integration step
Thanks for the advice