# Using MTK when I \*import\* ModelingToolkit?

**URL:** <https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681>\
**Category:** Modelling & Simulations\
**Created:** [November 5, 2025, 2:19pm UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681 "2025-11-05T14:19:53Z")\
**Posts on this page:** 20\
**Page:** 2

<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:** [November 7, 2025, 2:52pm UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/21 "2025-11-07T14:52:37Z")

</div>

Perhaps a silly question… As far as I know, ModelingToolkit.jl does not directly support quantities with units. In other words, I can not write something like (using `Unitful.jl` syntax…):

```julia
@component function MyModel(; name, struct_p = false, kwargs...)
    vars = @variables begin
        x(t)=1u"m"
        y(t)=2u"K"
    end

```

Instead, it is possible to write:

```julia
 vars = @variables begin
        x(t)=1, [unit=u"m"]
        y(t)=2, [unit=u"K"]
 end

```

or something to that effect. But this only works if SI units are provided…

**Question** : Would the following work?

```julia
 vars = @variables begin
        x(t)=ustrip(uconvert(u"m", 25u"in"), [unit=u"m"]
        y(t)=ustrip(uconvert(u"K", 300u"°C"), [unit=u"K"]
 end

```

The idea is to use the unit system of `Unitful.jl` to avoid conversion errors, but then strip off the unit in the assignment `x(t) = `, etc.

If this works, would it have a negative effect on performance?

---

<div class="post-metadata">

