Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion chapters/classes.tex
Original file line number Diff line number Diff line change
Expand Up @@ -1034,6 +1034,7 @@ \section{Balanced Models}\label{balanced-models}
For each declared component of specialized class \lstinline!connector! component, it is the number of unknown variables inside it (i.e., excluding parameters and constants and counting the elements after expanding all records and arrays to a set of scalars of primitive types).
\item
For each declared component of specialized class \lstinline!block! or \lstinline!model!, it is the sum of the number of inputs and flow variables in the (top level) public connector components of these components (and counting the elements after expanding all records and arrays to a set of scalars of primitive types).
If these public connector components contain overdetermined connectors each instance of an overdetermined type or record in that connector is assumed to be a separate root.
Copy link
Collaborator

@qlambert-pro qlambert-pro Nov 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is overly abstract and as I explained before the only way I am signing off on it is if other people prefer this formulation to what I proposed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So that others can find that alternative (which responded to a previous variant of this text):

An alternative to the count here is:

  • For over-determined variables and equations, where the cardinality of the type is c and the size of the residual is n:
    • Over-determined connector variables are counted as n variables.
    • Declaration and equality equation of over-determined type are counted as c.
    • Connections.root and Connections.branch are counted as adding n - c equations.
    • Connections.potentialRoot is counted as adding n - c if the root is selected and 0 otherwise.
    • Generated potential equations are counted as adding n equations.

Originally posted by @qlambert-pro in #3750 (comment)

I have a hard time understanding how that description really works, as Connections.root and Connections.potentialRoot don't directly contribute to the global equation count (for potentialRoot there is normally an if-equation based on whether it is selected as root or not).

However, I can understand that this problem is abstract and complicated to get right.

The following are four cases that seem to covert this:

  • A root-less component with one over-determined connector, like Modelica.Mechanics.MultiBody.Forces.WorldForce
  • A component with a root and one over-determined connector, like a simplified Modelica.Mechanics.MultiBody.Parts.Body
  • A (root-less) component with a pair of over-determined connectors connected to similar ones in a sub-component, like Modelica.Mechanics.MultiBody.Forces.Spring
  • A (root-less) component with a pair of over-determined connectors connected to similar ones in two sub-component (like a parallel Spring and Damper variant built by components).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After some additional thinking:

I still don't think that describing local variable and equation sizes in that way for the local check would be good, as it creates a different way of counting even for a simple model with overdetermined connectors and without sub-components.

However, it indicates that it is locally and globally possible to check balancing without generating the spanning tree and the corresponding equations, and that seems seems like something that could be documented in general. I would slightly rewrite it as (and view that as a separate pull-request):

-Start-

For checking the number of variables and equations for overdetermined connectors an alternative to generating equations from the spanning tree is the following (note that this often generates fewer variables and equations, but both counts are decreased by the same amount):

For over-determined variables and equations, where the cardinality of the type is c and the size of the residual is n (where c>=n):

  • Over-determined connector variables are counted as n variables.
  • Declaration and equality equation of over-determined type are counted as c.
  • Connections.root and Connections.branch are counted as adding c-n variables.
  • Connections.potentialRoot is counted as adding c-n variables if the root is selected and 0 otherwise.
  • Generated potential equations (from connections) are counted as adding n equations.

The balance should hold for all legal selections of potential roots, and also for all possibilities for Connections.isRooted. For local check only the local Connections.root etc are considered.

The addition of c-n variables effectively mean that roots (and one of the arguments to branch) are counted as having the cardinality of its type, c.

-End-

Notes:

  • The over-determined connector variables counted as c correspond to branches being in parallel with equations for the entire over-determined connector (i.e., of size c) and roots having equations for the entire over-determined connector, i.e., c equations, not only equations for the residual.
  • The statement that it should hold for all selections adds something, both locally and globally.
  • It is still necessary to process connections, due to the possibility of redundancy in the connection sets (both for over-determined connectors and for normal ones).
  • I prefer to add positive variables instead of subtracting equations (or as above adding a negative number), since negative number of equations are generally quite confusing for users; and in this case the added variables isn't just a number, but it corresponds to actual variables as explained above (or specifically it change the count to an actual variable).
  • It indirectly uses the spanning tree as explained below.

