Help needed for a simple static sum

Hi,

I’m learning ModelingToolkit.jl and it’s my first experience with acausal modeling. I’m working on modeling a mining circuit. My flow variable is a mass flowrate in t/h (tonnage). I’m starting with a simple example, a silo with 2 inlets and 1 outlet. For now, I only want steady-state simulations. The silo reduces to a simple sum in static. Here’s my code:

using ModelingToolkit

@variables t

@connector function PipeNode(; name)
    states = @variables Ṁ(t) = 1.0 [connect = Flow]
    ODESystem(Equation[], t, states, []; name = name)
end

@component function Source(; name, feed = 1.0)
    @named outlet = PipeNode()
    params = @parameters feed = feed
    eqs = [
        outlet.Ṁ ~ feed
    ]
    compose(ODESystem(eqs, t, [], params; name = name), outlet)
end

@component function Sink(; name, product = 1.0)
    @named inlet = PipeNode()
    params = @parameters product = product
    eqs = [
        product ~ inlet.Ṁ
    ]
    compose(ODESystem(eqs, t, [], params; name = name), inlet)
end

@component function Silo(; name)
    @named inlet1 = PipeNode()
    @named inlet2 = PipeNode()
    @named outlet = PipeNode()
    eqs = [
        outlet.Ṁ ~ inlet1.Ṁ + inlet2.Ṁ
    ]
    compose(ODESystem(eqs, t, [], []; name = name), inlet1, inlet2, outlet)
end

@named silo = Silo()
@named feed_circuit = Source()
@named feed_extern  = Source()
@named prod_circuit = Sink()

circuit_eqs = [
    connect(feed_circuit.outlet, silo.inlet1)
    connect(feed_extern.outlet, silo.inlet2)
    connect(silo.outlet, prod_circuit.inlet)
]

@named circuit_model = ODESystem(circuit_eqs, t)

When I run this, I get this error:

