I’m trying to set up a circulation model with units. Or at least allow consistency checks. So I was playing around with Model Validation and Units · ModelingToolkit.jl and set up the following:
using ModelingToolkit, Unitful
@parameters t [unit = u"s"]
@connector function Pin(; name)
sts = @variables p(t), [unit = u"Pa"], q(t), [unit = u"m^3 * s^-1", connect = Flow]
ODESystem(Equation[], t, sts, []; name = name)
end
function Ground(;name, P)
@named g = Pin()
ps = @parameters P = P [unit = u"Pa"]
eqs = [g.p ~ P]
compose(ODESystem(eqs, t, [], ps; name=name), g)
end
function OnePort(;name)
@named in = Pin()
@named out = Pin()
sts = @variables Δp(t) [unit = u"Pa"] q(t) [unit = u"m^3 * s^-1"]
eqs = [
Δp ~ out.p - in.p
0 ~ in.q + out.q
q ~ in.q
]
compose(ODESystem(eqs, t, sts, []; name=name), in, out)
end
function Resistor(;name, R)
@named oneport = OnePort()
@unpack Δp, q = oneport
ps = @parameters R [unit = u"Pa * s * m^-3"]
eqs = [
Δp ~ - q * R
]
extend(ODESystem(eqs, t, [], ps; name=name), oneport)
end
function Capacitor(;name, C)
@named oneport = OnePort()
@unpack Δp, q = oneport
ps = @parameters C [unit = u"m^3 * Pa^-1"]
D = Differential(t)
eqs = [
D(Δp) ~ - q / C
]
extend(ODESystem(eqs, t, [], ps; name=name), oneport)
end
function ConstantFlow(;name, Q)
@named oneport = OnePort()
@unpack q = oneport
ps = @parameters Q = Q [unit = u"m^3 * s^-1"]
eqs = [
q ~ Q
]
extend(ODESystem(eqs, t, [], ps; name=name), oneport)
end
@named source = ConstantFlow(Q = 1u"m^3 * s^-1")
@named R = Resistor(R = 1u"Pa * s * m^-3")
@named C = Capacitor(C = 1u"m^3 * Pa^-1")
@named ground = Ground(P = 0u"Pa")
eqs = [
connect(source.out, R.in)
connect(R.out, C.in)
connect(C.out, ground.g, source.in)
]
@named _model = ODESystem(eqs, t)
Which then fails with the following.
┌ Warning: in eq. #1left: no method matching get_unit for arguments (Connection,).
└ @ ModelingToolkit ~/.julia/packages/ModelingToolkit/H0KaK/src/systems/validation.jl:144
┌ Warning: in eq. #1right: no method matching get_unit for arguments (Connection,).
└ @ ModelingToolkit ~/.julia/packages/ModelingToolkit/H0KaK/src/systems/validation.jl:144
┌ Warning: in eq. #2left: no method matching get_unit for arguments (Connection,).
└ @ ModelingToolkit ~/.julia/packages/ModelingToolkit/H0KaK/src/systems/validation.jl:144
┌ Warning: in eq. #2right: no method matching get_unit for arguments (Connection,).
└ @ ModelingToolkit ~/.julia/packages/ModelingToolkit/H0KaK/src/systems/validation.jl:144
┌ Warning: in eq. #3left: no method matching get_unit for arguments (Connection,).
└ @ ModelingToolkit ~/.julia/packages/ModelingToolkit/H0KaK/src/systems/validation.jl:144
┌ Warning: in eq. #3right: no method matching get_unit for arguments (Connection,).
└ @ ModelingToolkit ~/.julia/packages/ModelingToolkit/H0KaK/src/systems/validation.jl:144
I am known to get my units mangled up, so that’s always an option. But it seems that there is a method missing. So the question is. Is this whole unit business compatible with the way I am using MTK?
The next two lines would be:
@named model = compose(_model, [source, R, C, ground])
sys = structural_simplify(model)
And I did quite expect structural_simplify
to fail. This whole exercise was to see if I could get away with it.
So if you can tell me that this does work and I’m just stupid and am making a silly mistake - that would be awesome.
If not, then I’ll forget about units for the time being and get back to modelling