For simulation models this is consistent with the equation count in for the spanning tree since:

  • Nodes will add c-n variables (unless already done), and based on the spanning tree a corresponding number of equations:
    • If there's incoming edge to the node and it is an optional spanning tree edge it means we generate normal equations for the connection, of size c, i.e., adding c-n equations.
    • Otherwise it must be a root (potential or otherwise), or have a required edge as incoming (based on Connection.branch), and in those cases we already added c-n variables.
  • If an optional spanning tree isn't such an incoming edge it has been removed from the spanning tree, and generate n residual equations.

An alternative that is more intuitive, except for one minor issue, would be to reduce the changes to:

  • Over-determined connector variables are counted as c variables, if they are (locally) selected as root (potential or otherwise) or the target of Connections.branch; in all other cases as n variables.
  • Generated potential equations (from connections) are counted as adding n equations (regardless of whether the branch is broken or not).

The only issue is that the Connections.branch "target" must be a non-root to avoid double-counting. So, if you have two potential roots and a branch between them you may have to adjust the target depending on the root-selection (both cannot be selected). Trivial, but that is sort of looking at the spanning tree).

That model is an issue also for the proposal above, that is hidden in the "all legal selection of roots", so if someone has such a model and writes if Connections.isRoot(f_a.o) then ... else if Connections.isRoot(f_b.o) then else ... end if based on the understanding that only one of them will be a root we need to use the spanning tree information to rule out both being selected as roots, since otherwise it will be unbalanced in that case.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the cases above with an over-constrained connector, Frame, with n flows and c variables in the over-determined type. To me one major benefit of this way of thinking is that one can adjust this to not only have a local balance in terms of number of variables and equations, but also construct structurally non-singular equations based on this, which may find structurally singular sub-components even if they are balanced.

Modelica.Mechanics.MultiBody.Parts.Body (with potential root we also cover Modelica.Mechanics.MultiBody.Forces.WorldForce). The thing that makes it complicated is the quaternions which are due to the same underlying issue with over-determined types, so I thought it best to include that as well in a general setting:

model SimpleBody
   constant Integer nQ=4;
   constant Real dummyQ[nQ]=...;
   Real Q[nQ];
   Frame frame_a;
equation
   Connections.potentialRoot(frame_a.R);
   if Connections.isRoot(frame_a.R) then
      frame_a.R=from_Q(Q);
      zeros(nQ-n)=orientationConstraint(Q);
   else
      Q=dummyQ;
   end if;
end SimpleBody;

It has if nQ+n+c variables and the same number of equations:

  • Actual equations if isRoot(frame_a.R) then c+(nQ-n) else nQ
  • Equations for flow-variables in outside connectors n
  • Possibly root-less spanning tree if isRoot(frame_a.R) then 0 else c-n

Note: This works both if the over-determined type describe rotation as rotation matrix (c=9) or as quaternion(c=4).

Connection from a sub-component (half of Modelica.Mechanics.MultiBody.Forces.Spring - it would be straightforward to add the other half):

model HalfSpring
  Frame frame_a;
  HalfLineForce halfLine;
equation
  connect(frame_a, halfLine.frame_a);
end HalfSpring;

It has n+c+n variables (we only consider flow-variables for connectors in sub-components) and the same number of equations:

  • Actual equations with just equality for connect: n+c equations.
  • Equations for flow-variables in outside connectors n
  • No root-less spanning tree: 0

