Skip to content

Commit 48605db

Browse files
Remove network results and violation detection on disabled branches on one side in fast DC Security Analysis (#1213)
Signed-off-by: p-arvy <pierre.arvy@artelys.com> Co-authored-by: Hadrien <hadrien.godard@artelys.com>
1 parent 3ef4bf9 commit 48605db

10 files changed

Lines changed: 294 additions & 35 deletions

docs/security/parameters.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ The `dcFastMode` property allows to use fast DC security analysis, based on Wood
5555
when DC mode is activated.
5656

5757
Please note that fast mode has a few limitations:
58-
- Contingencies applied on branches opened on one side are ignored.
58+
- Contingencies applied on branches opened on one side are ignored. Also, if a contingency causes the loss of one side of a branch,
59+
it is considered completely disabled, and no results are reported for this branch.
5960
- AC emulation of HVDC lines is disabled, as it is not yet supported.
6061
Instead, the [active power setpoint](../loadflow/loadflow.md#computing-hvdc-power-flow) mode is used to control the active power flow through these lines.
6162
- Only PST remedial actions are supported for now.

src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,12 @@ private static List<ConnectivityAnalysisResult> computeConnectivityData(LfNetwor
142142

143143
GraphConnectivity<LfBus, LfBranch> connectivity = lfNetwork.getConnectivity();
144144
for (PropagatedContingency contingency : potentiallyBreakingConnectivityContingencies) {
145-
List<ComputedContingencyElement> breakingConnectivityCandidates = contingency.getBranchIdsToOpen().keySet().stream().map(contingencyElementByBranch::get).collect(Collectors.toList());
145+
List<ComputedContingencyElement> breakingConnectivityCandidates = contingency.getBranchIdsToOpen().keySet().stream().sorted().map(contingencyElementByBranch::get).collect(Collectors.toList());
146146

147147
// we confirm the breaking of connectivity by network connectivity
148-
Set<ComputedContingencyElement> breakingConnectivityElements;
148+
// the traversal order of the set must be deterministic to ensure consistent element selection when multiple elements can restore connectivity
149+
// without this, fast DC post contingency states may vary for buses disconnected from main connected component, depending on which elements were selected
150+
LinkedHashSet<ComputedContingencyElement> breakingConnectivityElements;
149151
connectivity.startTemporaryChanges();
150152
try {
151153
ComputedContingencyElement.applyToConnectivity(lfNetwork, connectivity, breakingConnectivityCandidates);

src/main/java/com/powsybl/openloadflow/sa/AbstractNetworkResult.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.List;
2222
import java.util.Objects;
2323
import java.util.function.Consumer;
24+
import java.util.function.Predicate;
2425

2526
/**
2627
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
@@ -43,11 +44,11 @@ protected AbstractNetworkResult(LfNetwork network, StateMonitorIndex monitorInde
4344
this.createResultExtension = createResultExtension;
4445
}
4546

46-
protected void addResults(StateMonitor monitor, Consumer<LfBranch> branchConsumer) {
47+
protected void addResults(StateMonitor monitor, Consumer<LfBranch> branchConsumer, Predicate<LfBranch> isBranchDisabled) {
4748
Objects.requireNonNull(monitor);
4849
if (!monitor.getBranchIds().isEmpty()) {
4950
network.getBranches().stream()
50-
.filter(lfBranch -> !lfBranch.isDisabled())
51+
.filter(lfBranch -> !isBranchDisabled.test(lfBranch))
5152
.forEach(lfBranch -> {
5253
for (String originalId : lfBranch.getOriginalIds()) {
5354
if (monitor.getBranchIds().contains(originalId)) {

src/main/java/com/powsybl/openloadflow/sa/LimitViolationManager.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.powsybl.iidm.network.*;
1111
import com.powsybl.openloadflow.network.LfBranch;
1212
import com.powsybl.openloadflow.network.LfBus;
13+
import com.powsybl.openloadflow.network.LfElement;
1314
import com.powsybl.openloadflow.network.LfNetwork;
1415
import com.powsybl.openloadflow.util.Evaluable;
1516
import com.powsybl.openloadflow.util.PerUnit;
@@ -20,6 +21,7 @@
2021

2122
import java.util.*;
2223
import java.util.function.Function;
24+
import java.util.function.Predicate;
2325
import java.util.function.ToDoubleFunction;
2426

2527
/**
@@ -60,10 +62,19 @@ public List<LimitViolation> getLimitViolations() {
6062
* @param network network on which the violation limits are checked
6163
*/
6264
public void detectViolations(LfNetwork network) {
65+
detectViolations(network, LfElement::isDisabled);
66+
}
67+
68+
/**
69+
* Detect violations on branches and on buses
70+
* @param network network on which the violation limits are checked
71+
* @param isBranchDisabled predicate to evaluate if a branch of the network is disabled or not
72+
*/
73+
public void detectViolations(LfNetwork network, Predicate<LfBranch> isBranchDisabled) {
6374
Objects.requireNonNull(network);
6475

6576
// Detect violation limits on branches
66-
network.getBranches().stream().filter(b -> !b.isDisabled()).forEach(this::detectBranchViolations);
77+
network.getBranches().stream().filter(b -> !isBranchDisabled.test(b)).forEach(this::detectBranchViolations);
6778

6879
// Detect violation limits on buses
6980
network.getBuses().stream().filter(b -> !b.isDisabled()).forEach(this::detectBusViolations);

src/main/java/com/powsybl/openloadflow/sa/PostContingencyNetworkResult.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.powsybl.contingency.Contingency;
1111
import com.powsybl.contingency.ContingencyElement;
1212
import com.powsybl.contingency.ContingencyElementType;
13+
import com.powsybl.openloadflow.network.LfBranch;
1314
import com.powsybl.openloadflow.network.LfNetwork;
1415
import com.powsybl.security.monitor.StateMonitor;
1516
import com.powsybl.security.monitor.StateMonitorIndex;
@@ -18,6 +19,7 @@
1819
import java.util.ArrayList;
1920
import java.util.List;
2021
import java.util.Objects;
22+
import java.util.function.Predicate;
2123

2224
/**
2325
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
@@ -43,7 +45,7 @@ protected void clear() {
4345
branchResults.clear();
4446
}
4547

46-
public void addResults(StateMonitor monitor) {
48+
public void addResults(StateMonitor monitor, Predicate<LfBranch> isBranchDisabled) {
4749
addResults(monitor, branch -> {
4850
var preContingencyBranchResult = preContingencyMonitorInfos.getBranchResult(branch.getId());
4951
double preContingencyBranchP1 = preContingencyBranchResult != null ? preContingencyBranchResult.getP1() : Double.NaN;
@@ -61,17 +63,21 @@ public void addResults(StateMonitor monitor) {
6163
}
6264
}
6365
branchResults.addAll(branch.createBranchResult(preContingencyBranchP1, preContingencyBranchOfContingencyP1, createResultExtension));
64-
});
66+
}, isBranchDisabled);
6567
}
6668

6769
@Override
6870
public void update() {
71+
update(LfBranch::isDisabled);
72+
}
73+
74+
public void update(Predicate<LfBranch> isBranchDisabled) {
6975
clear();
7076
StateMonitor stateMonitor = monitorIndex.getSpecificStateMonitors().get(contingency.getId());
7177
if (stateMonitor != null) {
72-
addResults(stateMonitor);
78+
addResults(stateMonitor, isBranchDisabled);
7379
} else {
74-
addResults(monitorIndex.getAllStateMonitor());
80+
addResults(monitorIndex.getAllStateMonitor(), isBranchDisabled);
7581
}
7682
}
7783

src/main/java/com/powsybl/openloadflow/sa/PreContingencyNetworkResult.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@
77
*/
88
package com.powsybl.openloadflow.sa;
99

10+
import com.powsybl.openloadflow.network.LfBranch;
1011
import com.powsybl.openloadflow.network.LfNetwork;
1112
import com.powsybl.security.monitor.StateMonitor;
1213
import com.powsybl.security.monitor.StateMonitorIndex;
1314
import com.powsybl.security.results.BranchResult;
1415

1516
import java.util.*;
17+
import java.util.function.Predicate;
1618

1719
/**
1820
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
@@ -31,18 +33,22 @@ protected void clear() {
3133
branchResults.clear();
3234
}
3335

34-
private void addResults(StateMonitor monitor) {
36+
private void addResults(StateMonitor monitor, Predicate<LfBranch> isBranchDisabled) {
3537
addResults(monitor, branch -> {
3638
branch.createBranchResult(Double.NaN, Double.NaN, createResultExtension)
3739
.forEach(branchResult -> branchResults.put(branchResult.getBranchId(), branchResult));
38-
});
40+
}, isBranchDisabled);
3941
}
4042

4143
@Override
4244
public void update() {
45+
update(LfBranch::isDisabled);
46+
}
47+
48+
public void update(Predicate<LfBranch> isBranchDisabled) {
4349
clear();
44-
addResults(monitorIndex.getNoneStateMonitor());
45-
addResults(monitorIndex.getAllStateMonitor());
50+
addResults(monitorIndex.getNoneStateMonitor(), isBranchDisabled);
51+
addResults(monitorIndex.getAllStateMonitor(), isBranchDisabled);
4652
}
4753

4854
public BranchResult getBranchResult(String branchId) {

src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545

4646
import java.util.*;
4747
import java.util.function.Function;
48+
import java.util.function.Predicate;
4849
import java.util.function.Supplier;
4950
import java.util.stream.Collectors;
5051

@@ -206,7 +207,8 @@ private void filterActions(List<Action> actions) {
206207
private PostContingencyResult computePostContingencyResultFromPostContingencyStates(DcLoadFlowContext loadFlowContext, Contingency contingency, LfContingency lfContingency,
207208
LimitViolationManager preContingencyLimitViolationManager, PreContingencyNetworkResult preContingencyNetworkResult,
208209
boolean createResultExtension, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters,
209-
double[] postContingencyStates, List<LimitReduction> limitReductions) {
210+
double[] postContingencyStates, Predicate<LfBranch> isBranchDisabledDueToContingency,
211+
List<LimitReduction> limitReductions) {
210212

211213
// update network state with post contingency states
212214
LfNetwork lfNetwork = loadFlowContext.getNetwork();
@@ -217,11 +219,11 @@ private PostContingencyResult computePostContingencyResultFromPostContingencySta
217219

218220
// update post contingency network result
219221
var postContingencyNetworkResult = new PostContingencyNetworkResult(lfNetwork, monitorIndex, createResultExtension, preContingencyNetworkResult, contingency);
220-
postContingencyNetworkResult.update();
222+
postContingencyNetworkResult.update(isBranchDisabledDueToContingency);
221223

222224
// detect violations
223225
var postContingencyLimitViolationManager = new LimitViolationManager(preContingencyLimitViolationManager, limitReductions, violationsParameters);
224-
postContingencyLimitViolationManager.detectViolations(lfNetwork);
226+
postContingencyLimitViolationManager.detectViolations(lfNetwork, isBranchDisabledDueToContingency);
225227

226228
// connectivity result due to the application of the lf contingency
227229
var connectivityResult = new ConnectivityResult(
@@ -244,15 +246,16 @@ private PostContingencyResult computePostContingencyResultFromPostContingencySta
244246
*/
245247
private PostContingencyResult processPostContingencyResult(DcLoadFlowContext context, PropagatedContingency contingency, LfContingency lfContingency, Supplier<double[]> postContingencyStatesSupplier,
246248
LimitViolationManager preContingencyLimitViolationManager, PreContingencyNetworkResult preContingencyNetworkResult,
247-
boolean createResultExtension, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters,
249+
Predicate<LfBranch> isBranchDisabledDueToContingency, boolean createResultExtension,
250+
SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters,
248251
List<LimitReduction> limitReductions) {
249252
logPostContingencyStart(context.getNetwork(), lfContingency);
250253
Stopwatch stopwatch = Stopwatch.createStarted();
251254

252255
double[] postContingencyStates = postContingencyStatesSupplier.get();
253256
PostContingencyResult postContingencyResult = computePostContingencyResultFromPostContingencyStates(context, contingency.getContingency(),
254257
lfContingency, preContingencyLimitViolationManager, preContingencyNetworkResult, createResultExtension,
255-
violationsParameters, postContingencyStates, limitReductions);
258+
violationsParameters, postContingencyStates, isBranchDisabledDueToContingency, limitReductions);
256259

257260
stopwatch.stop();
258261
logPostContingencyEnd(context.getNetwork(), lfContingency, stopwatch);
@@ -266,7 +269,7 @@ private PostContingencyResult processPostContingencyResult(DcLoadFlowContext con
266269
private OperatorStrategyResult computeOperatorStrategyResultFromPostContingencyAndOperatorStrategyStates(DcLoadFlowContext loadFlowContext, LfContingency lfContingency, OperatorStrategy operatorStrategy,
267270
List<LfAction> operatorStrategyLfActions, LimitViolationManager preContingencyLimitViolationManager,
268271
boolean createResultExtension, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters,
269-
double[] postContingencyAndOperatorStrategyStates, List<LimitReduction> limitReductions) {
272+
double[] postContingencyAndOperatorStrategyStates, Predicate<LfBranch> isBranchDisabledDueToContingency, List<LimitReduction> limitReductions) {
270273
// update network state with post contingency and post operator strategy states
271274
LfNetwork lfNetwork = loadFlowContext.getNetwork();
272275
loadFlowContext.getEquationSystem().getStateVector().set(postContingencyAndOperatorStrategyStates);
@@ -278,11 +281,11 @@ private OperatorStrategyResult computeOperatorStrategyResultFromPostContingencyA
278281

279282
// update network result
280283
var postActionsNetworkResult = new PreContingencyNetworkResult(lfNetwork, monitorIndex, createResultExtension);
281-
postActionsNetworkResult.update();
284+
postActionsNetworkResult.update(isBranchDisabledDueToContingency);
282285

283286
// detect violations
284287
var postActionsViolationManager = new LimitViolationManager(preContingencyLimitViolationManager, limitReductions, violationsParameters);
285-
postActionsViolationManager.detectViolations(lfNetwork);
288+
postActionsViolationManager.detectViolations(lfNetwork, isBranchDisabledDueToContingency);
286289

287290
return new OperatorStrategyResult(operatorStrategy, PostContingencyComputationStatus.CONVERGED,
288291
new LimitViolationsResult(postActionsViolationManager.getLimitViolations()),
@@ -297,8 +300,8 @@ private OperatorStrategyResult computeOperatorStrategyResultFromPostContingencyA
297300
private OperatorStrategyResult processOperatorStrategyResult(DcLoadFlowContext context, LfContingency contingency, OperatorStrategy operatorStrategy,
298301
Function<List<LfAction>, double[]> postContingencyAndOperatorStrategyStatesSupplier,
299302
LimitViolationManager preContingencyLimitViolationManager, PostContingencyResult postContingencyResult,
300-
Map<String, LfAction> lfActionById, boolean createResultExtension, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters,
301-
List<LimitReduction> limitReductions) {
303+
Map<String, LfAction> lfActionById, Predicate<LfBranch> isBranchDisabledDueToContingency, boolean createResultExtension,
304+
SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, List<LimitReduction> limitReductions) {
302305
// get the actions associated to the operator strategy
303306
List<String> actionIds = checkCondition(operatorStrategy, postContingencyResult.getLimitViolationsResult());
304307
List<LfAction> operatorStrategyLfActions = actionIds.stream()
@@ -311,7 +314,7 @@ private OperatorStrategyResult processOperatorStrategyResult(DcLoadFlowContext c
311314

312315
double[] postContingencyAndOperatorStrategyStates = postContingencyAndOperatorStrategyStatesSupplier.apply(operatorStrategyLfActions);
313316
OperatorStrategyResult operatorStrategyResult = computeOperatorStrategyResultFromPostContingencyAndOperatorStrategyStates(context, contingency, operatorStrategy, operatorStrategyLfActions,
314-
preContingencyLimitViolationManager, createResultExtension, violationsParameters, postContingencyAndOperatorStrategyStates, limitReductions);
317+
preContingencyLimitViolationManager, createResultExtension, violationsParameters, postContingencyAndOperatorStrategyStates, isBranchDisabledDueToContingency, limitReductions);
315318

316319
stopwatch.stop();
317320
logActionEnd(context.getNetwork(), operatorStrategy, stopwatch);
@@ -333,9 +336,13 @@ private void addPostContingencyAndOperatorStrategyResults(DcLoadFlowContext cont
333336
ReportNode postContSimReportNode = Reports.createPostContingencySimulation(lfNetwork.getReportNode(), contingency.getContingency().getId());
334337
lfNetwork.setReportNode(postContSimReportNode);
335338

339+
// predicate to determine if a branch is disabled or not due to the contingency
340+
// note that branches with one side opened due to the contingency are considered are disabled
341+
Predicate<LfBranch> isBranchDisabled = branch -> lfContingency.getDisabledNetwork().getBranchesStatus().containsKey(branch);
342+
336343
// process post contingency result with supplier giving post contingency states
337344
PostContingencyResult postContingencyResult = processPostContingencyResult(context, contingency, lfContingency, toPostContingencyStates, preContingencyLimitViolationManager,
338-
preContingencyNetworkResult, createResultExtension, violationsParameters, limitReductions);
345+
preContingencyNetworkResult, isBranchDisabled, createResultExtension, violationsParameters, limitReductions);
339346
postContingencyResults.add(postContingencyResult);
340347

341348
// restore pre contingency states for next calculation
@@ -349,7 +356,7 @@ private void addPostContingencyAndOperatorStrategyResults(DcLoadFlowContext cont
349356

350357
// process operator strategy result with supplier giving post contingency and post operator strategy states
351358
OperatorStrategyResult operatorStrategyResult = processOperatorStrategyResult(context, lfContingency, operatorStrategy, toPostContingencyAndOperatorStrategyStates, preContingencyLimitViolationManager,
352-
postContingencyResult, lfActionById, createResultExtension, violationsParameters, limitReductions);
359+
postContingencyResult, lfActionById, isBranchDisabled, createResultExtension, violationsParameters, limitReductions);
353360
operatorStrategyResults.add(operatorStrategyResult);
354361

355362
// restore pre contingency states for next calculation

0 commit comments

Comments
 (0)