Skip to content

Commit 69a852c

Browse files
Add parameter to define min nominal voltage for unrealistic state check (#1217)
Signed-off-by: Didier Vidal <didier.vidal_externe@rte-france.com> Co-authored-by: jeandemanged <damien.jeandemange@artelys.com>
1 parent 7e8432b commit 69a852c

File tree

7 files changed

+78
-17
lines changed

7 files changed

+78
-17
lines changed

docs/loadflow/parameters.md

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -320,8 +320,9 @@ The default values are `0.8` and `1.2` and they must be greater or equal to `0`.
320320
**minRealisticVoltage** and **maxRealisticVoltage**
321321
These parameters are used to identify if the AC Solver has converged to an unrealistic state.
322322

323-
For any component where a bus voltage is solved outside these per-unit
324-
thresholds, the component solution is deemed unrealistic and its solution status is flagged as failed.
323+
If there is any bus in a voltage level, in pu, higher than 'minNominalVoltageRealisticVoltageCheck', with
324+
a computed voltage outside these per-unit thresholds, the component solution is deemed unrealistic and
325+
its solution status is flagged as failed.
325326

326327
If `voltageRemoteControlRobustMode` is set to true, the check of unrealistic voltage is done after the
327328
ReactiveLimits outerloop has been used. In addition, the ReactiveLimits outerloop uses these values as a
@@ -330,6 +331,21 @@ their reactive diagram.
330331

331332
The default values are `0.5` and `2.0` and they must be greater or equal to `0`.
332333

334+
**minNominalVoltageRealisticVoltageCheck**
335+
This parameter defines the minimal nominal voltage, in kV, for which a bus oustide of **minRealisticVoltage**
336+
and **maxRealisticVoltage** will stop the simulation.
337+
338+
Unrealistic voltages -particularly in high-voltage substations- can trigger automated protections or other
339+
hazardous phenomena, potentially causing significant impacts to the system. Steady-state simulation may not
340+
accurately account for these effects. Therefore, results obtained under such conditions should be interpreted
341+
with caution.
342+
343+
A configuration that offers both reliable simulation results and resilience to local observability issues could,
344+
for example, use 0.8 and 1.2 p.u. for **minRealisticVoltage** and **maxRealisticVoltage**, respectively,
345+
and 100 kV for **minNominalVoltageRealisticVoltageCheck**.
346+
347+
The default value is 0 kV.
348+
333349
**reactiveRangeCheckMode**
334350
Open Load Flow discards voltage control for generators with a too small reactive power range, because in practice a too
335351
small reactive power ranger means limited to zero voltage control capability.
@@ -396,9 +412,11 @@ Allows to ignore active power limits during calculations. Active power limits ar
396412
Disables voltage control for generators with `targetP` outside the interval [`minP`, `maxP`]. The default value is `false`.
397413

398414
**minNominalVoltageTargetVoltageCheck**
399-
This parameter defines the minimal nominal voltage to check the target of voltage control in per-unit.
400-
The default value is `20 kV`, meaning that under the controlled buses of voltage levels under this value are ignored from the check.
401-
It must be greater or equal to `0 kV`.
415+
This parameter defines the minimal nominal voltage, in kV, for which the plausible voltage target checks are applied.
416+
417+
Above this voltage level, voltage targets that are, in pu, outside 'minPlausibleTargetVoltage' - 'maxPlausibleTargetVoltage' are ignored.
418+
419+
The default value is `20 kV`. It must be greater or equal to `0 kV`.
402420

403421
**reactivePowerDispatchMode**
404422
This parameter defines how reactive power is split among generators with controls (voltage or reactive power).

src/main/java/com/powsybl/openloadflow/OpenLoadFlowParameters.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ public enum FictitiousGeneratorVoltageControlCheckMode {
206206

207207
public static final String MAX_REALISTIC_VOLTAGE_PARAM_NAME = "maxRealisticVoltage";
208208

209+
public static final String MIN_NOMINAL_VOLTAGE_REALISTIC_VOLTAGE_CHECK_PARAM_NAME = "minNominalVoltageRealisticVoltageCheck";
210+
209211
public static final String MIN_NOMINAL_VOLTAGE_TARGET_VOLTAGE_CHECK_PARAM_NAME = "minNominalVoltageTargetVoltageCheck";
210212

211213
public static final String REACTIVE_RANGE_CHECK_MODE_PARAM_NAME = "reactiveRangeCheckMode";
@@ -390,6 +392,7 @@ public static List<Object> getAcSolverTypePossibleValues() {
390392
new Parameter(MAX_PLAUSIBLE_TARGET_VOLTAGE_PARAM_NAME, ParameterType.DOUBLE, "Max plausible target voltage", LfNetworkParameters.MAX_PLAUSIBLE_TARGET_VOLTAGE_DEFAULT_VALUE, ParameterScope.FUNCTIONAL, VOLTAGE_CONTROLS_CATEGORY_KEY),
391393
new Parameter(MIN_REALISTIC_VOLTAGE_PARAM_NAME, ParameterType.DOUBLE, "Min realistic voltage", AcLoadFlowParameters.DEFAULT_MIN_REALISTIC_VOLTAGE, ParameterScope.FUNCTIONAL, VOLTAGE_CONTROLS_CATEGORY_KEY),
392394
new Parameter(MAX_REALISTIC_VOLTAGE_PARAM_NAME, ParameterType.DOUBLE, "Max realistic voltage", AcLoadFlowParameters.DEFAULT_MAX_REALISTIC_VOLTAGE, ParameterScope.FUNCTIONAL, VOLTAGE_CONTROLS_CATEGORY_KEY),
395+
new Parameter(MIN_NOMINAL_VOLTAGE_REALISTIC_VOLTAGE_CHECK_PARAM_NAME, ParameterType.DOUBLE, "Min nominal voltage realistic voltage check", AcLoadFlowParameters.DEFAULT_MIN_NOMINAL_VOLTAGE_REALISTIC_VOLTAGE_CHECK, ParameterScope.FUNCTIONAL, VOLTAGE_CONTROLS_CATEGORY_KEY),
393396
new Parameter(REACTIVE_RANGE_CHECK_MODE_PARAM_NAME, ParameterType.STRING, "Reactive range check mode", LfNetworkParameters.REACTIVE_RANGE_CHECK_MODE_DEFAULT_VALUE.name(), getEnumPossibleValues(ReactiveRangeCheckMode.class), ParameterScope.FUNCTIONAL, GENERATOR_VOLTAGE_CONTROL_CATEGORY_KEY),
394397
new Parameter(LOW_IMPEDANCE_THRESHOLD_PARAM_NAME, ParameterType.DOUBLE, "Low impedance threshold in per unit", LfNetworkParameters.LOW_IMPEDANCE_THRESHOLD_DEFAULT_VALUE, ParameterScope.FUNCTIONAL, MODEL_CATEGORY_KEY),
395398
new Parameter(NETWORK_CACHE_ENABLED_PARAM_NAME, ParameterType.BOOLEAN, "Network cache enabled", LfNetworkParameters.CACHE_ENABLED_DEFAULT_VALUE, ParameterScope.FUNCTIONAL, FAST_RESTART_CATEGORY_KEY),
@@ -539,6 +542,8 @@ public enum LowImpedanceBranchMode {
539542

540543
private double maxRealisticVoltage = AcLoadFlowParameters.DEFAULT_MAX_REALISTIC_VOLTAGE;
541544

545+
private double minNominalVoltageRealisticVoltageCheck = AcLoadFlowParameters.DEFAULT_MIN_NOMINAL_VOLTAGE_REALISTIC_VOLTAGE_CHECK;
546+
542547
private double lowImpedanceThreshold = LfNetworkParameters.LOW_IMPEDANCE_THRESHOLD_DEFAULT_VALUE;
543548

544549
public enum ReactiveRangeCheckMode {
@@ -962,6 +967,15 @@ public OpenLoadFlowParameters setMaxRealisticVoltage(double maxRealisticVoltage)
962967
return this;
963968
}
964969

970+
public double getMinNominalVoltageRealisticVoltageCheck() {
971+
return minNominalVoltageRealisticVoltageCheck;
972+
}
973+
974+
public OpenLoadFlowParameters setMinNominalVoltageRealisticVoltageCheck(double minNominalVoltageRealisticVoltageCheck) {
975+
this.minNominalVoltageRealisticVoltageCheck = minNominalVoltageRealisticVoltageCheck;
976+
return this;
977+
}
978+
965979
public ReactiveRangeCheckMode getReactiveRangeCheckMode() {
966980
return reactiveRangeCheckMode;
967981
}
@@ -1455,6 +1469,7 @@ public OpenLoadFlowParameters update(PlatformConfig platformConfig) {
14551469
config.getOptionalDoubleProperty(MAX_PLAUSIBLE_TARGET_VOLTAGE_PARAM_NAME).ifPresent(this::setMaxPlausibleTargetVoltage);
14561470
config.getOptionalDoubleProperty(MIN_REALISTIC_VOLTAGE_PARAM_NAME).ifPresent(this::setMinRealisticVoltage);
14571471
config.getOptionalDoubleProperty(MAX_REALISTIC_VOLTAGE_PARAM_NAME).ifPresent(this::setMaxRealisticVoltage);
1472+
config.getOptionalDoubleProperty(MIN_NOMINAL_VOLTAGE_REALISTIC_VOLTAGE_CHECK_PARAM_NAME).ifPresent(this::setMinNominalVoltageRealisticVoltageCheck);
14581473
config.getOptionalEnumProperty(REACTIVE_RANGE_CHECK_MODE_PARAM_NAME, ReactiveRangeCheckMode.class)
14591474
.ifPresent(this::setReactiveRangeCheckMode);
14601475
config.getOptionalDoubleProperty(LOW_IMPEDANCE_THRESHOLD_PARAM_NAME).ifPresent(this::setLowImpedanceThreshold);
@@ -1580,6 +1595,8 @@ public OpenLoadFlowParameters update(Map<String, String> properties) {
15801595
.ifPresent(prop -> this.setMinRealisticVoltage(Double.parseDouble(prop)));
15811596
Optional.ofNullable(properties.get(MAX_REALISTIC_VOLTAGE_PARAM_NAME))
15821597
.ifPresent(prop -> this.setMaxRealisticVoltage(Double.parseDouble(prop)));
1598+
Optional.ofNullable(properties.get(MIN_NOMINAL_VOLTAGE_REALISTIC_VOLTAGE_CHECK_PARAM_NAME))
1599+
.ifPresent(prop -> this.setMinNominalVoltageRealisticVoltageCheck(Double.parseDouble(prop)));
15831600
Optional.ofNullable(properties.get(REACTIVE_RANGE_CHECK_MODE_PARAM_NAME))
15841601
.ifPresent(prop -> this.setReactiveRangeCheckMode(ReactiveRangeCheckMode.valueOf(prop)));
15851602
Optional.ofNullable(properties.get(LOW_IMPEDANCE_THRESHOLD_PARAM_NAME))
@@ -1710,6 +1727,7 @@ public Map<String, Object> toMap() {
17101727
map.put(MAX_PLAUSIBLE_TARGET_VOLTAGE_PARAM_NAME, maxPlausibleTargetVoltage);
17111728
map.put(MIN_REALISTIC_VOLTAGE_PARAM_NAME, minRealisticVoltage);
17121729
map.put(MAX_REALISTIC_VOLTAGE_PARAM_NAME, maxRealisticVoltage);
1730+
map.put(MIN_NOMINAL_VOLTAGE_REALISTIC_VOLTAGE_CHECK_PARAM_NAME, minNominalVoltageRealisticVoltageCheck);
17131731
map.put(REACTIVE_RANGE_CHECK_MODE_PARAM_NAME, reactiveRangeCheckMode);
17141732
map.put(LOW_IMPEDANCE_THRESHOLD_PARAM_NAME, lowImpedanceThreshold);
17151733
map.put(NETWORK_CACHE_ENABLED_PARAM_NAME, networkCacheEnabled);
@@ -1977,7 +1995,8 @@ public static AcLoadFlowParameters createAcParameters(LoadFlowParameters paramet
19771995
.setSolverFactory(solverFactory, parameters)
19781996
.setVoltageRemoteControlRobustMode(parametersExt.isVoltageRemoteControlRobustMode())
19791997
.setMinRealisticVoltage(parametersExt.minRealisticVoltage)
1980-
.setMaxRealisticVoltage(parametersExt.maxRealisticVoltage);
1998+
.setMaxRealisticVoltage(parametersExt.maxRealisticVoltage)
1999+
.setMinNominalVoltageRealisticVoltageCheck(parametersExt.getMinNominalVoltageRealisticVoltageCheck());
19812000
}
19822001

19832002
public static DcLoadFlowParameters createDcParameters(Network network, LoadFlowParameters parameters, OpenLoadFlowParameters parametersExt,
@@ -2158,6 +2177,7 @@ public static boolean equals(LoadFlowParameters parameters1, LoadFlowParameters
21582177
extension1.isVoltageRemoteControlRobustMode() == extension2.isVoltageRemoteControlRobustMode() &&
21592178
extension1.isForceTargetQInReactiveLimits() == extension2.isForceTargetQInReactiveLimits() &&
21602179
extension1.isDisableInconsistentVoltageControls() == extension2.isDisableInconsistentVoltageControls() &&
2180+
extension1.getMinNominalVoltageRealisticVoltageCheck() == extension2.getMinNominalVoltageRealisticVoltageCheck() &&
21612181
extension1.isExtrapolateReactiveLimits() == extension2.isExtrapolateReactiveLimits();
21622182
}
21632183

@@ -2205,6 +2225,7 @@ public static LoadFlowParameters clone(LoadFlowParameters parameters) {
22052225
.setMaxPlausibleTargetVoltage(extension.getMaxPlausibleTargetVoltage())
22062226
.setMinRealisticVoltage(extension.getMinRealisticVoltage())
22072227
.setMaxRealisticVoltage(extension.getMaxRealisticVoltage())
2228+
.setMinNominalVoltageRealisticVoltageCheck(extension.getMinNominalVoltageRealisticVoltageCheck())
22082229
.setReactiveRangeCheckMode(extension.getReactiveRangeCheckMode())
22092230
.setLowImpedanceThreshold(extension.getLowImpedanceThreshold())
22102231
.setNetworkCacheEnabled(extension.isNetworkCacheEnabled())

src/main/java/com/powsybl/openloadflow/ac/AcLoadFlowParameters.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public class AcLoadFlowParameters extends AbstractLoadFlowParameters<AcLoadFlowP
3030

3131
public static final double DEFAULT_MIN_REALISTIC_VOLTAGE = 0.5;
3232
public static final double DEFAULT_MAX_REALISTIC_VOLTAGE = 2;
33+
public static final double DEFAULT_MIN_NOMINAL_VOLTAGE_REALISTIC_VOLTAGE_CHECK = 0;
3334

3435
private AcEquationSystemCreationParameters equationSystemCreationParameters = new AcEquationSystemCreationParameters();
3536

@@ -53,6 +54,8 @@ public class AcLoadFlowParameters extends AbstractLoadFlowParameters<AcLoadFlowP
5354

5455
private double maxRealisticVoltage = DEFAULT_MAX_REALISTIC_VOLTAGE;
5556

57+
private double minNominalVoltageRealisticVoltageCheck = DEFAULT_MIN_NOMINAL_VOLTAGE_REALISTIC_VOLTAGE_CHECK;
58+
5659
public AcEquationSystemCreationParameters getEquationSystemCreationParameters() {
5760
return equationSystemCreationParameters;
5861
}
@@ -148,6 +151,15 @@ public AcLoadFlowParameters setMaxRealisticVoltage(double maxRealisticVoltage) {
148151
return this;
149152
}
150153

154+
public double getMinNominalVoltageRealisticVoltageCheck() {
155+
return minNominalVoltageRealisticVoltageCheck;
156+
}
157+
158+
public AcLoadFlowParameters setMinNominalVoltageRealisticVoltageCheck(double minNominalVoltageRealisticVoltageCheck) {
159+
this.minNominalVoltageRealisticVoltageCheck = minNominalVoltageRealisticVoltageCheck;
160+
return this;
161+
}
162+
151163
@Override
152164
public String toString() {
153165
return "AcLoadFlowParameters(" +
@@ -165,6 +177,7 @@ public String toString() {
165177
", voltageRemoteControlRobustMode=" + voltageRemoteControlRobustMode +
166178
", minRealisticVoltage=" + minRealisticVoltage +
167179
", maxRealisticVoltage=" + maxRealisticVoltage +
180+
", minNominalVoltageRealisticVoltageCheck=" + minNominalVoltageRealisticVoltageCheck +
168181
')';
169182
}
170183
}

src/main/java/com/powsybl/openloadflow/ac/AcloadFlowEngine.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ private void runOuterLoop(AcOuterLoop outerLoop, AcOuterLoopContext outerLoopCon
9696
}
9797

9898
// if not yet stable, restart solver
99-
runningContext.lastSolverResult = runAcSolverAndCheckRealisticState(solver, new PreviousValueVoltageInitializer(), reportNode, checkUnrealistic);
99+
runningContext.lastSolverResult = runAcSolverAndCheckRealisticState(solver, new PreviousValueVoltageInitializer(), reportNode, checkUnrealistic,
100+
outerLoopContext.getLoadFlowContext().getParameters());
100101

101102
runningContext.nrTotalIterations.add(runningContext.lastSolverResult.getIterations());
102103
runningContext.outerLoopTotalIterations++;
@@ -108,8 +109,11 @@ private void runOuterLoop(AcOuterLoop outerLoop, AcOuterLoopContext outerLoopCon
108109
&& runningContext.outerLoopTotalIterations < context.getParameters().getMaxOuterLoopIterations());
109110

110111
if (!checkUnrealistic && runningContext.lastUnrealisticStateFixingLoop == outerLoop && runningContext.lastSolverResult.getStatus() == AcSolverStatus.CONVERGED) {
112+
111113
// This is time to check the unrealistic state and create a report if needed
112-
boolean isStateUnrealistic = isStateUnrealistic(context.getNetwork().getReportNode());
114+
boolean isStateUnrealistic = isStateUnrealistic(context.getNetwork().getReportNode(),
115+
outerLoopContext.getLoadFlowContext().getParameters().getMinNominalVoltageRealisticVoltageCheck());
116+
113117
if (isStateUnrealistic) {
114118
runningContext.lastSolverResult = new AcSolverResult(AcSolverStatus.UNREALISTIC_STATE,
115119
runningContext.lastSolverResult.getIterations(),
@@ -122,7 +126,8 @@ private void runOuterLoop(AcOuterLoop outerLoop, AcOuterLoopContext outerLoopCon
122126
}
123127
}
124128

125-
private boolean isStateUnrealistic(ReportNode reportNode) {
129+
private boolean isStateUnrealistic(ReportNode reportNode, double minNominalVoltageRealisticVoltageCheck) {
130+
126131
EquationSystem<AcVariableType, AcEquationType> equationSystem = context.getEquationSystem();
127132
AcLoadFlowParameters parameters = context.getParameters();
128133
LfNetwork network = context.getNetwork();
@@ -131,7 +136,10 @@ private boolean isStateUnrealistic(ReportNode reportNode) {
131136
if (v.getType() == AcVariableType.BUS_V && !network.getBus(v.getElementNum()).isFictitious()) {
132137
double value = equationSystem.getStateVector().get(v.getRow());
133138
if (value < parameters.getMinRealisticVoltage() || value > parameters.getMaxRealisticVoltage()) {
134-
busesOutOfNormalVoltageRange.put(network.getBus(v.getElementNum()).getId(), value);
139+
// only consider unrealistic if nominal voltage high enough
140+
if (network.getBus(v.getElementNum()).getNominalV() >= minNominalVoltageRealisticVoltageCheck) {
141+
busesOutOfNormalVoltageRange.put(network.getBus(v.getElementNum()).getId(), value);
142+
}
135143
}
136144
}
137145
}
@@ -150,10 +158,10 @@ private boolean isStateUnrealistic(ReportNode reportNode) {
150158
}
151159

152160
private AcSolverResult runAcSolverAndCheckRealisticState(AcSolver solver, VoltageInitializer voltageInitializer,
153-
ReportNode reportNode, boolean checkUnrealistic) {
161+
ReportNode reportNode, boolean checkUnrealistic, AcLoadFlowParameters parameters) {
154162
AcSolverResult result = solver.run(voltageInitializer, reportNode);
155163

156-
if (checkUnrealistic && result.getStatus() == AcSolverStatus.CONVERGED && isStateUnrealistic(reportNode)) {
164+
if (checkUnrealistic && result.getStatus() == AcSolverStatus.CONVERGED && isStateUnrealistic(reportNode, parameters.getMinNominalVoltageRealisticVoltageCheck())) {
157165
result = new AcSolverResult(AcSolverStatus.UNREALISTIC_STATE, result.getIterations(), result.getSlackBusActivePowerMismatch());
158166
}
159167

@@ -230,7 +238,7 @@ public AcLoadFlowResult run() {
230238
boolean checkUnrealisticStates = runningContext.lastUnrealisticStateFixingLoop == null;
231239

232240
// initial solver run
233-
runningContext.lastSolverResult = runAcSolverAndCheckRealisticState(solver, voltageInitializer, reportNode, checkUnrealisticStates);
241+
runningContext.lastSolverResult = runAcSolverAndCheckRealisticState(solver, voltageInitializer, reportNode, checkUnrealisticStates, context.getParameters());
234242

235243
runningContext.nrTotalIterations.add(runningContext.lastSolverResult.getIterations());
236244

0 commit comments

Comments
 (0)