Connection from a sub-component (half of spring-damper built in the same way`):

model HalfSpringDamper
  Frame frame_a;
  HalfLineForce lineSpring;
  HalfLineForce lineDamper;
equation
  connect(frame_a, lineSpring.frame_a);
  connect(frame_a, lineDamper.frame_a);
end HalfSpringDamper;

Since both of the inside over-determined connectors are seen as roots it has to break of the connections.

It has n+c+n*2 variables (we only consider flow-variables for connectors in sub-components), and the same number of equations:

  • Flows summing to zero: n
  • One connect generating normal potential equations: c equations
  • One connect being over-determined: n residual equations
  • Equations for flow-variables in outside connectors n
  • No root-less spanning tree: 0

However, even if I could include that in the specification as examples (with both halves) I now think it would be too much.

\end{itemize}
\end{definition}

Expand Down Expand Up @@ -1130,7 +1131,7 @@ \section{Balanced Models}\label{balanced-models}
\end{example}
\item
In a declarations of a component of a \lstinline!model! or \lstinline!block! class, modifiers shall only contain redeclarations of replaceable elements and binding equations.
The binding equations in modifiers for components may in these cases only be for parameters, constants, inputs and variables having a default binding equation.
The binding equations in modifiers for components may in these cases only be for parameters, constants, non-connector inputs and variables having a default binding equation.
For the latter case of variables having a default binding equation the modifier may not remove the binding equation using \lstinline!break!, see \cref{removing-modifiers-break}.
\item
Modifiers of base-classes (on extends and short class definitions) shall only contain redeclarations of replaceable elements and binding equations.
Expand Down
8 changes: 5 additions & 3 deletions chapters/connectors.tex
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ \subsection{Expandable Connectors}\label{expandable-connectors}
Introducing elements in an array gives an array with at least the specified elements, other elements are either not created or have a default value (i.e., as if they were only potentially present, and the same note regarding the use of \lstinline!size! also applies here).
\item
If the variable on the other side of the \lstinline!connect!-equation is \lstinline!input! or \lstinline!output! the new component will be either \lstinline!input! or \lstinline!output! to satisfy the restrictions in \cref{restrictions-of-connections-and-connectors} for a non-expandable connector.
If both would be valid it shall be \lstinline!input! to ensure that there is a source of the signal.
If the corresponding connection set contain two or more variables in expandable connectors that are deduced to be input it is an error as there should only be one source of the signal.
\begin{nonnormative}
The general rule ensures consistency for inside and outside connectors, and handles multiple connections to the new component.
In the simple case of no other connections involving these variables and the existing side referring to an inside connector (i.e., a connector of a component), the new variable will copy its causality (i.e., \lstinline!input! if \lstinline!input! and \lstinline!output! if \lstinline!output!) since the expandable connector must be an outside connector.
Expand Down Expand Up @@ -622,9 +624,9 @@ \section{Restrictions of Connections and Connectors}\label{restrictions-of-conne

\subsection{Balancing Restriction and Size of Connectors}\label{balancing-restriction-and-size-of-connectors}

For each non-partial non-simple non-expandable connector class the number of flow variables shall be equal to the number of variables that are neither \lstinline!parameter!, \lstinline!constant!, \lstinline!input!, \lstinline!output!, \lstinline!stream! nor \lstinline!flow!.
The \emph{number of variables} is the number of all elements in the connector class after expanding all records and arrays to a set of scalars of primitive types.
The number of variables of an overdetermined type or record class (see \cref{overconstrained-equation-operators-for-connection-graphs}) is the size of the output argument of the corresponding \lstinline!equalityConstraint!() function.
For each non-partial non-simple non-expandable connector class the number of flow variables shall be equal to the number of potential variables that are neither \lstinline!parameter!, \lstinline!constant!, \lstinline!input!, \lstinline!output!, \lstinline!stream! nor \lstinline!flow!.
The \emph{number of potential variables} is the number of all elements in the connector class after expanding all records and arrays to a set of scalars of primitive types.
The number of potential variables of an overdetermined type or record class (see \cref{overconstrained-equation-operators-for-connection-graphs}) is the size of the output argument of the corresponding \lstinline!equalityConstraint!() function.
A simple connector class is not expandable, has some time-varying variables, and has neither \lstinline!input!, \lstinline!output!, \lstinline!stream! nor \lstinline!flow! variables.
\begin{nonnormative}
Expandable connector classes are excluded from this, since their component declarations are only a form of constraint.
Expand Down