Advanced

Network elements can be described in an advanced way with reactive limits, loading limits, phase and ratio tap changers.

Reactive limits

Javadoc

The reactive limits may be used to model limitations of the reactive power of generators, VSC converter stations and batteries.

Min-Max reactive limits

With the min-max reactive limits, the reactive power does not depend on the active power. For any active power value, the reactive power value is in the [minQ, maxQ] interval.

Reactive capability curve

With the reactive capability curve limits, the reactive power limitation depends on the active power value. This dependency is based on a curve provided by the user. The curve is defined as a set of points that associate, to each active power value, a minimum and maximum reactive power value. In between the defined points of the curve, the reactive power limits are computed through a linear interpolation.

Examples

This example shows how to use the MinMaxReactiveLimits and ReactiveCapabilityCurve classes:

Generator generator = network.getGenerator("G");
if (generator.getReactiveLimits().getKind() == ReactiveLimitsKind.MIN_MAX) {
    MinMaxReactiveLimits limits = generator.getReactiveLimits(MinMaxReactiveLimits.class);
    System.out.println("MinMaxReactiveLimits: [" + limits.getMinQ() + ", " + limits.getMaxQ() + "]");
} else {
    ReactiveCapabilityCurve limits = generator.getReactiveLimits(ReactiveCapabilityCurve.class);
    System.out.println("ReactiveCapabilityCurve:");
    limits.getPoints().forEach(p -> System.out.println("\t" + p.getP() + " -> [" + p.getMinQ() + ", " + p.getMaxQ() + "]"));
}

This example shows how to create a new MinMaxReactiveLimits object:

Generator generator = network.getGenerator("G");
generator.newMinMaxReactiveLimits()
    .setMinQ(-100.0)
    .setMaxQ(100.0)
    .add();

This example shows how to create a new ReactiveCapabilityCurve object:

Generator generator = network.getGenerator("G");
generator.newReactiveCapabilityCurve()
    .beginPoint()
        .setP(-10)
        .setMinQ(-10)
        .setMaxQ(10)
    .endPoint()
    .beginPoint()
        .setP(0)
        .setMinQ(-20)
        .setMaxQ(20)
    .endPoint()
    .beginPoint()
        .setP(10)
        .setMinQ(-15)
        .setMaxQ(-15)
    .endPoint()
    .add();

Loading Limits

Javadoc

Some equipment has operational limits regarding the current, active power or apparent power value, corresponding to the equipment’s physical limitations (related to heating).

Loading limits can be declined into active power limits (in MW), apparent power limits (in kVA) and current limits (in A). They may be set for lines, boundary lines, tie lines (via their boundary lines), two-winding transformers and three-winding transformers. The active power limits are in absolute value.

Loading limits are defined by one permanent limit and any number of temporary limits (zero or more). The permanent limit sets the current, active power or apparent power absolute value under which the equipment can safely be operated for any duration. The temporary limits can be used to define higher current, active power or apparent power limitations corresponding to specific operational durations. A temporary limit thus has an acceptable duration.

The component on which the current limits are applied can safely remain between the preceding limit (it could be another temporary limit or a permanent limit) and this limit for a duration up to the acceptable duration. Please look at this scheme to fully understand the modeling (the following example shows current limits, but this modeling is valid for all loading limits):

Loading limits model Loading limits model

Note that, following this modeling, in general, the last temporary limit (the higher one in value) should be infinite with an acceptable duration different from zero, except for tripping current modeling where the last temporary limit is infinite with an acceptable duration equal to zero. If temporary limits are modeled, the permanent limit becomes mandatory. If no temporary limit is present, then the acceptable duration above the permanent limit will be infinite.

Limit group collection

In network development studies or in an operational context (CGMES), we can have a set of operational limits according to the season (winter vs summer, for example), the time of the day (day vs night) etc. In PowSyBl, users can store a collection of limits:

  • Active power limits, apparent power limits and current limits are gathered into an OperationalLimitsGroup object.

  • Lines, transformers (and other mentioned above in Loading limits) are associated with a collection of OperationalLimitsGroup (one collection per side/leg). Users can then choose one or more OperationalLimitsGroup to activate according to their needs.

OperationalLimitsGroup objects have an id, and may have properties — which allow associating additional arbitrary data items under the general schema of pairs <Key, Value>. Note that unlike the properties on the network components, no notification is emitted when a property is added, changed or removed.

Examples

Four examples are provided below, with their corresponding limits scheme, to show clearly how to create new CurrentLimits instances.

First example

This first example creates a CurrentLimits instance containing one permanent limit and two temporary limits.

CurrentLimits currentLimits = network.getBoundaryLine("DL").newCurrentLimits()
    .setPermanentLimit(100.0)
    .beginTemporaryLimit()
        .setName("TL1")
        .setValue(120.0)
        .setAcceptableDuration(20 * 60)
    .endTemporaryLimit()
    .beginTemporaryLimit()
        .setName("TL2")
        .setValue(140.0)
        .setAcceptableDuration(10 * 60)
    .endTemporaryLimit()
    .add();