Model circuit_model with 0 ERROR: UndefVarError: `name` not defined
Stacktrace:
  [1] connection2set!(connectionsets::Vector{ModelingToolkit.ConnectionSet}, namespace::Nothing, ss::Tuple{ODESystem, ODESystem}, isouter::ModelingToolkit.var"#isouter#219"{Vector{Symbol}})
    @ ModelingToolkit ~/.julia/packages/ModelingToolkit/b9DXJ/src/systems/connectors.jl:195
  [2] generate_connection_set!(connectionsets::Vector{ModelingToolkit.ConnectionSet}, sys::ODESystem, find::Nothing, replace::Nothing, namespace::Nothing)
    @ ModelingToolkit ~/.julia/packages/ModelingToolkit/b9DXJ/src/systems/connectors.jl:312
  [3] generate_connection_set!
    @ ~/.julia/packages/ModelingToolkit/b9DXJ/src/systems/connectors.jl:273 [inlined]
  [4] generate_connection_set
    @ ~/.julia/packages/ModelingToolkit/b9DXJ/src/systems/connectors.jl:263 [inlined]
  [5] generate_connection_set
    @ ~/.julia/packages/ModelingToolkit/b9DXJ/src/systems/connectors.jl:262 [inlined]
  [6] n_extra_equations(sys::ODESystem)
    @ ModelingToolkit ~/.julia/packages/ModelingToolkit/b9DXJ/src/systems/abstractsystem.jl:812
  [7] show(io::IOContext{Base.TTY}, mime::MIME{Symbol("text/plain")}, sys::ODESystem)
    @ ModelingToolkit ~/.julia/packages/ModelingToolkit/b9DXJ/src/systems/abstractsystem.jl:844
  [8] (::REPL.var"#55#56"{REPL.REPLDisplay{REPL.LineEditREPL}, MIME{Symbol("text/plain")}, Base.RefValue{Any}})(io::Any)
    @ REPL ~/.julia/juliaup/julia-1.9.0+0.x64.linux.gnu/share/julia/stdlib/v1.9/REPL/src/REPL.jl:276
  [9] with_repl_linfo(f::Any, repl::REPL.LineEditREPL)
    @ REPL ~/.julia/juliaup/julia-1.9.0+0.x64.linux.gnu/share/julia/stdlib/v1.9/REPL/src/REPL.jl:557
 [10] display(d::REPL.REPLDisplay, mime::MIME{Symbol("text/plain")}, x::Any)
    @ REPL ~/.julia/juliaup/julia-1.9.0+0.x64.linux.gnu/share/julia/stdlib/v1.9/REPL/src/REPL.jl:262
 [11] display(d::REPL.REPLDisplay, x::Any)
    @ REPL ~/.julia/juliaup/julia-1.9.0+0.x64.linux.gnu/share/julia/stdlib/v1.9/REPL/src/REPL.jl:281
 [12] display(x::Any)
    @ Base.Multimedia ./multimedia.jl:340
 [13] #invokelatest#2
    @ ./essentials.jl:816 [inlined]
 [14] invokelatest
    @ ./essentials.jl:813 [inlined]
 [15] (::VSCodeServer.var"#66#70"{Bool, Bool, Bool, Module, String, Int64, Int64, String, VSCodeServer.ReplRunCodeRequestParams})()
    @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.47.2/scripts/packages/VSCodeServer/src/eval.jl:199
 [16] withpath(f::VSCodeServer.var"#66#70"{Bool, Bool, Bool, Module, String, Int64, Int64, String, VSCodeServer.ReplRunCodeRequestParams}, path::String)
    @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.47.2/scripts/packages/VSCodeServer/src/repl.jl:249
 [17] (::VSCodeServer.var"#65#69"{Bool, Bool, Bool, Module, String, Int64, Int64, String, VSCodeServer.ReplRunCodeRequestParams})()
    @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.47.2/scripts/packages/VSCodeServer/src/eval.jl:155
 [18] hideprompt(f::VSCodeServer.var"#65#69"{Bool, Bool, Bool, Module, String, Int64, Int64, String, VSCodeServer.ReplRunCodeRequestParams})
    @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.47.2/scripts/packages/VSCodeServer/src/repl.jl:38
 [19] (::VSCodeServer.var"#64#68"{Bool, Bool, Bool, Module, String, Int64, Int64, String, VSCodeServer.ReplRunCodeRequestParams})()
    @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.47.2/scripts/packages/VSCodeServer/src/eval.jl:126
 [20] with_logstate(f::Function, logstate::Any)
    @ Base.CoreLogging ./logging.jl:514
 [21] with_logger
    @ ./logging.jl:626 [inlined]
 [22] (::VSCodeServer.var"#63#67"{VSCodeServer.ReplRunCodeRequestParams})()
    @ VSCodeServer ~/.vscode/extensions/julialang.language-julia-1.47.2/scripts/packages/VSCodeServer/src/eval.jl:225
 [23] #invokelatest#2
    @ ./essentials.jl:816 [inlined]
 [24] invokelatest(::Any)
    @ Base ./essentials.jl:813
 [25] macro expansion
    @ ~/.vscode/extensions/julialang.language-julia-1.47.2/scripts/packages/VSCodeServer/src/eval.jl:34 [inlined]
 [26] (::VSCodeServer.var"#61#62")()
    @ VSCodeServer ./task.jl:514

What am I doing wrong ? I’m sure it’s a stupid mistake.

Thanks for your time,

Francis Gagnon

I’m wondering, is ModelingToolkit appropriate for purely static systems ? It feels weird to build steady-state equations with ODESystem constructor. In the end, I want to be able to simulate a flowsheet in which some of the systems will be differential equations, others will be nonlinear steady-state equations. Is ModelingToolkit the right tool for it ?

Thanks !

Francis

I’m trying once more, does anyone with ModelingToolkit.jl experience are willing to help me ? In short, I’m only trying to implement a silo with two inlet and one outlet in steady-state using @component, thus the simple steady-state equation:

Ṁout = Ṁin1 + Ṁin2

in which Ṁin1 and Ṁin2 are simulation inputs. Should I use NonlinearSystem instead of ODESystem ?

Thanks !

Francis

The error you are seeing here is an error during display of the system, creating the system actually succeeds. Try adding a ; to prevent display and then see if you can create an ODEProblem or a NonlinearProblem (I think either should work).

@named circuit_model = ODESystem(circuit_eqs, t);
1 Like

Thanks for the help !

Indeed there is no error if I supress the output in the REPL with a ;. However, if I try to simplify the system including a semicolon:

using ModelingToolkit

@variables t

@connector function PipeNode(; name)
    states = @variables Ṁ(t) = 1.0 [connect = Flow]
    ODESystem(Equation[], t, states, []; name = name)
end

@component function Source(; name, feed = 1.0)
    @named outlet = PipeNode()
    params = @parameters feed = feed
    eqs = [
        outlet.Ṁ ~ feed
    ]
    compose(ODESystem(eqs, t, [], params; name = name), outlet)
