﻿id	summary	reporter	owner	description	type	status	priority	milestone	component	version	resolution	keywords	cc
6240	Extend overconstrained connector semantics to handle dynamic branches	Francesco Casella	Karim Adbdelhak	"This is a second, improved attempt to address this issue, following #6238

The overconstrained connector semantics defined in Section [https://specification.modelica.org/master/connectors-and-connections.html#equation-operators-for-overconstrained-connection-based-equation-systems1 9.4] of Modelica 3.4 considers a fixed connection graph, that can be handled statically at compile time. 

One of the cited examples for overconstrained types in connectors is the phase information in AC power systems. The current semantics is able to represent synchronous systems whose topology remains unchanged during simulation. The phase reference is generated by one component of the synchronous system (normally a power generator) and distributed throughout the entire synchronous system via the overconstrained connector variable. In fact, it is possible to have multiple synchronous systems in the same Modelica model, that correspond to structurally disconnected connections sub-graphs, e.g. two national grids connected by a DC link, but in any case their topology is fixed at runtime.

When modelling AC trasmission systems, is is possible that in case of severe perturbations, some key circuit breakers are switched open (i.e., their conductance brough to zero), effectively splitting a single synchronous system into multiple synchronous islands. Note that this requires no structural changes in the grid equations, only to set some admittance values to zero.

When this happens, the two (or more) ensuing islands can settle into new steady states with different frequencies. Hence, if a single, whole-system-wide reference is still used, the phase angle of currents and voltages of the now disconnected island(s) will continue to rotate permanently with a frequency that is the difference between the local island frequency and the frequency of the island where the original root node was picked. This is very inconvenient, because it prevents variable step-size solvers to increase the step size, once the system settles to the new steady state.

This problem could be avoided by allowing to dynamically break and reconnect the breakable branches corresponding to {{{connect()}}} statements in the connection graph of [https://specification.modelica.org/v3.4/Ch9.html#equation-operators-for-overconstrained-connection-based-equation-systems1 Section 9.4]. It would then be possible to break the synchronous connections established by transmission lines when their admittance is brough to zero, thus modelling effects of circuit breakers on the synchronous sub-system topology.

As a consequence, two or more disjoint connection graphs would be formed at the time of the breaker openings, each corresponding to a new synchronous island. The new graph topology should be analyzed at this point, picking a new root node for each newly formed island in the grid. Then, instead of having a single phase reference for the entire system, which would no longer be adequate, one would now have two or more independent phase references, one for each island, which would ensure that the variables of each island reach a steady state, thus avoiding the persistent sinusoidal oscillations found in the case of a statically determined connection topology.

From the point of view of the language specification, this extension only requires to add one optional Boolean input to the {{{connect()}}} statement
{{{
  connect(A.R, B.R, activeBranch = true);
}}}
where {{{activeBranch}}} tells whether a breakable branch should be added to the connection graph (possibly to be broken at a later stage to avoid loops), or not.

If {{{activeBranch}}} is set to a constant value of {{{true}}} (possibly by default), the behaviour is exactly the same as in Modelica 3.4. In case instead it is set to a Boolean variable, the breakable branch will only be added to the graph when {{{activeBranch = true}}}.

From an implementation point of view, this means that the graph connection analysis no longer can be performed statically at compile time, but needs to be deferred to run time. According to [https://specification.modelica.org/v3.4/Ch9.html#converting-the-connection-graph-into-trees-and-generating-connection-equations Section 9.4.2], everything except overconstrained connector variables is always handled in the same way, i.e., following [https://specification.modelica.org/v3.4/Ch9.html#generation-of-connection-equations Section 9.2], so the runtime analysis will be limited to overconstrained variables in connectors. Everthing else, including determining connection sets, building connection equations for flow variables, and handling stream connector variables, is unchanged and can still be managed statically at compile time.

In general this can be quite a big deal, because Modelica cannot handle structural dynamics at runtime. However, the special case of scalar overconstrained connector variables with zero-dimensional {{{equalityConstraint()}}} function output turns out to be very easy to handle, and is enough to address the issue with the synchronous AC grids. This is demonstrated by the attached examplary case.

The attached package contains components to build conceptual models of phasor-based AC power grid models. The components are overly simplified and only retain the minimal features that are needed to analyze this language semantics extension.

In this case, the overconstrained variable is actually not the phase angle but rather the angular velocity of the phasor reference frame, which is sufficient to ensure that all state variables are constant when the synchronous islands are all operating in steady state.

{{{System 1}}} is a basic example with two generators {{{G1}}} and {{{G2}}}, each connected to a local load, connected by an inductive transmission line {{{T}}}. The system starts in steady state with balanced loads, then at time = 1 the active power consumption of load {{{L2}}} is reduced by 20%. This starts a transient, that eventually dies out once the primary frequency controls stabilize the system at a new, higher frequency. Note that at that point, all state variables are constant, allowing implicit solvers to take large time steps.

{{{System 2}}} is similar to {{{System1}}}, except that line {{{T}}} is split in the series connection of lines {{{T1a}}} and {{{T1b}}}, running in parallel, with line {{{T2}}}. This allows to demonstrate the overconstrained connector mechanism, since {{{T1a}}} and {{{T1b}}} form a loop that must be broken to avoid getting an overconstrained system of equations. The overall impedance is the same, so the power and frequency transients are the same as in {{{System1}}}.

In {{{System 3}}}, line {{{T2}}} also includes a circuit breaker mechanism, that brings its susceptance {{{B}}} to zero when the {{{T2.open}}} signal becomes true. From that point onwards, there is no longer any exchange of power along the lines, so the system is effectively split into two synchronous islands, one containing {{{G1}}} and {{{L1}}}, the other one containing {{{G2}}} and {{{L2}}}. The frequencies of the two drift apart, causing the phasors and state variables of {{{G2}}} and {{{L2}}}, that still use {{{G1.port.omegaRef}}} as a reference angular velocity, to oscillate forever even when the new steady state is reached.

In order to avoid this, the connection graph needs to be split when the breaker embedded in {{{T2}}} is opened. This behaviour is achieved in {{{System4}}} by using the modified {{{TransmissionLineVariableBranch}}} component, that contains two public and one protected ports
{{{#!mo
  ACPort port_a;
  ACPort port_b;
protected
  ACPort port_b_int;
}}}
and the following equations
{{{#!mo
  port_a.i = Complex(0,B_act)*(port_a.v - port_b_int.v);
  when open then
    closed = false;
    B_act = 0;
  elsewhen close then
    closed = true;
    B_act = B;
  end when;
  port_a.omegaRef = port_b_int.omegaRef;
  Connections.branch(port_a.omegaRef, port_b_int.omegaRef);
  connect(port_b_int, port_b, closed);
}}}
where the breakable branch between the protected port {{{port_b_int}}} and the public {{{port_b}}} is only activated when {{{closed = true}}}.

Handling the case of Real overdetermined connector variables with empty constraint function is relatively straighforward.

During flattening, the front end should indentify all the structurally connected subgraphs (i.e., ignoring the values of {{{activeBranch}}}), then identify those of them that only contain static breakable branches (for which {{{activeBranch = true}}} by default or by means of constant-evaluated binding) and those that contain at least one dynamically breakable branch.

The former should be handled as in Modelica 3.4. For the latter, all the relevant information about overconstrained types and variables, and about nodes and branches of the corresponding subgraphs, should be passed to the backend using some suitable formalism. Subgraphs that are structurally unconnected, regardless of {{{activeBranch}}} status of their breakable branches should be identified.

I guess we should try to re-use the front-end code in the backend as much as possible, and even in the runtime code (e.g. for graph analysis) as long as the MetaModelica code of the frontend can be translated into C/C++ code.

The generated code should then perform the following operations at initialization and each time any {{{activeBranch}}} connection attribute changes:
- re-build the connection graphs of all the structurally unconnected sub-graphs to which the branches that changed their activation status belong, according to the rules set forth in [https://specification.modelica.org/master/connectors-and-connections.html#equation-operators-for-overconstrained-connection-based-equation-systems1 Section 9.4], only accounting for branches with {{{activeBranch = true}}}
- in case a previously de-activated branch is re-established, check that the corresponding connection equation involving the overconstrained connector variables is actually verified within some tolerance, otherwise aborting the simulation; this would correspond to the requirement that two islands can only be reconnected if the are operating exactly at the same frequency or phase. This check could be defined by adding one more function {{{reconnectable()}}} to the overconstrained type definition, which returns a boolean indicating if the reconnection is feasible (see below).
- identify disjoint sub-graphs within each structurally connected, re-built sub-graph, and select one root node for each of them, according the standard rules set forth in [https://specification.modelica.org/v3.4/Ch9.html#converting-the-connection-graph-into-trees-and-generating-connection-equations Section 9.4.2]
- break all loops in those sub-graphs
- set each overconstrained connector variable of each sub-graph to be equal to the value of the corresponding root node variable (this can be done trivially via pointers!)


If a frequency reference is used, the {{{reconnectable}}} function could be implemented as
{{{#!mo
function reconnectable
  input ReferenceFrequency f1;
  input ReferenceFrequency f2;
  output Boolean canReconnect;
protected
  constant Real eps = 1e-6;
algorithm
  canReconnect := abs(f1 - f2) < eps;
end reconnectable;
}}}

For phase references, one should account for {{{2*pi}}} ambiguity

{{{#!mo
function reconnectable
  input ReferenceAngle theta1;
  input ReferenceAngle theta2;
  output Boolean canReconnect;
protected
  constant Real eps = 1e-6;
  SI.Angle delta;
algorithm
  delta := (theta1 - theta2)- div(theta1 - thetha2, 2*pi)*2*pi;
  canReconnect := abs(delta) < eps;
end reconnectable;
}}}

I suppose this feature could be implemented rather easily in OpenModelica, as a first prototype implementation of this language extension. It could be tested in an extended version of the attached package, including some more examples with a bit more nodes and edges in the connection graphs, and finally tested on an extended version of the [https://github.com/powergrids PowerGrids library], that already envisioned such a feature. 

If the experiments with the prototype are successful, this could form the basis of an MCP to introduce this feature into the next version of the Modelica Specification."	enhancement	new	high	2.0.0	Backend	1.16.0			Andreas Heuermann Philip Hannebohm Per Östlund Adrian Pop Dietmar Winkler massimo ceraolo Andrea Bartolini adrien.guironnet@… Rüdiger Franke dr.christian.kral@… anton.haumer@…
