MTK & Standard Library & Analysis points

I’m trying to figure out how to define “analysis points” in my MTK models, and how to use such to linearize the model.

Initial questions:

  • Is the “analysis points” facility part of the standard library, or of MTK?
  • It seems like “analysis points” can be inserted in between two causal blocks. I assume this means that one can use blocks from the standard library to do this?

Here is what I have tried…

using ModelingToolkit, ModelingToolkitStandardLibrary.Blocks
using DifferentialEquations

@variables t
Dt = Differential(t)

@mtkmodel Tank_m begin
    # Model parameters
    @parameters begin 
        ρ=1,    [description = "Liquid density"]
        A=5,    [description = "Cross sectional tank area"]
        K=5,    [description = "Effluent valve constant"]
        h_ς=3,  [description = "Scaling level in valve model"]
    # Model variables, with initial values needed
    @variables begin
        m(t)=1.5*ρ*A,   [description = "Liquid mass"]
        # ṁ_i(t),         [description = "Influent mass flow rate"]
        ṁ_e(t),         [description = "Effluent mass flow rate"]
        V(t),           [description = "Liquid volume"]
        h(t),           [description = "level"]
    # Components from ModelingToolkitStandardLibrary
    @components begin
        # We move ṁ_i from "variables" to "components"
        ṁ_i = RealInput()   # Influent mass flow rate
        y_ṁ_e = RealOutput()
    # Providing model equations
    @equations begin
        Dt(m) ~ ṁ_i.u - ṁ_e
        m ~ ρ*V
        V ~ A*h
        ṁ_e ~ K*sqrt(h/h_ς)
        y_ṁ_e.u ~ ṁ_e

@mtkmodel Sys2Tank_m begin
    # Components used
    @components begin 
        ṁ = Constant(k=2)
        tank_1 = Tank_m()
        tank_2 = Tank_m()
    # Equations for connecting components
    @equations begin
        connect(ṁ.output, :u1, tank_1.ṁ_i)
        connect(tank_1.y_ṁ_e, :u2, tank_2.ṁ_i)

@mtkbuild s2t = Sys2Tank_m()

This code works for standard simulation, e.g.,

tspan = (0,10)
prob = ODEProblem(s2t,[],tspan)
sol = solve(prob)

My attempt of “analysis points” is :u1 and :u2 inserted in the @equations block of the Sys2Tank_m model/connect statements.

I have then assumed that…

  • Specifying ṁ = Constant(k=2) in the Sys2Tank_m model qualifies as making output from a causal block (i.e., from Constant).
  • Specifying ṁ_i = RealInput() in the Tank_m model qualifies as making Tank_m a “causal block” with ṁ_i as input.

In other words, that it is correct to define :u1 and :u2 as analysis points via the statements:

 @equations begin
        connect(ṁ.output, :u1, tank_1.ṁ_i)
        connect(tank_1.y_ṁ_e, :u2, tank_2.ṁ_i)

Question 1: Is my understand correct so far, or is it horribly wrong? [If wrong, what is wrong?]

Question 2: If correct so far, what method can I use to linearize the model? Is there some function linearize in ModelingToolkit or ControlSystems or ControlSystemsMTK, etc. that can be used?

[I tried with:

linsys = linearize(s2t, :u1, tank_2.m)

but am told that tank_2 doesn’t exist. Still:


responds with
If I instead try with:

linsys = linearize(s2t, :u1, s2t.tank_2.m)

I’m told:

Any tips on where to go from here?]

The standard library, you can only find this in the documentation of the stdlib and not the documentation of MTK?

Yes, the analysis points relies on you placing them between connectors of type RealOutput and RealInput

It’s correct

You use the function ModelingToolkit.linearize, in particular, the last method documented here

In ControlSystemsMTK, there’s a function called named_ss which does the same thing, but returns a linear statespace system from ControlSystemsBase with signal names attached, rather than returning the matrices alone like linearize does.

That’s probably a namespacing problem. All linearization functions expect the non-simplified system.

OK, so I cannot use @mtkbuild s2t = Sys2Tank_m() for linearization.

Instead, I try the following, where both sys below and csys should be non-simplified.

using ControlSystemsMTK
@named sys = Sys2Tank_m()
csys = complete(sys)
named_ss(sys, :u2, csys.tank_2.m)

gives the following error message:

If I use (MTK) linearize instead, i.e., linearize(sys,:u2, csys.tank_2.m), I get exactly the same error message.

Ah… found the error. I need to use:

named_ss(sys, :u2, [csys.tank_2.m])

Then it works.

No, unfortunately not, at least not at the moment.


named_ss(sys, :u2, [csys.tank_2.m])
1 Like

It is not quite clear to me why I need to distinguish between sys and csys in the calling of named_ss, etc.

  • Is there a reason for this?

It’s related to the namespacing issue that @mtkbuild was supposed to solve, but @mtkbuild currently doesn’t take functions that perform custom simplification (i.e., require an unsimplified system as input) into account, and the user thus has to deal with the namespacing issue for those functions until we have a better solution. complete makes it so that sys.x produces a symbol x instead of a symbol namespaced like sys.x, and MTK requires the x version rather than the sys.x version.

By the way, you could have used csys in both places as well

named_ss(csys, :u2, [csys.tank_2.m])
1 Like

Great to know.

One more thing: I assume that in a “library perspective”, my model Tank_m above would be a unit in a library, while Sys2Tank_m could be automatically generated using a GUI tool, where I drag the “components” of Sys2Tank_m [two instances of Tank_m and one instance of a Constant source] onto the palette, and connect them by drawing lines between the blocks [thereby producing the connect statements].

If so – if I have a “vector” of inputs and outputs from a model (a la Tank_m with RealInput and RealOutput instantiations), what would be the order of the inputs and outputs in GUI connectors? Would it be the order in which they are listed in the @component part of Tank_m? I mean, in the case that I have more than one RealInput and RealOutput in a model? [I guess MTK SL comes with some standard descriptors a la “Flow”, etc…] Is there a documentation page on this that is valid for the new @mtkmodel macro style?

Configurable. The GUI aspects are still under active development so I cannot quite answer exactly how this will look and feel yet.

I’m not quite sure what “this” refers to here. There are several connectors in MTKstdlib, usually at least one for each submodule. For example, Mechanical.Rotational.Flange is the fundamental connector in the Rotational mechanics module. “Flow” is a property of a variable in a connector, it’s not a connector by itself. The current in an electrical pin connector has the property “flow”, so does the dm variable (mass flow) in the HydraulicPort connector in the Hydraulic submodule.

1 Like