end

@component function Sink(; name, product = 1.0)
    @named inlet = PipeNode()
    params = @parameters product = product
    eqs = [
        product ~ inlet.Ṁ
    ]
    compose(ODESystem(eqs, t, [], params; name = name), inlet)
end

@component function Silo(; name)
    @named inlet1 = PipeNode()
    @named inlet2 = PipeNode()
    @named outlet = PipeNode()
    eqs = [
        outlet.Ṁ ~ inlet1.Ṁ + inlet2.Ṁ
    ]
    compose(ODESystem(eqs, t, [], []; name = name), inlet1, inlet2, outlet)
end

@named silo = Silo()

@named feed_circuit = Source()
@named feed_screen  = Source()
@named prod_circuit = Sink()


circuit_eqs = [
    connect(feed_circuit.outlet, silo.inlet1)
    connect(feed_screen.outlet, silo.inlet2)
    connect(silo.outlet, prod_circuit.inlet)
]

@named _circuit_model = ODESystem(circuit_eqs, t);

@named circuit_model = compose(_circuit_model,
                          [silo, feed_circuit, feed_screen, prod_circuit]);

sys = structural_simplify(circuit_model);

I get a similar error:

ERROR: UndefVarError: `name` not defined
Stacktrace:
  [1] connection2set!(connectionsets::Vector{ModelingToolkit.ConnectionSet}, namespace::Nothing, ss::Tuple{ODESystem, ODESystem}, isouter::ModelingToolkit.var"#isouter#221"{Vector{Symbol}})
    @ ModelingToolkit ~/.julia/packages/ModelingToolkit/MDLZQ/src/systems/connectors.jl:195
  [2] generate_connection_set!(connectionsets::Vector{ModelingToolkit.ConnectionSet}, sys::ODESystem, find::Nothing, replace::Nothing, namespace::Nothing)
    @ ModelingToolkit ~/.julia/packages/ModelingToolkit/MDLZQ/src/systems/connectors.jl:312
  [3] generate_connection_set!
    @ ~/.julia/packages/ModelingToolkit/MDLZQ/src/systems/connectors.jl:273 [inlined]
  [4] generate_connection_set
    @ ~/.julia/packages/ModelingToolkit/MDLZQ/src/systems/connectors.jl:263 [inlined]
  [5] expand_connections(sys::ODESystem, find::Nothing, replace::Nothing; debug::Bool, tol::Float64)
    @ ModelingToolkit ~/.julia/packages/ModelingToolkit/MDLZQ/src/systems/connectors.jl:512
  [6] expand_connections (repeats 2 times)
    @ ~/.julia/packages/ModelingToolkit/MDLZQ/src/systems/connectors.jl:510 [inlined]
  [7] structural_simplify(sys::ODESystem, io::Nothing; simplify::Bool, kwargs::Base.Pairs{Symbol, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
    @ ModelingToolkit ~/.julia/packages/ModelingToolkit/MDLZQ/src/systems/systems.jl:21
  [8] structural_simplify
    @ ~/.julia/packages/ModelingToolkit/MDLZQ/src/systems/systems.jl:19 [inlined]
  [9] structural_simplify(sys::ODESystem)
    @ ModelingToolkit ~/.julia/packages/ModelingToolkit/MDLZQ/src/systems/systems.jl:19
 [10] top-level scope
    @ ~/Documents/Code/SimHPGR/src/mdltk_silo.jl:60

Any idea why ? Acausal compopnent-based modeling is not easy.

Francis

OK, I dug into this a little more. It turns out that this crash is a bug in some error reporting code in MTK, I made a PR, hopefully that will be merged soon.

What it is trying to say once you fix that is

ERROR: connect(feed_circuit₊outlet,silo₊inlet1) contains multiple source domain connectors. There can only be one!

A DomainConnector is a connector with only one flow variable and no other states. ModelingToolkit does not allow multiple DomainConnectors to be connected to one another, and I don’t understand why and can’t find the documentation for this. I don’t know how to get this model to work.

I would try adding a pressure variable to your connector and see if setting it to just pass through all your components (inlet.p ~ outlet.p) makes this work.

2 Likes

I hit the same problem and wrote an issue about it.

Clarify DomainConnector error message · Issue #3064 · SciML/ModelingToolkit.jl (github.com)

1 Like