How to use MTK as one block in a co-simulation

How could I use this model

using ModelingToolkit
import ModelingToolkit: t_nounits as t, D_nounits as D
@variables x(t)=0 u(t)=0 y(t)
@parameters k = 1
eqs = [D(x) ~ -k * (x + u)
       y ~ x]

@named sys = System(eqs, t)

as the plant in a control loop?
Something like this:

while t<t_end
  u = step_ctrl(y)
  y = step_mtk(u)
  t += dt
end

A typical FMI-style co simulation has an init! and a y=step!(u). But non of the SciML implementations has the notion of input nor output. The input is somewhat straightforward, i.e. by using some kind of buffer in the parameters that I write values to and missusing the parameter as an input signal. But for the output I have to compute it somehow from the state, parameters and time. How would I use the integrator interface for this.

Is there an example of this somewhere?

1 Like

This tutorial could help

The basic steps are


Here’s another example

4 Likes

Would it be favourable to use ODEProblem and init to get an integrator, to have access to the full suit of algorithms of DiffEq?
This video seems to use this approach: https://www.youtube.com/watch?v=LrSM0-Bv7uQ&t=1677s

Is integrator.u guaranteed to be the same as the state vector expected by build_explicit_observed_function?

If you need some special integrator then yes, you can do that.

I believe so, yes.

This approach is associated with a lot of manual bookkeeping to handle the inputs. If you want to go this route, have a look at GitHub - bradcarman/ModelingToolkitInputs.jl: Support for driving ModelingToolkit model inputs with data in determinate (data known upfront) and indeterminate form (data streamed at runtime). that was created to facilitate this

Thank you! This is exactly what I am looking for Home · ModelingToolkitInputs.jl

The current implementation of MTKInputs.jl has a number of type instabilities and performs symbolic operations in set_input!, so if this is performance critical you may want to have a look at that.

If I simply do it myself, i.e. make an InputInterpolator that MTK treats as a parameter and I update it’s values after every step there should not be any problems. That is pretty much the approach from the video I think.

Or do I get problems with the discontinuities? The input will be ZOH in all cases I think.
Is stepping the integrator to the next time point, updating the parameters, i.e. inputs and doing the next step safe?

I think the argument from here Home · ModelingToolkitInputs.jl would not apply since with stepping the integrator manually I do not have problems with this, I think.

I don’t know. Some integrators use an optimization called “first same as last” (FSAL) which is violated when the input changes discontinuously, so I assume you have to communicate this somehow.

The docs above indicate that modifying the state can sometimes be very inefficient, but I think that this would communicate what you need (and possibly more than that, making it overly conservative, I don’t know).