I have the following simple hierarchical model comprising a reaction inside a chamber. The reaction model simply sets the mass rate to the mass, and it's connected to the chamber that encloses it.
connector Conn
Real mass;
flow Real massRate;
end Conn;
model Reaction
Conn conn;
equation
conn.massRate = conn.mass;
end Reaction;
model Chamber
Real mass(start = 1);
Reaction reaction;
Conn conn;
equation
conn.mass = mass;
der(mass) = conn.massRate;
connect(reaction.conn, conn);
end Chamber;
Now to my mind, there are in total five variables: mass
, reaction.conn.mass
, reaction.conn.massRate
, conn.mass
, and conn.massRate
. And there are five equations: two in the equation section, viz.
conn.mass = mass
der(mass) = conn.massRate
one from the reaction
reaction.conn.massRate = reaction.conn.mass
and two from the connect equation:
reaction.conn.mass = conn.mass
reaction.conn.massRate = conn.massRate
So we have five equations in five variables. The solver logic can simply combine these equations like so
der(mass) = conn.massRate = reaction.conn.massRate = reaction.conn.mass
= conn.mass = mass
and since the mass is given a start value, Bob's your uncle. The mass
should increase over time. But my simulation environment (Wolfram|One) says
Error: Simulation model is not globally balanced, having 1 variable and 2 equations.
Can someone please explain what is going on? Note that if I take the reactor outside the chamber (reversing the sign in the reaction to give conn.massRate = -conn.mass
), it works as intended.
This is described in section "4.7 Balanced Models" in the Modelica specification.
The problem is that chamber has a top-level connector conn
and there is also one equation related to that; e.g. conn.massRate=0;
corresponding to a default-connected connector in a hierarchical model. Not only is it one equation too many - it is also wrong.
In addition if you used the Chamber as a sub-model, and wanted to add an external flow into/out of the Chamber you could connect to conn
- but the equations wouldn't make sense.
When you move the reactor out of the chamber you avoid that dangling connector. Another alternative, that might be clearer would be to have two models such as:
model Chamber
Reaction reaction;
MassPart source;
equation
connect(reaction.conn, source.conn);
end Chamber;
model MassPart
Conn conn;
Real mass(start=1);
equation
conn.mass = mass;
der(mass) = -conn.massRate;
end MassPart;
(assuming I got the sign-part right). Here you can see that the MassPart and Reaction in themselves both have the same number of equations and variables, when you add one equation for the flow-variable of the connector.