# MTK: updated documentation?

**URL:** <https://discourse.julialang.org/t/mtk-updated-documentation/134937>\
**Category:** Modelling & Simulations\
**Created:** [January 7, 2026, 2:38pm UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937 "2026-01-07T14:38:42Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [January 7, 2026, 2:38pm UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/1 "2026-01-07T14:38:42Z")

</div>

I am trying to use ModelingToolkit (MTK). In the first example in the documentation,

```julia
using ModelingToolkit, Plots, OrdinaryDiffEq
using ModelingToolkit: t_nounits as t, D_nounits as D
@mtkmodel FOL begin
    @parameters begin
        τ = 3.0 # parameters
    end
    @variables begin
        x(t) = 0.0 # dependent variables
    end
    @equations begin
        D(x) ~ (1 - x) / τ
    end
end

@mtkcompile fol = FOL()

```

This example doesn’t run with the latest version of MTK: I get an error message that `@mtkmodel` is not defined in `Main`.

* * *

OK – based on previous discussion, I know that MTK is in a transition to a new way to describe components – but my understanding was that the “old way” would still work, but with a warning. The new style works, though:

```julia
@component function FOL(;name)
    params = @parameters begin
        τ = 3.0 # parameters
    end
    vars = @variables begin
        x(t) = 0.0 # dependent variables
    end
    eqs = [
        D(x) ~ (1 - x) / τ
    ]
    System(eqs, t, vars, params; name)
end

@mtkcompile fol = FOL()

```

* * *

**Question** : Where is the “new style” documented?? Although I know the basics of the new style, it is not easy to guess how to make acausal models. E.g., `@components` doesn’t exist any more, the error message tells me.

---

<div class="post-metadata">

**Author:** ![franckgaga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/franckgaga/32/218241_2.png) [@franckgaga](https://discourse.julialang.org/u/franckgaga)\
**Post date:** [January 7, 2026, 3:31pm UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/2 "2026-01-07T15:31:19Z")

</div>

Is it a bug in the documentation deploy on github ? Because releasing a breaking release without documenting it properly (in the official documentation) is reckless for a package as important as MTK. That piles up on the reasons why I still don’t consider MTK as a mature package.

---

<div class="post-metadata">

**Author:** ![Brad\_Carman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/brad_carman/32/17631_2.png) [@Brad\_Carman](https://discourse.julialang.org/u/Brad_Carman)\
**Post date:** [January 7, 2026, 3:40pm UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/3 "2026-01-07T15:40:25Z")

</div>

ModelingToolkit recently updated to a v11 release and deprecated the @mtkmodel macro, see [ModelingToolkit.jl/NEWS.md at master · SciML/ModelingToolkit.jl](https://github.com/SciML/ModelingToolkit.jl/blob/master/NEWS.md#deprecation-of-mtkmodel) for more information. It seems the MTK docs are not out yet for v11 (you can see the release version in the bottom dropdown menu).

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [January 7, 2026, 7:38pm UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/4 "2026-01-07T19:38:48Z")

</div>

> [@franckgaga](#):
>
> That piles up on the reasons why I still don’t consider MTK as a mature package.

I wouldn’t be so categorical: I think the developers have done excellent work in a relatively short time span. And I like the improvements I see; I hope these will solve some problems of the past (from my experience), like better handling of initialization with guesses, improved linearization; I love the moving of “analysis points” out of the standard library and to the general tool. In comparison, when I used OpenModelica the first time (ca. 2003-2004), it could only handle models with a couple of states.

Still, I look forward to seeing some updated documentation.

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [January 8, 2026, 3:12pm UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/5 "2026-01-08T15:12:05Z")

</div>

OK… Microsoft Copilot suggested the following modification of the Acausal example in the documentation… (the first couple of attempts failed, but by providing it with the error messages, this code works) 🙂

```julia
using ModelingToolkit, Plots, OrdinaryDiffEq
using ModelingToolkit: t_nounits as t, D_nounits as D

@connector function Pin(; name)
    sts = @variables v(t) [guess = 1.0] i(t) [guess = 1.0, connect = Flow]
    ODESystem(Equation[], t, sts, []; name = name)
end

@component function Ground(; name)
    @named g = Pin()
    eqs = [g.v ~ 0]
    compose(ODESystem(eqs, t, [], []; name = name), g)
end

@component function OnePort(; name)
    @named p = Pin()
    @named n = Pin()
    sts = @variables v(t) [guess = 1.0] i(t) [guess = 1.0]
    eqs = [
        v ~ p.v - n.v
        0 ~ p.i + n.i
        i ~ p.i
    ]
    compose(ODESystem(eqs, t, sts, []; name = name), p, n)
end

@component function Resistor(; name, R = 1.0)
    @named oneport = OnePort()
    @unpack v, i = oneport
    ps = @parameters R = R
    eqs = [v ~ i * R]
    extend(ODESystem(eqs, t, [], ps; name = name), oneport)
end

@component function Capacitor(; name, C = 1.0)
    @named oneport = OnePort()
    @unpack v, i = oneport
    ps = @parameters C = C
    eqs = [D(v) ~ i / C]
    extend(ODESystem(eqs, t, [], ps; name = name), oneport)
end

@component function ConstantVoltage(; name, V = 1.0)
    @named oneport = OnePort()
    @unpack v = oneport
    ps = @parameters V = V
    eqs = [V ~ v]
    extend(ODESystem(eqs, t, [], ps; name = name), oneport)
end

# --- Build the RC circuit ---

R = 2.0
C = 1.0
V = 1.0

@named resistor = Resistor(R = R)
@named capacitor = Capacitor(C = C)
@named source = ConstantVoltage(V = V)
@named ground = Ground()

rc_eqs = [
    connect(source.p, resistor.p)
    connect(resistor.n, capacitor.p)
    connect(capacitor.n, source.n)
    connect(capacitor.n, ground.g)
]

@named _rc_model = ODESystem(rc_eqs, t)
@named rc_model = compose(_rc_model, [resistor, capacitor, source, ground])

sys = structural_simplify(rc_model)

u0 = [
    capacitor.v => 0.0
]

prob = ODEProblem(sys, u0, (0, 10.0))
sol = solve(prob, Tsit5())
plot(sol)

```

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [January 8, 2026, 3:57pm UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/6 "2026-01-08T15:57:16Z")

</div>

The new docs just need some downstream stuff updated in order to build. Should happen rather soon.

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [January 8, 2026, 7:30pm UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/7 "2026-01-08T19:30:20Z")

</div>

I should say that I struggle somewhat with understanding when I can use `@mtkcompile`, when I should use `structural_simplify`, and – is there `mtkcompile`?? I had a “session” with MS Copilot on this, and didn’t get much wiser.

---

<div class="post-metadata">

**Author:** ![langestefan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/langestefan/32/207923_2.png) [@langestefan](https://discourse.julialang.org/u/langestefan)\
**Post date:** [January 8, 2026, 7:57pm UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/8 "2026-01-08T19:57:31Z")

</div>

There is no more `structural_simplify`, use `mtkcompile`. Or the macro `@mtkcompile`

from [ModelingToolkit.jl/NEWS.md at b8940e544bbf04f518a8f5d5bc340fd90db68133 · SciML/ModelingToolkit.jl · GitHub](https://github.com/SciML/ModelingToolkit.jl/blob/b8940e544bbf04f518a8f5d5bc340fd90db68133/NEWS.md?plain=1#L374)

> ## New `mtkcompile` and `@mtkcompile`
> 
> `structural_simplify` is now renamed to `mtkcompile`. `@mtkbuild` is renamed to  
> `@mtkcompile`. Their functionality remains the same. However, instead of a second  
> positional argument `structural_simplify(sys, (inputs, outputs))` the inputs and outputs  
> should be specified via keyword arguments as `mtkcompile(sys; inputs, outputs, disturbance_inputs)`.

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [January 9, 2026, 6:58am UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/9 "2026-01-09T06:58:58Z")

</div>

To answer the original question: `@mtkmodel` is now in a separate package called `SciCompDSL`, which is inside of the MTK repo. `using SciCompDSL` will make your original example work with a deprecation warning. If `@component` works for you, using it is more forward-looking.

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [January 9, 2026, 9:49am UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/10 "2026-01-09T09:49:56Z")

</div>

I guess MS Copilot was “under the influence”… it claimed first that there was no `mtkcompile` and that `@mtkcompile` had been removed. When I pushed back, it claimed that `@mtkcompile` only works for systems in state space form (DEs of index 0), and that `mtkcompile` and `structural_simplify` served different purposes.

Anyways, `structural_simplify` still works.

I am still wondering about _when_ to use `@mtkcompile` and _when_ to use `mtkcompile`. It must be possible to present that in a simple way(?).

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [January 9, 2026, 9:53am UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/11 "2026-01-09T09:53:35Z")

</div>

Another new thing… When should we use `System` and when should we use `ODESystem`?

---

<div class="post-metadata">

**Author:** ![sablonl](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sablonl/32/217805_2.png) [@sablonl](https://discourse.julialang.org/u/sablonl)\
**Post date:** [January 9, 2026, 10:04am UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/12 "2026-01-09T10:04:17Z")

</div>

In recent MTK versions, you should always prefer `System` and `mtkcompile`. I think that `ODESystem` and `structural_simplify` are just there for backward compatibility.

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [January 9, 2026, 10:06am UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/13 "2026-01-09T10:06:52Z")

</div>

So… to answer my own question – is the following correct?

#### When to use `@mtkcompile`:

When the complete model is “baked” into a component:

```julia
@component function FOL(;name)
    params = @parameters begin
        τ = 3.0 # parameters
    end
    vars = @variables begin
        x(t) = 0.0 # dependent variables
    end
    eqs = [
        D(x) ~ (1 - x) / τ
    ]
    System(eqs, t, vars, params; name)
end

@mtkcompile fol = FOL()
prob = ODEProblem(fol, [], (0.0, 10.0))
sol = solve(prob)

```

#### When to use `mtkcompile`:

When the complete model is composed in `Main`/outside of a `component`?

```julia
params = @parameters begin
        τ = 3.0 # parameters
end

vars = @variables begin
        x(t) = 0.0 # dependent variables
end

eqs = [
        D(x) ~ (1 - x) / τ
    ]

@named _fol2 = System(eqs, t, vars, params) 

fol2 = mtkcompile(_fol2)
prob = ODEProblem(fol2, [], (0.0, 10.0))
sol = solve(prob)

```

Is this correct?

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [January 9, 2026, 12:15pm UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/14 "2026-01-09T12:15:21Z")

</div>

Yes, the macro just does named and mtkcompile as one step.

---

<div class="post-metadata">

**Author:** ![langestefan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/langestefan/32/207923_2.png) [@langestefan](https://discourse.julialang.org/u/langestefan)\
**Post date:** [January 9, 2026, 12:16pm UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/15 "2026-01-09T12:16:01Z")

</div>

From the docs: [Model building reference · ModelingToolkit.jl](https://docs.sciml.ai/ModelingToolkit/dev/API/model_building/#ModelingToolkit.@mtkcompile)

```julia-auto
@mtkcompile sys = Constructor(args...; kwargs....)

```

Is shorthand for

```julia-auto
@named sys = Constructor(args...; kwargs...)
sys = mtkcompile(sys)

```

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [January 9, 2026, 1:30pm UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/16 "2026-01-09T13:30:57Z")

</div>

I interpret these two answers as in order to use `@mtkcompile`, there needs to be a constructor for the complete model.

---

<div class="post-metadata">

**Author:** ![franckgaga](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/franckgaga/32/218241_2.png) [@franckgaga](https://discourse.julialang.org/u/franckgaga)\
**Post date:** [January 10, 2026, 5:01pm UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/17 "2026-01-10T17:01:44Z")

</div>

True. And, gotta say, OrdinaryDiffEq.jl package, so awesome 🏎🏎🏎

---

<div class="post-metadata">

**Author:** ![JaviJR](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/javijr/32/218294_2.png) [@JaviJR](https://discourse.julialang.org/u/JaviJR)\
**Post date:** [January 11, 2026, 10:11am UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/18 "2026-01-11T10:11:41Z")

</div>

In my case, coming from a Simulink and Modelica background, I found the `@mtkmodel` macro especially convenient and intuitive, and for that reason I have based most of my models on it. That said, I fully understand that if this macro introduces serious difficulties in terms of maintenance, bug fixing, and debugging, then it makes sense to move away from it or deprecate it.

I do hope, however, that the new documentation clearly explains how to proceed without this macro (ideally by reworking the examples that currently rely on it) so that users like myself, who had grown accustomed to using `@mtkmodel`, can adapt to the new recommended workflow more easily.

---

<div class="post-metadata">

**Author:** ![BLI](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bli/32/37206_2.png) [@BLI](https://discourse.julialang.org/u/BLI)\
**Post date:** [January 11, 2026, 5:24pm UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/19 "2026-01-11T17:24:26Z")

</div>

Further problems… I figured out how to make the acausal example in the old documentation work under the new style.

So I tried to use this working style and make my own “library” of components – I want to understand how things work. When doing `mtkcompile`, there is no error message, and the `latexify` of the model works and is correct. Then I try to create an `ODEProblem`, and get an error message:

```julia
A completed system is required. Call `complete` or `mtkcompile` on the system before creating a `ODEProblem`.

```

But I have done `mtkcompile`!! And if I do `complete` of the named system _before_ I do `mtkcompile`, I get another error message:

```julia
Encountered operator `Differential(t, 1)` which has different independent variable than the one used in the system `nothing`.

Context:
c₊C*Differential(t, 1)(c₊u(t))

```

Any ideas?

Note: when I created my own “components”, I did not use the `OnePort` “container” with extension. Below is my entire code for this case. Note: I used `u` for voltage instead of `v`…; `u` is more common in Europe, and to me `v` is velocity… Also, I use slightly different names for various things, e.g., `a` and `b` for the pins on the one port.

```julia
using ModelingToolkit
using ModelingToolkit: t_nounits as t, D_nounits as D
using OrdinaryDiffEq

@connector function ElectricPort(; name)
    vars = @variables begin 
        u(t), [guess = 0.0]
        i(t), [guess = 0.0, connect = Flow]
    end
    System(Equation[], t, vars, []; name = name)
end

@component function Ground(; name)
    @named a = ElectricPort()
    eqs = [a.u ~ 0]
    compose(System(eqs, t, [], []; name = name), a)
end

@component function Resistor(; name, R = 1.0)
    @named a = ElectricPort()
    @named b = ElectricPort()
    pars = @parameters begin
        R = R, [description = "Resistance, Ohm"]
    end 
    vars = @variables begin
        u(t), [guess = 0.0]
        i(t), [guess = 0.0]
    end
    eqs = [
        u ~ a.u - b.u
        0 ~ a.i + b.i
        i ~ a.i
        u ~ R * i
    ]
    compose(System(eqs, t, vars, pars; name = name), a, b)
end

@component function Capacitor(; name, C = 1.0)
    @named a = ElectricPort()
    @named b = ElectricPort()
    pars = @parameters begin
        C = C, [description = "Capacitance, Farad"]
    end 
    vars = @variables begin
        u(t), [guess = 0.0]
        i(t), [guess = 0.0]
    end
    eqs = [
        u ~ a.u - b.u
        0 ~ a.i + b.i
        i ~ a.i
        i ~ C * D(u)
    ]
    compose(System(eqs, t, vars, pars; name = name), a, b)
end

@component function Inductor(; name, L = 1.0)
    @named a = ElectricPort()
    @named b = ElectricPort()
    pars = @parameters begin
        L = L, [description = "Inductance, Henry"]
    end 
    vars = @variables begin
        u(t), [guess = 0.0]
        i(t), [guess = 0.0]
    end
    eqs = [
        u ~ a.u - b.u
        0 ~ a.i + b.i
        i ~ a.i
        u ~ L * D(i)
    ]
    compose(System(eqs, t, vars, pars; name = name), a, b)
end

@component function VoltageSourceAC(; name, U = 1.0, f = 50.0)
    @named a = ElectricPort()
    @named b = ElectricPort()
    pars = @parameters begin
        U = U, [description = "Amplitude, Volt"]
        f = f, [description = "Frequency, Hz"]
    end
    vars = @variables begin
        u(t), [guess = 0.0]
    end
    eqs = [
        u ~ U * sin(2 * pi * f * t)
        u ~ a.u - b.u
    ]
    compose(System(eqs, t, vars, pars; name = name), a, b)
end

# Parameters
# 
R = 20 #, [description = "RCL resistance, ohm"]
R_ell = 40 #, [description = "RCL load resistance, ohm"]
C = 10e-6 #, [description = "RCL capacitance, F"]
L = 10e-3 #, [description = "RCL inductance, H"]
U = 10 #, [description = "Voltage source amplitude, V"] 
f = 500 #, [description = "Voltage source frequency, Hz"]  
#
#
@named r = Resistor(; R=R)
@named c = Capacitor(; C=C)
@named l = Inductor(; L=L)
@named r_ell = Resistor(; R=R_ell)
@named source = VoltageSourceAC(; U=U, f=f)
@named ground = Ground()

rcl2_eqs = [
    connect(source.a, r.a)
    connect(r.b, c.a)
    connect(r.b, l.a)
    connect(l.b, r_ell.a)
    connect(c.b, ground.a)
    connect(r_ell.b, ground.a)
    connect(ground.a, source.b)
]

@named _rclsys2 = System(rcl2_eqs, t)
@named rclsys2 = compose(_rclsys2, [r, c, l, r_ell, source, ground])
#rclsys2 = complete(rclsys2)

sys = mtkcompile(rclsys2)

tspan = (0,5e-3)

prob = ODEProblem(rclsys2, [], tspan)

```

This gives the indicated error messages.

---

<div class="post-metadata">

**Author:** ![JaviJR](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/javijr/32/218294_2.png) [@JaviJR](https://discourse.julialang.org/u/JaviJR)\
**Post date:** [January 12, 2026, 9:28am UTC](https://discourse.julialang.org/t/mtk-updated-documentation/134937/20 "2026-01-12T09:28:38Z")

</div>

Hi, first of all thank you very much for sharing the whole process and building everything from scratch, that is always very helpful for those of us who are just starting and trying to understand how things work.

Secondly, in your example, shouldn’t you write

```julia-auto
sys = mtkcompile(rclsys2)

tspan = (0, 5e-3)

prob = ODEProblem(sys, [], tspan)

```

instead of

```julia-auto
sys = mtkcompile(rclsys2)

tspan = (0, 5e-3)

prob = ODEProblem(rclsys2, [], tspan)

```

?

[Next page](https://discourse.julialang.org/t/mtk-updated-documentation/134937.md?page=2)
