Skip to main content

Module area

Module area 

Source
Expand description

Area interchange control: holding each control area’s net export at its scheduled value.

DistributedSlack drives one number to one target — the slack’s output to its own schedule. Interconnected systems schedule more than that: each control area agrees a net position with its neighbours, and the area’s generators are dispatched to meet it. An area importing 300 MW when it agreed to import 200 has every tie-line flow around it wrong, for the same reason a single slack absorbing an unscheduled few hundred megawatts does.

§The formulation

An area’s interchange is the active power leaving it across its own boundary branches, measured at its own side of each:

\[ X_a = \sum_{b \in \partial a} P_b^{(a\text{-side})} \]

and its mismatch is that against the schedule. The knob is the same one distributed slack uses: the participating generators’ p_spec.

§One area’s position is dependent, and it has to be

The targets are not independent. Each area’s side of a tie line is measured at its own terminal, into the branch, so both ends of a tie contribute positively and their sum is what the tie dissipates:

\[ \sum_a X_a = +\ell_{\text{tie}} \]

— a quantity nobody knows before the solve. (The sign is easy to get backwards: it is not that one area’s export is the other’s import, because the loss falls between them and belongs to neither.) Targets that sum to zero, which is what a set of agreed net positions looks like, are therefore unachievable by exactly the tie losses. Counting it out: the knobs are each area’s aggregate participant schedule, \(N\) of them; the conditions wanted are \(N\) interchange targets plus the slack on its own schedule, \(N+1\). Over-determined by one, always.

So the area holding the slack is the dependent one: its own target is not enforced, and its condition is that the slack produces its schedule instead. Every other area’s position is met exactly, and the slack’s area absorbs the tie losses — which is what a real interconnection does, and what makes one area’s position a residual rather than an agreement. AreaInterchangeReport::dependent names it, and its residual entry reports how far its nominal target was missed, so the number is visible rather than implied.

§Deriving the sign, which is the rest of the difficulty

For an area that is not the slack’s, an export above target means it should generate less, so the mismatch \(X_a - X_a^{target}\) is subtracted from the participants by weight.

For the slack’s area, write \(\delta_s\) for the slack’s excess over its own schedule. Its participants must take that excess up — exactly DistributedSlack’s move — so the quantity subtracted is \(-\delta_s\).

Worth checking the degenerate case, because it is also a test (area_interchange_with_one_area_is_distributed_slack): one area covering the whole network is the slack’s area, so the only condition is \(-\delta_s\), and the loop becomes distributed slack exactly. Area interchange generalizes it rather than sitting beside it, which is why powsybl-open-loadflow’s own AcAreaInterchangeControlOuterLoop constructs a DistributedSlackOuterLoop as its no-area fallback and why the two must not both be configured.

Structs§

AreaDefinition
Which buses belong to which control area, what each area is scheduled to export, and who adjusts to get there.
AreaInterchange
Drives every area’s net export to its scheduled value, and the slack to its own schedule, by moving the participating generators.
AreaInterchangeReport
What AreaInterchange did.