**Author:** ![cryptic.ax](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cryptic.ax/32/220540_2.png) [@cryptic.ax](https://discourse.julialang.org/u/cryptic.ax)\
**Post date:** [November 7, 2025, 3:02pm UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/22 "2025-11-07T15:02:17Z")

</div>

That will work. As long as the default for the variable is unitless, and the unit given in the metadata is an SI unit, it is equivalent to you having done the conversion manually.

While we’re on the topic of units, Unitful.jl support is disappearing too. We support DynamicQuantities.jl, and it should be a drop-in replacement. The reason for the discontinuation is that Unitful.jl invalidates a lot of code, which prevents us from precompiling core workflows in MTK (a _lot_ of work has gone into reducing TTFX). The validation for Unitful.jl was also subpar iirc.

---

<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:** [November 7, 2025, 5:16pm UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/23 "2025-11-07T17:16:17Z")

</div>

My impression is that `DynamicQuantities` is more efficient than `Unitful`, but the documentation of `Unitful` is much more complete. There is some discussion in the `DynamicQuantities` documentation about being able to convert to/from `Unitful`, but it is not clear whether `DynamicQuantities` supports all units and constants in the `Unitful` package.

Anyways, my _guess_ is that if I do as I indicate, and even drop specifying `unit`, this should work. And hopefully, using `Unitful` with conversion and stripping off units in the `@parameters` and `@variables` section does not influence the speed of the solver – since I assume that those sections are not used in the solver??

---

<div class="post-metadata">

**Author:** ![cryptic.ax](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cryptic.ax/32/220540_2.png) [@cryptic.ax](https://discourse.julialang.org/u/cryptic.ax)\
**Post date:** [November 7, 2025, 6:01pm UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/24 "2025-11-07T18:01:15Z")

</div>

Unitful puts the units in the type. Theoretically, this means that if you have inconsistent units in your calculation the error is inferred at compile time. In practice, this doesn’t work out for MTK since we do the unit checking at model building time. The `ODEProblem` doesn’t have units in it. So putting things in the type only makes everything slower because everything ends up being a dynamic dispatch. DynamicQuantities puts the unit in the value domain, so it’s generally easier to work with.

---

<div class="post-metadata">

**Author:** ![cryptic.ax](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cryptic.ax/32/220540_2.png) [@cryptic.ax](https://discourse.julialang.org/u/cryptic.ax)\
**Post date:** [November 7, 2025, 6:02pm UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/25 "2025-11-07T18:02:33Z")

</div>

Effectively, any concrete number you give to MTK should not have a unit. All units should be specified via the `unit` metadata. i.e. `@variables x(t) = 1 [unit = u"m"]` is fine, `@variables x = 1u"m"` is bad.

---

<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:** [November 7, 2025, 6:30pm UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/26 "2025-11-07T18:30:45Z")

</div>

Got it. And even if I don’t want to use units (i.e., do not specify `unit`), I can convert to any non-SI unit, e.g.,

```julia-auto
vars = @variables begin
        x(t)=ustrip(uconvert(u"mm", 25u"in"))
        y(t)=ustrip(uconvert(u"pK", 300u"°C"))
 end

```

and as long as I strip off units, there is no computational cost, even when I use `Unitful` over `DynamicQuantities`.

---

<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:** [November 11, 2025, 12:16pm UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/27 "2025-11-11T12:16:22Z")

</div>

> [@cryptic.ax](#):
>
> As an example, the above form is pretty close to the `@mtkmodel` equivalent.

I’m struggling with how to include `@structural_parameters` in the new “MTK-model”.

Here is a semi-realistic model [simulating 2 nitrogen atoms interacting via a harmonic and a Morse potential…].

My old/working model:

```julia
@mtkmodel TwoAtoms begin
    #
   # Model parameters
    # -- structure parameters
    @structural_parameters begin
        # typeP, :harmonic -- harmonic potential
        # typeP, :Morse -- Morse potential
        typeP = :harmonic
    end
    #
    # -- parameters
    #
    # Model parameters
    @parameters begin
        # Constant
        mb = 14, [description = "Nitrogen atom mass, atom mass unit u"]
        D_e = 945, [description = "Morse parameter D_e, unit u*nm^2/ps^2"]
        a = 27, [description = "Morse parameter a, unit 1/nm"]
        r_e = 0.1, [description = "Potential equilibrium distance, unit nm"]
        k_e = 2a^2*D_e, [description = "Harmonic parameter, u/ps^2"]
        r_0 = 1.5r_e, [description = "Initial distance between particles, nm"]
        #
    end
    #
    # Model variables, with initial values needed
    @variables begin
        # Variables
        x_1(t)=0, [description = "Particle 1, position unit nm"]
        v_1(t)=0, [description = "Particle 1, velocity unit nm/ps"]
        x_2(t)=r_0, [description = "Particle 2, position unit nm"]
        v_2(t)=0, [description = "Particle 2, velocity unit nm/ps"]
        r(t), [description = "Distance between particles, nm"]
        P(t), [description = "Potential energy, u*nm^2/ps^2"]
        K(t), [description = "Kinetic energy, u*nm^2/ps^2"]
        E(t), [description = "Total energy, u*nm^2/ps^2"]
    end
    #
    # Model equations
    @equations begin
        # Basic algebraics
        K ~ mb*(v_1^2 + v_2^2)/2
        r ~ abs(x_1 - x_2)
        #
        # Velocity definitions
        Dt(x_1) ~ v_1
        Dt(x_2) ~ v_2
        # Dynamics based on typeP
        if typeP == :harmonic  
            Dt(v_1) ~ -k_e*(r - r_e)*sign(x_1-x_2)/mb
            Dt(v_2) ~ k_e*(r - r_e)*sign(x_1-x_2)/mb
            P ~ k_e/2*(r-r_e)^2
        elseif typeP == :Morse
            Dt(v_1) ~ -2*D_e*a*(1-exp(-a*(r-r_e)))*exp(-a*(r-r_e))*sign(x_1-x_2)/mb
            Dt(v_2) ~ 2*D_e*a*(1-exp(-a*(r-r_e)))*exp(-a*(r-r_e))*sign(x_1-x_2)/mb
            P ~ D_e*(1 - exp(-a*(r-r_e)))^2
        end
        E ~ K + P
    end
end

```

and here is how I instantiate two models:

```julia
@mtkcompile tp_h = TwoAtoms()
@mtkcompile tp_m = TwoAtoms(;typeP=:Morse)

```

* * *

Next, I am trying to use the `@component` macro, but do not understand how to handle `structural_parameters`. Here is the same code as above, where I have had to comment out the structural parameter `typeP` in order to make it work:

```julia
@component function TwoAtomsNew(; name)
    #
   # Model parameters
    # -- structure parameters
    #=
    struct_params = @structural_parameters begin
        # typeP, :harmonic -- harmonic potential
        # typeP, :Morse -- Morse potential
        typeP = :harmonic
    end
    =#
    #
    # -- parameters
    #
    # Model parameters
    params = @parameters begin
        # Constant
        mb = 14, [description = "Nitrogen atom mass, atom mass unit u"]
        D_e = 945, [description = "Morse parameter D_e, unit u*nm^2/ps^2"]
        a = 27, [description = "Morse parameter a, unit 1/nm"]
        r_e = 0.1, [description = "Potential equilibrium distance, unit nm"]
        k_e = 2a^2*D_e, [description = "Harmonic parameter, u/ps^2"]
        r_0 = 1.5r_e, [description = "Initial distance between particles, nm"]
        #
    end
    #
    # Model variables, with initial values needed
    vars = @variables begin
        # Variables
        x_1(t)=0, [description = "Particle 1, position unit nm"]
        v_1(t)=0, [description = "Particle 1, velocity unit nm/ps"]
        x_2(t)=r_0, [description = "Particle 2, position unit nm"]
        v_2(t)=0, [description = "Particle 2, velocity unit nm/ps"]
        r(t), [description = "Distance between particles, nm"]
        P(t), [description = "Potential energy, u*nm^2/ps^2"]
        K(t), [description = "Kinetic energy, u*nm^2/ps^2"]
        E(t), [description = "Total energy, u*nm^2/ps^2"]
    end
    #
    # Model equations
    eqs = [
        # Basic algebraics
        K ~ mb*(v_1^2 + v_2^2)/2
        r ~ abs(x_1 - x_2)
        #
        # Velocity definitions
        Dt(x_1) ~ v_1
        Dt(x_2) ~ v_2
        # Dynamics based on typeP
        #if typeP == :harmonic  
            Dt(v_1) ~ -k_e*(r - r_e)*sign(x_1-x_2)/mb
            Dt(v_2) ~ k_e*(r - r_e)*sign(x_1-x_2)/mb
            P ~ k_e/2*(r-r_e)^2
        #=elseif typeP == :Morse
            Dt(v_1) ~ -2*D_e*a*(1-exp(-a*(r-r_e)))*exp(-a*(r-r_e))*sign(x_1-x_2)/mb
            Dt(v_2) ~ 2*D_e*a*(1-exp(-a*(r-r_e)))*exp(-a*(r-r_e))*sign(x_1-x_2)/mb
            P ~ D_e*(1 - exp(-a*(r-r_e)))^2
        end 
        E ~ K + P =#
    ]
    #
    System(eqs, t, vars, params; name)
end

```

Instantiating this new version works by doing:

```julia
@mtkcompile tp_h = TwoAtomsNew()

```

**Question** : How can I extend `TwoAtomsNew` with the structural parameter?

---

<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:** [November 11, 2025, 12:20pm UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/28 "2025-11-11T12:20:33Z")

</div>

Try this

```julia-auto
    eqs = [
        # Basic algebraics
        K ~ mb*(v_1^2 + v_2^2)/2
        r ~ abs(x_1 - x_2)
        # Velocity definitions
        Dt(x_1) ~ v_1
        Dt(x_2) ~ v_2
        # Dynamics based on typeP
        if typeP == :harmonic  
            [Dt(v_1) ~ -k_e*(r - r_e)*sign(x_1-x_2)/mb
            Dt(v_2) ~ k_e*(r - r_e)*sign(x_1-x_2)/mb
            P ~ k_e/2*(r-r_e)^2]
        elseif typeP == :Morse
            [Dt(v_1) ~ -2*D_e*a*(1-exp(-a*(r-r_e)))*exp(-a*(r-r_e))*sign(x_1-x_2)/mb
            Dt(v_2) ~ 2*D_e*a*(1-exp(-a*(r-r_e)))*exp(-a*(r-r_e))*sign(x_1-x_2)/mb
            P ~ D_e*(1 - exp(-a*(r-r_e)))^2]
        end 
        E ~ K + P
    ]

```

That is, each branch of the if statement returns an array that is then concatenated with the rest of the equations. This is not MTK specific, it works for any julia code

```julia-auto
julia> [
       1
       2
       if true
         [3,4]
       else
         [5,6]
       end
       7
       ]
5-element Vector{Int64}:
 1
 2
 3
 4
 7

```

---

<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:** [November 11, 2025, 12:46pm UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/29 "2025-11-11T12:46:13Z")

</div>

How do I introduce `typeP`?

There appears to be no “macro” `@structural_parameters` for `@component`.

Should I do:

```julia
@component function TwoAtomsNew(; name, typeP=:harmonic)

```

* * *

OK – tested it, and it works. Thanks!

---

<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:** [November 11, 2025, 12:51pm UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/30 "2025-11-11T12:51:25Z")

</div>

> [@BLI](#):
>
> There appears to be no “macro” `@structural_parameters` for `@component`.

Correct, a structural parameter is just a function argument that isn’t used to create a symbolic variable.

---

<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:** [November 11, 2025, 12:55pm UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/31 "2025-11-11T12:55:34Z")

</div>

And… here is the result when using `@component` – the same as when using the old system:

 ![image](https://global.discourse-cdn.com/julialang/original/3X/1/b/1bbf5df61dec3c1ae12852889358a63ad03752b8.png)

---

<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:** [November 11, 2025, 2:53pm UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/32 "2025-11-11T14:53:25Z")

</div>

Ah. I ran into another problem… suppose I use a structural parameter to decide whether I should leave an input perturbation as zero or undefined (for the purpose of linearization). Here is a basic example:

```julia
@component function SimpleSys(; name, u_ex=false)
    #
   # Model parameters
    # -- structure parameters
        # u_ex, false -- no input perturbation
        # u_ex, true -- input perturbation is undefined
    #
    # -- parameters
    #
    # Model parameters
    params = @parameters begin
        a = -2
        b = 0.5
        #
    end
    #
    # Model variables, with initial values needed
    # Variables
    vars = @variables begin
        x(t) = 3.0
        y(t) = 1.0
        u(t) = 0.0
        du(t)
    end
    #
    # Model equations
    eqs = [
        u ~ 1
        if u_ex == false
            du ~ 0
        end
        Dt(x) ~ a*x + b*(u+du)
        Dt(y) ~ -x + 2*a*y
    ]
    #
    System(eqs, t, vars, params; name)
end

```

I can instantiate this:

```julia
@mtkcompile sisy = SimpleSys()

```

Next, I try to set `u_ex = true`, which means that I want an “external” input `du` that is unspecified:

```julia
@named sisy_lin = SimpleSys(; u_ex=true)
sisy_lin = complete(sisy_lin)

```

The idea is that `sisy_lin` has an unspecified input `du` which I can use in linearization.

This worked in the past, but does not work now.

**Question** : what has changed?

---

<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:** [November 11, 2025, 2:59pm UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/33 "2025-11-11T14:59:52Z")

</div>

> [@BLI](#):
>
> suppose I use a structural parameter to decide whether I should leave an input perturbation as zero or undefined (for the purpose of linearization).

You shouldn’t 🙂 We have a mechanism called “analysis point” to handle exactly this issue. Always connect it, but connect it like this

```julia-auto
connect(y, :name, u)

```

and then when you want to linearize, you pass `sys.name` instead of `u` as the input, and the connection will be removed automatically.

---

<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:** [November 11, 2025, 4:18pm UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/34 "2025-11-11T16:18:56Z")

</div>

Yes, I know about the “analysis point”. My guess is that it does more or less what I have indicated, i.e., create an extra “fictitious” input that is set to zero for normal simulation. Then during “analysis”, this value is relaxed from zero and used as the input during linearization if it is an input in the linearization – this makes it trivial to choose the operating point value for this “fictitious” input, and is kept as an output otherwise.

* * *

The only “disadvantage” with using “analysis point” is that I think it is necessary to:

- Add the `ModelingToolkitStandardLibrary` [not a disadvantage in itself, of course, but adds complexity)
- Add components from `ModelingToolkitStandardLibrary` for “input signal” and “output signal” (?) and connect these as you indicate. Again, not a disadvantage per se, but adds some complexity.

For the “old” way of defining the model, I could simply do:

```julia
@mtkmodel SimpleSys begin
   # Model parameters
    # -- structure parameters
    @structural_parameters begin
        # u_ex, boolean, input U defined EXternally
        u_ex = false
    end
    #
    # Model parameters
    @parameters begin
        a = -2
        b = 0.5
        #
    end
    #
    # Model variables, with initial values needed
    # Variables
    @variables begin
        x(t) = 3.0
        y(t) = 1.0
        u(t) = 0.0
        du(t)
    end
    #
    # Model equations
   @equations begin
        u ~ 1
        if u_ex == false
            du ~ 0
        end
        Dt(x) ~ a*x + b*(u+du)
        Dt(y) ~ -x + 2*a*y
    end
end

```

and

```julia
@named sisy_lin = SimpleSys(; u_ex=true)
sisy_lin = complete(sisy_lin)

```

and it worked.

* * *

Is there an updated example with new `@component` macro with `RealInput` etc. from MTKSL, etc. that works?

---

<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:** [November 11, 2025, 6:22pm UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/35 "2025-11-11T18:22:31Z")

</div>

This works

```julia-auto
Dt = ModelingToolkit.D_nounits
t = ModelingToolkit.t_nounits
@mtkmodel SimpleSys2 begin
   # Model parameters
    # -- structure parameters
    @structural_parameters begin
        # u_ex, boolean, input U defined EXternally
        u_ex = false
    end
    #
    # Model parameters
    @parameters begin
        a = -2
        b = 0.5
        #
    end
    #
    # Model variables, with initial values needed
    # Variables
    @variables begin
        x(t) = 3.0
        y(t) = 1.0
        u(t)# = 0.0
        du(t), [input = true]
        c0(t), [output = true]
    end
    #
    # Model equations
   @equations begin
        u ~ 1
        c0 ~ 0
        connect(c0, :name, du)
        Dt(x) ~ a*x + b*(u+du)
        Dt(y) ~ -x + 2*a*y
    end
end

@named model = SimpleSys2()
linearize(model, [model.name], [])

```

you no longer need MTKStdlib to use analysis points, declarig variables as input/output as above is sufficient

---

<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:** [November 12, 2025, 8:15am UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/36 "2025-11-12T08:15:24Z")

</div>

Great that the analysis point idea has been incorporated into MTK itself!

A couple of things in the example `SimpSys2` that I don’t quite get.

You introduce `c0` as an `output`, and then give it a value of `0`.

- Is this meant to be the “output” of an external input signal that functions as an additional input to the system?

Then you connect `c0` to `du`.

- Does this mean that you give `du` the value of `c0` by connecting them, but you add the possibility of the analysis point?
- What precisely does this analysis point do? Does it add a hidden variable (that the user does not need to know about), say named `du_p` or something (`p` for perturbation) which is set to zero for normal simulation, but that is allowed to be different from zero during linearization and with zero operating point?

What does `linearize` do?

- `linearize(model, [model.name], [])` … it linearizes from the analysis point (`model.name`)… to what output? To all states when an output is not listed?

---

<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:** [November 12, 2025, 8:35am UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/37 "2025-11-12T08:35:40Z")

</div>

> [@BLI](#):
>
> You introduce `c0` as an `output`, and then give it a value of `0`.
> 
> - Is this meant to be the “output” of an external input signal that functions as an additional input to the system?

There’s a rule that `connect` between two variables is only allowed if one is an input and the other is an output.

> [@BLI](#):
>
> Does this mean that you give `du` the value of `c0` by connecting them, but you add the possibility of the analysis point?

correct

> [@BLI](#):
>
> What precisely does this analysis point do?

it depends on how you’re using it. When you simulate the model it does nothing, when you call `linearize` it performs a number of model transformations. I’ll plan to submit a talk on this on the upcoming MODPROD conference in a few months, but I haven’t yet put the material together. In this case, it breaks the connection (like it wasn’t there), adds a new virtual input that is connected to the input variable in the connection and uses this new virtual input as the linearization input.

If you call `get_looptransfer, get_sensitivity` etc., the analysis point does other things, as appropriate to give you the requested function.

> [@BLI](#):
>
> `linearize(model, [model.name], [])` … it linearizes from the analysis point (`model.name`)… to what output? To all states when an output is not listed?

In this case I listed no outputs, so the C matrix is empty. You still get the A,B matrices though.

---

<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:** [November 12, 2025, 10:40am UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/38 "2025-11-12T10:40:07Z")

</div>

So I re-wrote your working code to the new `@Component` syntax, and simplified it + slight change of notation:

```julia
# Dt = ModelingToolkit.D_nounits
# t = ModelingToolkit.t_nounits
@component function SimpleSys3(; name)
   # Model parameters
    #
    # Model parameters
    params = @parameters begin
        a = -2
        b = 0.5
        #
    end
    #
    # Model variables, with initial values needed
    # Variables
    vars = @variables begin
        x(t) = 3.0
        z(t) = 1.0
        u(t), [input = true]
        u_ex(t), [output = true]
    end
    #
    # Model equations
   eqs = [
        u_ex ~ 1
        connect(u_ex, :pump, u)
        Dt(x) ~ a*x + b*u
        Dt(z) ~ -x + 2*a*z
   ]
   #
   System(eqs,t,vars,params; name)
end

@named model3 = SimpleSys3()

linearize(model3, [model3.pump], [])

```

This works. But what if I want to specify the output in the linearization? Suppose I want to do `y ~ z` and use `y` as output leading to `C` and `D` matrices.

Doing:

```julia
linearize(model3, [model3.pump], [model3.z])

```

does not work.

---

<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:** [November 12, 2025, 11:21am UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/39 "2025-11-12T11:21:25Z")

</div>

Use `complete(model).z` for the output. It’s unfortunate that this discrepancy exists, but I think @cryptic.ax has some explanation for why it’s hard to get rid of.

---

<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:** [November 12, 2025, 11:25am UTC](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681/40 "2025-11-12T11:25:44Z")

</div>

Ah. I think I figured it out. I needed to re-wire my brain 🙃

- I am used to thinking in terms of linearization from an input signal to a system, to an output signal from the system.
- But with “analysis points”, I must instead think in terms of linearization from one connection point to another connection point.
- Connection points are defined by connectors between components.

In my simple example above, at the outset, that is the only component there is, and there is no component upstream or downstream in the information flow.

So I need to create fictitious upstream and downstream “components”. In my example above, `u_ex` is actually the output signal from the upstream “component”, so I rename it to `y_up`. Then I must connect that “output” from the upstream “component” to the input `u` of the model/component I describe here.

* * *

OK. To define a downstream connection, I need to treat the output `y` from my system as an `output` from this “component”, and then I need to add `u_dwn` as an `input` to the fictitious downstream component. And finally make a connection seemingly outside of my model by connecting the output `y` of this model to the fictitious input `u_dwn` of the downstream system.

```julia
# Dt = ModelingToolkit.D_nounits
# t = ModelingToolkit.t_nounits
@component function SimpleSys3(; name)
   # Model parameters
    #
    # Model parameters
    params = @parameters begin
        a = -2
        b = 0.5
        #
    end
    #
    # Model variables, with initial values needed
    # Variables
    vars = @variables begin
        x(t) = 3.0
        z(t) = 1.0
        u(t), [input = true]
        y_up(t), [output = true]
        y(t), [output = true]
        u_dwn(t), [input = true]

    end
    #
    # Model equations
   eqs = [
        y_up ~ 1
        connect(y_up, :pump, u)
        Dt(x) ~ a*x + b*u
        Dt(z) ~ -x + 2*a*z
        y ~ z 
        connect(y, :sensor, u_dwn)
   ]
   #
   System(eqs,t,vars,params; name)
end

@named model3 = SimpleSys3()
linsys = linearize(model3, [model3.pump], [model3.sensor])

```

In summary, although I really only have a single system that is not even a component, I need to treat it as a component and define `u` as input, and `y` as output.

In addition, I need to create a “fictitious” upstream component with output `y_up`, and a fictitious downstream component with input `u_dwn`.

Then I do the “component” connections with analysis points.

* * *

Does this seem correct?

[Previous page](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681.md?page=1)

[Next page](https://discourse.julialang.org/t/using-mtk-when-i-import-modelingtoolkit/133681.md?page=3)