Current limits scheme_example1 Current limits scheme_example1

Second example

This second example creates a CurrentLimits instance containing one permanent limit and three temporary limits, one of them having an infinite limit value.

CurrentLimits currentLimits = network.getBoundaryLine("DL").newCurrentLimits()
    .setPermanentLimit(700.0)
    .beginTemporaryLimit()
        .setName("IT20")
        .setValue(800.0)
        .setAcceptableDuration(20 * 60)
    .endTemporaryLimit()
    .beginTemporaryLimit()
        .setName("IT10")
        .setValue(900.0)
        .setAcceptableDuration(10 * 60)
    .endTemporaryLimit()
    .beginTemporaryLimit()
        .setName("IT1")
        .setValue(Double.POSITIVE_INFINITY)
        .setAcceptableDuration(60)
    .endTemporaryLimit()
    .add();

Current limits scheme_example2 Current limits scheme_example2

Third example

This third example shows how to create multiple OperationalLimitsGroup on the same end, and set one of these as the selected (active) one.

Line line = network.getLine("Line");

line.newOperationalLimitsGroup1("SUMMER")
        .newCurrentLimits()
        .setPermanentLimit(60)
        .beginTemporaryLimit()
        .setName("TATL-10")
        .setValue(80)
        .setAcceptableDuration(10 * 60)
        .endTemporaryLimit()
        .add();

line.newOperationalLimitsGroup1("WINTER")
        .newCurrentLimits()
        .setPermanentLimit(100)
        .beginTemporaryLimit()
        .setName("TATL-10")
        .setValue(120)
        .setAcceptableDuration(10 * 60)
        .endTemporaryLimit()
        .add();

line.setSelectedOperationalLimitsGroup1("WINTER");

In this example, there is two sets of limits on the same line side (1). The selected set is the winter one: the limits violations will be tested against this set. Note that all setSelected methods will only keep a single set of limit activated at a time. Selecting “WINTER” then “SUMMER” this way will result in the only active group being the last selected (aka “SUMMER”). To have multiple OperationalLimitsGroup selected at the same time, see below the fourth example.

Fourth example

This fourth example creates three OperationalLimitsGroup on the same end, and sets all of them as selected (active).

final String activatedOneOne = "activated_1_1";
final String activatedOneTwo = "activated_1_2";

Line line = network.getLine("Line");

// create the default operational limits group and select it
line.getOrCreateSelectedOperationalLimitsGroup1().newCurrentLimits().setPermanentLimit(500).add();
// create two other operational limits group
line.newOperationalLimitsGroup1(activatedOneOne).newCurrentLimits()
        .setPermanentLimit(1100)
        .beginTemporaryLimit()
        .setName("10'")
        .setAcceptableDuration(10 * 60)
        .setValue(1200)
        .endTemporaryLimit()
        .beginTemporaryLimit()
        .setName("1'")
        .setAcceptableDuration(60)
        .setValue(1500)
        .endTemporaryLimit()
        .beginTemporaryLimit()
        .add();

line.newOperationalLimitsGroup1(activatedOneTwo).newCurrentLimits()
        .setPermanentLimit(300)
        .beginTemporaryLimit()
        .setName("40'")
        .setAcceptableDuration(40 * 60)
        .setValue(700)
        .endTemporaryLimit()
        .beginTemporaryLimit()
        .setName("0.5'")
        .setAcceptableDuration(30)
        .setValue(1600)
        .endTemporaryLimit()
        .beginTemporaryLimit()
        .setName("N/A") //there is no need to explicitly create this limit for the acceptable duration above the last temporary limit to be 0, this is just an example
        .setAcceptableDuration(0)
        .setValue(Double.MAX_VALUE)
        .endTemporaryLimit()
        .add();

// select the two other limits group on the side 1, no need to select the first created group, the function we used already selected it
line.addSelectedOperationalLimitsGroups(TwoSides.ONE, activatedOneOne, activatedOneTwo);

We thus have 3 OperationalLimitsGroup selected on the side 1 of the line. Note that not all created groups need to be activated, here all are activated, but we could have activated only 2 out of 3 (or 1 out of 3). Each activated group can return information about the acceptable duration (which can be different depending on the group).

The spacing on the y axis (branch current) is not to scale.

Current limits scheme_example4 Current limits scheme_example4

Permanent limit without any temporary limit

In the case of a group containing only a permanent limit (without any temporary above), there is no information available for the acceptable duration. The default acceptable duration has been chosen as infinite.

If you wish to have an acceptable duration of 0 instead, create a temporary limit with an acceptable duration of 0 and a value of Double.MAX_VALUE.

Phase tap changer

Javadoc

A phase tap changer can be added to either two-winding transformers or three-winding transformers’ legs.

Specifications

