The basic concept to count unknowns and equations.
Restrictions for model and block classes are present, in order that missing or too many equations can be detected and localized by a Modelica translator before using the respective model or block class.
partial model BaseCorrelation input Real x; Real y; end BaseCorrelation; model SpecialCorrelation // correct in Modelica 2.2 and 3.0 extends BaseCorrelation(x=2); equation y=2/x; end SpecialCorrelation; model UseCorrelation // correct according to Modelica 2.2 // not valid according to Modelica 3.0 replaceable model Correlation=BaseCorrelation; Correlation correlation; equation correlation.y=time; end UseCorrelation; model Broken // after redeclaration, there is 1 equation too much in Modelica 2.2 UseCorrelation example(redeclare Correlation=SpecialCorrelation); end Broken;
In this case one can argue that both UseCorrelation (adding an acausal equation) and SpecialCorrelation (adding a default to an input) are correct, but still when combined they lead to a model with too many equations - and it is not possible to determine which model is incorrect without strict rules. In Modelica 2.2, model Broken will work with some models. However, by just redeclaring it to model SpecialCorrelation, an error will occur and it will be very difficult in a larger model to figure out the source of this error. In Modelica 3.0, model UseCorrelation is no longer allowed and the translator will give an error. In fact, it is guaranteed that a redeclaration cannot lead to an unbalanced model any more.
The restrictions below apply after flattening " i.e., inherited components are included " possibly modified.
Definition 1: Local Number of Unknowns
The local number of unknowns of a model or block class is the sum based on the components:
Definition 2: Local Equation Size
The local equation size of a model or block class is the sum of the following numbers:
model M input Real u; input Real u2=2; end M;Here "u" and "u2" are top-level inputs and not connectors. The variable u2 has a binding equation, but u does not have a binding equation. In the equation count, it is assumed that an equation for u is supplied when using the model.]
Definition 3: Locally Balanced
A model or block class is "locally balanced" if the "local number of unknowns" is identical to the "local equation size" for all legal values of constants and parameters [respecting final bindings and min/max-restrictions. A tool shall verify the "locally balanced" property for the actual values of parameters and constants in the simulation model. It is a quality of implementation for a tool to verify this property in general, due to arrays of (locally) undefined sizes, conditional declarations, for loops, etc.].
Definition 4: Globally Balanced
Similarly as locally balanced, but including all unknowns and equations from all components. The global number of unknowns is computed by expanding all unknowns (i.e., excluding parameters and constants) into a set of scalars of primitive types. This should match the global equation size defined as:
The following restrictions hold:
Based on these restrictions, the following strong guarantee can be given for simulation models and blocks:
Proposition 1: All simulation models and blocks are
globally balanced.
[Therefore the number of unknowns equal to the number of equations
of a simulation model or block, provided that every used
non-partial model or block class is locally balanced.]
Example 1: connector Pin Real v; flow Real i; end Pin; model Capacitor parameter Real C; Pin p, n; Real u; equation 0 = p.i + n.i; u = p.v - n.v; C*der(u) = p.i; end Capacitor;
Model Capacitor is a locally balanced model according to the following analysis:
Locally unknown variables: p.i, p.v, n.i, n.v, u Local equations: 0 = p.i + n.i; u = p.v - n.v; C*der(u) = p.i; and 2 equations corresponding to the 2 flow-variables p.i and n.i.
These are 5 equations in 5 unknowns (locally balanced model). A more detailed analysis would reveal that this is structurally non-singular, i.e., that the hybrid DAE will not contain a singularity independent of actual values. If the equation "u = p.v - n.v" would be missing in the Capacitor model, there would be 4 equations in 5 unknowns and the model would be locally unbalanced and thus simulation models in which this model is used would be usually structurally singular and thus not solvable. If the equation "u = p.v - n.v" would be replaced by the equation "u = 0" and the equation C*der(u) = p.i would be replaced by the equation "C*der(u) = 0", there would be 5 equations in 5 unknowns (locally balanced), but the equations would be singular, regardless of how the equations corresponding to the flow-variables are constructed because the information that "u" is constant is given twice in a slightly different form.
Example 2: connector Pin Real v; flow Real i; end Pin; partial model TwoPin Pin p,n; end TwoPin; model Capacitor parameter Real C; extends TwoPin; Real u; equation 0 = p.i + n.i; u = p.v " n.v; C*der(u) = p.i; end Capacitor; model Circuit extends TwoPin; replaceable TwoPin t; Capacitor c(C=12); equation connect(p, t.p); connect(t.n, c.p); connect(c.n, n); end Circuit;
Since t is partial we cannot check whether this is a globally balanced model, but we can check that Circuit is locally balanced. Counting on model Circuit results in the following balance sheet:
Locally unknown variables (8): p.i, p.v, n.i, n.v, and 2 flow variables for t (t.p.i, t.n.i) and 2 flow variable for c (c.p.i, c.n.i). Local equations: p.v = t.p.v; 0 = p.i - t.p.i; c.p.v = load.n.v; 0 = c.p.i+load.n.i; n.v = c.n.v; 0 = n.i - c.n.i; and 2 equation corresponding to the flow variables p.i, n.i
In total we have 8 scalar unknowns and 8 scalar equations, i.e., a locally balanced model (and this feature holds for any models used for the replaceable component "t"). Some more analysis reveals that this local set of equations and unknowns is structurally non-singular. However, this does not provide any guarantees for the global set of equations, and specific combinations of models that are "locally non-singular" may lead to a globally non-singular model.]
Example 3: import SI = Modelica.SIunits; partial model BaseProperties "Interface of medium model for all type of media" parameter Boolean preferredMediumStates=false; constant Integer nXi "Number of independent mass fractions"; InputAbsolutePressure p; InputSpecificEnthalpy h; InputMassFraction Xi[nXi]; SI.Temperature T; SI.Density d; SI.SpecificInternalEnergy u; connector InputAbsolutePressure = input SI.AbsolutePressure; connector InputSpecificEnthalpy = input SI.SpecificEnthalpy; connector InputMassFraction = input SI.MassFraction; end BaseProperties;
The use of connector here is a special design pattern. The variables p, h, Xi are marked as input to get correct equation count. Since they are connectors they should neither be given binding equations in derived classes nor when using the model. The design pattern is to give textual equations for them (as below); using connect-statements for these connectors would be possible (and would work) but is not part of the design. This partial model defines that T,d,u can be computed from the medium model, provided p,h,Xi are given. Every medium with one or multiple substances and one or multiple phases, including incompressible media, has the property that T,d,u can be computed from p,h,Xi. A particular medium may have different "independent variables" from which all other intrinsic thermodynamic variables can be recursively computed. For example, a simple air model could be defined as:
model SimpleAir "Medium model of simple air. Independent variables: p,T" extends BaseProperties(nXi = 0, p(stateSelect = if preferredMediumStates then StateSelect.prefer else StateSelect.default), T(stateSelect = if preferredMediumStates then StateSelect.prefer else StateSelect.default)); constant SI.SpecificHeatCapacity R = 287; constant SI.SpecificHeatCapacity cp = 1005.45; constant SI.Temperature T0 = 298.15 equation d = p/(R*T); h = cp*(T-T0); u = h " p/d; end SimpleAir;
The local number of unknowns in model SimpleAir (after flattening) is:
The local equation size is:
Therefore, the model is locally balanced. The generic medium model BaseProperties is used as a replaceable model in different components, like a dynamic volume or a fixed boundary condition:
import SI = Modelica.SIunits connector FluidPort replaceable model Medium = BaseProperties; SI.AbsolutePressure p; flow SI.MassFlowRate m_flow; SI.SpecificEnthalpy h; flow SI.EnthalpyFlowRate H_flow; SI.MassFraction Xi [Medium.nXi] "Independent mixture mass fractions"; flow SI.MassFlowRate mXi_flow[Medium.nXi] "Independent substance mass flow rates"; end FluidPort; model DynamicVolume parameter SI.Volume V; replaceable model Medium = BaseProperties; FluidPort port(redeclare model Medium = Medium); Medium medium(preferredMediumStates=true); // No modifier for p,h,Xi SI.InternalEnergy U; SI.Mass M; SI.Mass MXi[medium.nXi]; equation U = medium.u*M; M = medium.d*V; MXi = medium.Xi*M; der(U) = port.H_flow; // Energy balance der(M) = port.m_flow; // Mass balance der(MXi) = port.mXi_flow; // Substance mass balance // Equations binding to medium (inputs) medium.p = port.p; medium.h = port.h; medium.Xi = port.Xi; end DynamicVolume;
The local number of unknowns of DynamicVolume is:
resulting in 8+4*nXi unknowns; the local equation size is
Therefore, DynamicVolume is a locally balanced model. Note, when the DynamicVolume is used and the Medium model is redeclared to "SimpleAir", then a tool will try to select p,T as states, since these variables have StateSelect.prefer in the SimpleAir model (this means that the default states U,M are derived quantities). If this state selection is performed, all intrinsic medium variables are computed from medium.p and medium.T, although p and h are the input arguments to the medium model. This demonstrates that in Modelica input/output does not define the computational causality. Instead, it defines that equations have to be provided here for p,h,Xi, in order that the equation count is correct. The actual computational causality can be different as it is demonstrated with the SimpleAir model.
model FixedBoundary_pTX parameter SI.AbsolutePressure p "Predefined boundary pressure"; parameter SI.Temperature T "Predefined boundary temperature"; parameter SI.MassFraction Xi[medium.nXi] "Predefined boundary mass fraction"; replaceable model Medium = BaseProperties; FluidPort port(redeclare model Medium = Medium); Medium medium; equation port.p = p; port.H_flow = semiLinear(port.m_flow, port.h , medium.h); port.MXi_flow = semiLinear(port.m_flow, port.Xi, medium.Xi); // Equations binding to medium (note: T is not an input). medium.p = p; medium.T = T; medium.Xi = Xi; end FixedBoundary_pTX;
The number of local variables in FixedBoundary_pTX is:
resulting in 6+3*nXi unknowns, while the local equation size is
Therefore, FixedBoundary_pTX is a locally balanced model. The predefined boundary variables p and Xi are provided via equations to the input arguments medium.p and medium.Xi, in addition there is an equation for T in the same way " even though T is not an input. Depending on the flow direction, either the specific enthalpy in the port (port.h) or h is used to compute the enthalpy flow rate H_flow. "h" is provided as binding equation to the medium. With the equation "medium.T = T", the specific enthalpy "h" of the reservoir is indirectly computed via the medium equations. Again, this demonstrates, that an "input" just defines the number of equations have to be provided, but that it not necessarily defines the computational causality.