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

**URL:** <https://discourse.julialang.org/t/how-to-use-mtk-as-one-block-in-a-co-simulation/134895>\
**Category:** Modelling & Simulations\
**Tags:** question, modelingtoolkit\
**Created:** [January 5, 2026, 5:25pm UTC](https://discourse.julialang.org/t/how-to-use-mtk-as-one-block-in-a-co-simulation/134895 "2026-01-05T17:25:57Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![ohmsweetohm1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ohmsweetohm1/32/49126_2.png) [@ohmsweetohm1](https://discourse.julialang.org/u/ohmsweetohm1)\
**Post date:** [January 5, 2026, 5:25pm UTC](https://discourse.julialang.org/t/how-to-use-mtk-as-one-block-in-a-co-simulation/134895/1 "2026-01-05T17:25:57Z")

</div>

How could I use this model

```julia
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:

```julia
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?

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [January 5, 2026, 5:32pm UTC](https://discourse.julialang.org/t/how-to-use-mtk-as-one-block-in-a-co-simulation/134895/2 "2026-01-05T17:32:33Z")

</div>

This tutorial could help

> **[Fit parameters of ModelingToolkit model · ControlSystemIdentification...](https://baggepinnen.github.io/ControlSystemIdentification.jl/dev/examples/modelingtoolkit/)**
>
> Documentation for ControlSystemIdentification Documentation.

The basic steps are

- [`ModelingToolkit.generate_control_function`](https://docs.sciml.ai/ModelingToolkit/dev/basics/InputOutput/)
- Discretization. This is done using [`SeeToDee.Rk4`](https://baggepinnen.github.io/SeeToDee.jl/dev/) in the tutorial, but you could use any integrator of your choice.
- [Generate a function that computes the output y given the state x, using `build_explicit_observed_function`](https://docs.sciml.ai/ModelingToolkit/dev/basics/InputOutput/#Generating-an-output-function,-g)

* * *

Here’s another example

> **[ModelingToolkit · ModelPredictiveControl.jl](https://juliacontrol.github.io/ModelPredictiveControl.jl/stable/manual/mtk/)**
>
> Documentation for ModelPredictiveControl.jl.

---

<div class="post-metadata">

**Author:** ![ohmsweetohm1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ohmsweetohm1/32/49126_2.png) [@ohmsweetohm1](https://discourse.julialang.org/u/ohmsweetohm1)\
**Post date:** [January 6, 2026, 10:43am UTC](https://discourse.julialang.org/t/how-to-use-mtk-as-one-block-in-a-co-simulation/134895/3 "2026-01-06T10:43:06Z")

</div>

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](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`?

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [January 6, 2026, 11:13am UTC](https://discourse.julialang.org/t/how-to-use-mtk-as-one-block-in-a-co-simulation/134895/4 "2026-01-06T11:13:22Z")

</div>

> [@ohmsweetohm1](#):
>
> Would it be favourable to use `ODEProblem` and `init` to get an integrator, to have access to the full suit of algorithms of DiffEq?

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

> [@ohmsweetohm1](#):
>
> Is `integrator.u` guaranteed to be the same as the state vector expected by `build_explicit_observed_function`

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).](https://github.com/bradcarman/ModelingToolkitInputs.jl) that was created to facilitate this

---

<div class="post-metadata">

**Author:** ![ohmsweetohm1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ohmsweetohm1/32/49126_2.png) [@ohmsweetohm1](https://discourse.julialang.org/u/ohmsweetohm1)\
**Post date:** [January 6, 2026, 12:39pm UTC](https://discourse.julialang.org/t/how-to-use-mtk-as-one-block-in-a-co-simulation/134895/5 "2026-01-06T12:39:26Z")

</div>

Thank you! This is exactly what I am looking for [Home · ModelingToolkitInputs.jl](https://bradcarman.github.io/ModelingToolkitInputs.jl/dev/#Indeterminate-Form:-Using-ModelingToolkit-with-Streaming-Data)

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [January 6, 2026, 1:03pm UTC](https://discourse.julialang.org/t/how-to-use-mtk-as-one-block-in-a-co-simulation/134895/6 "2026-01-06T13:03:02Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![ohmsweetohm1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ohmsweetohm1/32/49126_2.png) [@ohmsweetohm1](https://discourse.julialang.org/u/ohmsweetohm1)\
**Post date:** [January 6, 2026, 1:07pm UTC](https://discourse.julialang.org/t/how-to-use-mtk-as-one-block-in-a-co-simulation/134895/7 "2026-01-06T13:07:53Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![ohmsweetohm1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ohmsweetohm1/32/49126_2.png) [@ohmsweetohm1](https://discourse.julialang.org/u/ohmsweetohm1)\
**Post date:** [January 6, 2026, 1:13pm UTC](https://discourse.julialang.org/t/how-to-use-mtk-as-one-block-in-a-co-simulation/134895/8 "2026-01-06T13:13:23Z")

</div>

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](https://bradcarman.github.io/ModelingToolkitInputs.jl/dev/#Indeterminate-Form:-Using-ModelingToolkit-with-Streaming-Data) would not apply since with stepping the integrator manually I do not have problems with this, I think.

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [January 6, 2026, 1:33pm UTC](https://discourse.julialang.org/t/how-to-use-mtk-as-one-block-in-a-co-simulation/134895/9 "2026-01-06T13:33:04Z")

</div>

> [@ohmsweetohm1](#):
>
> Is stepping the integrator to the next time point, updating the parameters, i.e. inputs and doing the next step safe?

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.

> **[Note about mutating - Integrator Interface · DifferentialEquations.jl](https://docs.sciml.ai/DiffEqDocs/latest/basics/integrator/#Note-about-mutating)**
>
> The integrator interface gives one the ability to interactively step through the numerical solving of a differential equation. Through this interface, one can easily monitor results, modify the problem during a run, and dynamically continue solving...

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).