A phase tap changer is described by a set of tap positions (or steps) within which the transformer or transformer leg can operate. Additionally, to that set of steps, it is necessary to specify:

  • the lowest tap position

  • the highest tap position

  • the position index of the current tap (which has to be within the highest and lowest tap position bounds)

  • the solved position index of the tap that represents the index after a calculation

  • whether the phase tap changer can change tap positions onload or only offload

If the phase tap changer can change tap positions onload, regulation is specified as follows:

  • whether the tap changer is regulating or not

  • the regulation mode, which can be CURRENT_LIMITER, ACTIVE_POWER_CONTROL: the tap changer either regulates the current or the active power.

  • the regulation value (either a current value in A or an active power value in MW)

  • the regulating terminal, which can be local or remote: it is the specific connection point on the network where the setpoint is measured.

  • the target deadband, which defines a margin on the regulation so as to avoid an excessive update of controls

Each step of a phase tap changer has the following attributes:

Attribute

Unit

Description

\(r_{\phi, tap}\)

%

The resistance deviation in percent of nominal value

\(x_{\phi, tap}\)

%

The reactance deviation in percent of nominal value

\(g_{\phi, tap}\)

%

The conductance deviation in percent of nominal value

\(b_{\phi, tap}\)

%

The susceptance deviation in percent of nominal value

\(\rho_{\phi, tap}\)

p.u.

The voltage ratio in per unit of the rated voltages

\(\alpha_{\phi, tap}\)

\(^{\circ}\)

Angle difference

Example

This example shows how to add a phase tap changer to a two-winding transformer:

twoWindingsTransformer.newPhaseTapChanger()
    .setLowTapPosition(-1)
    .setTapPosition(0)
    .setLoadTapChangingCapabilities(true)
    .setRegulating(true)
    .setRegulationMode(PhaseTapChanger.RegulationMode.CURRENT_LIMITER)
    .setRegulationValue(25)
    .setRegulationTerminal(twoWindingsTransformer.getTerminal2())
    .beginStep()
        .setAlpha(-10)
        .setRho(0.99)
        .setR(1.)
        .setX(2.)
        .setG(0.5)
        .setB(0.5)
        .endStep()
    .beginStep()
        .setAlpha(0)
        .setRho(1)
        .setR(1.)
        .setX(2.)
        .setG(0.5)
        .setB(0.5)
        .endStep()
    .beginStep()
        .setAlpha(10)
        .setRho(1.01)
        .setR(1.)
        .setX(2.)
        .setG(0.5)
        .setB(0.5)
        .endStep()
    .add()

Ratio tap changer

Javadoc

A ratio tap changer can be added to either two-winding transformers or three-winding transformers’ legs.

Specifications

A ratio tap changer is described by a set of tap positions (or steps) within which the transformer or transformer leg can operate (or be operated offload). Additionally, to that set of steps, it is necessary to specify:

  • the lowest tap position

  • the highest tap position

  • the position index of the current tap (which has to be within the highest and lowest tap position bounds)

  • the solved position index of the tap that represents the index after a calculation

  • whether the ratio tap changer can change tap positions onload or only offload

If the ratio tap changer can change tap positions onload, regulation is specified as follows:

  • whether the tap changer is regulating or not

  • the regulation mode, which can be VOLTAGE or REACTIVE_POWER: the tap changer either regulates the voltage or the reactive power

  • the regulation value (either a voltage value in kV or a reactive power value in MVar)

  • the regulating terminal, which can be local or remote: it is the specific connection point on the network where the setpoint is measured.

  • the target deadband, which defines a margin on the regulation so as to avoid an excessive update of controls

Each step of a ratio tap changer has the following attributes:

Attribute

Unit

Description

\(r_{r, tap}\)

%

The resistance deviation in percent of nominal value

\(x_{r, tap}\)

%

The reactance deviation in percent of nominal value

\(g_{r, tap}\)

%

The conductance deviation in percent of nominal value

\(b_{r, tap}\)

%

The susceptance deviation in percent of nominal value

\(\rho_{r, tap}\)

p.u.

The voltage ratio in per unit of the rated voltages

Example

This example shows how to add a ratio tap changer to a two-winding transformer:

twoWindingsTransformer.newRatioTapChanger()
    .setLowTapPosition(-1)
    .setTapPosition(0)
    .setLoadTapChangingCapabilities(true)
    .setRegulating(true)
    .setRegulationMode(RatioTapChanger.RegulationMode.VOLTAGE)
    .setRegulationValue(25)
    .setRegulationTerminal(twoWindingsTransformer.getTerminal1())
    .beginStep()
        .setRho(0.95)
        .setR(1.)
        .setX(2.)
        .setG(0.5)
        .setB(0.5)
        .endStep()
    .beginStep()
        .setRho(1)
        .setR(1.)
        .setX(2.)
        .setG(0.5)
        .setB(0.5)
        .endStep()
    .beginStep()
        .setRho(1.05)
        .setR(1.)
        .setX(2.)
        .setG(0.5)
        .setB(0.5)
        .endStep()
    .add()