Skip to content

Commit 6f892b0

Browse files
authored
Security Analysis: add distributedActivePower to results (#1351)
Signed-off-by: Damien Jeandemange <damien.jeandemange@artelys.com>
1 parent 43d4947 commit 6f892b0

8 files changed

Lines changed: 104 additions & 24 deletions

File tree

docs/advanced_programming/contingency_active_power_loss.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ To add another plugin, you will need to code (in Java) an implementation of the
1414
interface and make this implementation available to the Java ServiceLoader (e.g. using Google's AutoService):
1515
- the `getName()` method should provide the plugin name - which can then be used in the `contingencyActivePowerLossDistribution` security analysis parameter
1616
- the `run(...)` method will be called by the security analysis engine for each contingency and should provide the logic.
17-
This method has access to:
17+
This method must return the amount of distributed active power (in per-unit) and has access to:
1818
- the network
1919
- the contingency in open-loadflow representation, including among others information about disconnected network elements, and how much active power has been lost.
2020
- the contingency definition

src/main/java/com/powsybl/openloadflow/lf/AbstractLoadFlowResult.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ public OuterLoopResult getOuterLoopResult() {
5050
return outerLoopResult;
5151
}
5252

53+
@Override
5354
public double getDistributedActivePower() {
5455
return distributedActivePower;
5556
}

src/main/java/com/powsybl/openloadflow/lf/LoadFlowResult.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,6 @@ record Status(com.powsybl.loadflow.LoadFlowResult.ComponentResult.Status status,
2424
double getSlackBusActivePowerMismatch();
2525

2626
Status toComponentResultStatus();
27+
28+
double getDistributedActivePower();
2729
}

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

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -227,9 +227,10 @@ SecurityAnalysisResult runSimulationsOnAllComponents(LfNetworkList networks, Lis
227227
}
228228

229229
// run simulation on first lfNetwork to initialize results structures
230-
LfNetwork firstNetwork = networkToSimulate.remove(0);
230+
LfNetwork firstNetwork = networkToSimulate.removeFirst();
231231
SecurityAnalysisResult result = runSimulations(firstNetwork, propagatedContingencies, parameters, securityAnalysisParameters,
232232
operatorStrategies, actions, limitReductions, contingencyActivePowerLossDistribution);
233+
double preContingencyDistributedActivePower = result.getPreContingencyResult().getDistributedActivePower();
233234

234235
List<PostContingencyResult> postContingencyResults = result.getPostContingencyResults();
235236
List<OperatorStrategyResult> operatorStrategyResults = result.getOperatorStrategyResults();
@@ -249,6 +250,7 @@ SecurityAnalysisResult runSimulationsOnAllComponents(LfNetworkList networks, Lis
249250
operatorStrategies, actions, limitReductions, contingencyActivePowerLossDistribution);
250251

251252
// Merge into first result
253+
preContingencyDistributedActivePower += resultOtherComponent.getPreContingencyResult().getDistributedActivePower();
252254
// PreContingency results first
253255
preContingencyViolations.addAll(resultOtherComponent.getPreContingencyResult().getLimitViolationsResult().getLimitViolations());
254256
mergedPreContingencyNetworkResult = mergeNetworkResult(mergedPreContingencyNetworkResult, resultOtherComponent.getPreContingencyResult().getNetworkResult());
@@ -262,7 +264,7 @@ SecurityAnalysisResult runSimulationsOnAllComponents(LfNetworkList networks, Lis
262264
PreContingencyResult mergedPrecontingencyResult =
263265
new PreContingencyResult(result.getPreContingencyResult().getStatus(),
264266
new LimitViolationsResult(preContingencyViolations),
265-
mergedPreContingencyNetworkResult, Double.NaN);
267+
mergedPreContingencyNetworkResult, preContingencyDistributedActivePower);
266268
return new SecurityAnalysisResult(mergedPrecontingencyResult, postContingencyResults, operatorStrategyResults);
267269
}
268270

@@ -291,7 +293,8 @@ void mergeSecurityAnalysisResult(SecurityAnalysisResult resultToMerge, Map<Strin
291293

292294
PostContingencyResult mergedPostContingencyResult =
293295
new PostContingencyResult(originalResult.getContingency(), originalResult.getStatus(),
294-
new LimitViolationsResult(violations), mergedNetworkResult, originalResult.getConnectivityResult(), Double.NaN);
296+
new LimitViolationsResult(violations), mergedNetworkResult, originalResult.getConnectivityResult(),
297+
originalResult.getDistributedActivePower() + postContingencyResult.getDistributedActivePower());
295298

296299
postContingencyResults.put(contingencyId, mergedPostContingencyResult);
297300
} else {
@@ -317,7 +320,8 @@ void mergeSecurityAnalysisResult(SecurityAnalysisResult resultToMerge, Map<Strin
317320

318321
OperatorStrategyResult.ConditionalActionsResult mergedConditionalActionResult
319322
= new OperatorStrategyResult.ConditionalActionsResult(conditionalActionsResult.getConditionalActionsId(),
320-
conditionalActionsResult.getStatus(), new LimitViolationsResult(violations), mergedNetworkResult, Double.NaN);
323+
conditionalActionsResult.getStatus(), new LimitViolationsResult(violations), mergedNetworkResult,
324+
originalRes.get().getDistributedActivePower() + conditionalActionsResult.getDistributedActivePower());
321325
conditionalActionsResults.add(mergedConditionalActionResult);
322326

323327
} else {
@@ -750,12 +754,12 @@ protected SecurityAnalysisResult runSimulations(LfNetwork lfNetwork, List<Propag
750754

751755
lfContingency.apply(loadFlowParameters.getBalanceType());
752756

753-
contingencyActivePowerLossDistribution.run(lfNetwork, lfContingency, propagatedContingency.getContingency(), securityAnalysisParameters, contingencyLoadFlowParameters, postContSimReportNode);
757+
double preDistributedActivePower = contingencyActivePowerLossDistribution.run(lfNetwork, lfContingency, propagatedContingency.getContingency(), securityAnalysisParameters, contingencyLoadFlowParameters, postContSimReportNode);
754758

755759
var postContingencyResult = runPostContingencySimulation(lfNetwork, context, propagatedContingency.getContingency(),
756760
lfContingency, preContingencyLimitViolationManager,
757761
securityAnalysisParameters,
758-
preContingencyNetworkResult, createResultExtension, limitReductions);
762+
preContingencyNetworkResult, createResultExtension, limitReductions, preDistributedActivePower);
759763
postContingencyResults.add(postContingencyResult);
760764

761765
if (contingencyLoadFlowParameters != null &&
@@ -819,7 +823,8 @@ protected SecurityAnalysisResult runSimulations(LfNetwork lfNetwork, List<Propag
819823
preContingencyLoadFlowResult.toComponentResultStatus().status(),
820824
new LimitViolationsResult(preContingencyLimitViolationManager.getLimitViolations()),
821825
new NetworkResult(preContingencyNetworkResult.getBranchResults(), preContingencyNetworkResult.getBusResults(),
822-
preContingencyNetworkResult.getThreeWindingsTransformerResults()), Double.NaN),
826+
preContingencyNetworkResult.getThreeWindingsTransformerResults()),
827+
preContingencyLoadFlowResult.getDistributedActivePower() * PerUnit.SB),
823828
postContingencyResults, operatorStrategyResults);
824829
}
825830
}
@@ -865,13 +870,14 @@ protected PostContingencyResult runPostContingencySimulation(LfNetwork network,
865870
LimitViolationManager preContingencyLimitViolationManager,
866871
SecurityAnalysisParameters securityAnalysisParameters,
867872
PreContingencyNetworkResult preContingencyNetworkResult, boolean createResultExtension,
868-
List<LimitReduction> limitReductions) {
873+
List<LimitReduction> limitReductions, double preDistributedActivePower) {
869874
logPostContingencyStart(network, lfContingency);
870875

871876
Stopwatch stopwatch = Stopwatch.createStarted();
872877

873878
// restart LF on post contingency equation system
874-
PostContingencyComputationStatus status = runActionLoadFlow(context); // FIXME: change name.
879+
R result = createLoadFlowEngine(context).run();
880+
PostContingencyComputationStatus status = postContingencyStatusFromLoadFlowResult(result);
875881
var postContingencyLimitViolationManager = new LimitViolationManager(preContingencyLimitViolationManager, limitReductions, securityAnalysisParameters.getIncreasedViolationsParameters());
876882

877883
LoadFlowModel loadFlowModel = securityAnalysisParameters.getLoadFlowParameters().isDc() ? LoadFlowModel.DC : LoadFlowModel.AC;
@@ -893,12 +899,15 @@ protected PostContingencyResult runPostContingencySimulation(LfNetwork network,
893899
lfContingency.getDisconnectedGenerationActivePower() * PerUnit.SB,
894900
lfContingency.getDisconnectedElementIds());
895901

896-
return new PostContingencyResult(contingency, status,
902+
return new PostContingencyResult(
903+
contingency,
904+
status,
897905
new LimitViolationsResult(postContingencyLimitViolationManager.getLimitViolations()),
898906
new NetworkResult(postContingencyNetworkResult.getBranchResults(),
899907
postContingencyNetworkResult.getBusResults(),
900908
postContingencyNetworkResult.getThreeWindingsTransformerResults()),
901-
connectivityResult, Double.NaN);
909+
connectivityResult,
910+
(preDistributedActivePower + result.getDistributedActivePower()) * PerUnit.SB);
902911
}
903912

904913
protected void logPostContingencyStart(LfNetwork network, LfContingency lfContingency) {
@@ -934,7 +943,8 @@ protected OperatorStrategyResult runActionSimulation(LfNetwork network, C contex
934943
Stopwatch stopwatch = Stopwatch.createStarted();
935944

936945
// restart LF on post contingency and post actions equation system
937-
PostContingencyComputationStatus status = runActionLoadFlow(context);
946+
R result = createLoadFlowEngine(context).run();
947+
PostContingencyComputationStatus status = postContingencyStatusFromLoadFlowResult(result);
938948
var postActionsViolationManager = new LimitViolationManager(preContingencyLimitViolationManager, limitReductions, securityAnalysisParameters.getIncreasedViolationsParameters());
939949
LoadFlowModel loadFlowModel = securityAnalysisParameters.getLoadFlowParameters().isDc() ? LoadFlowModel.DC : LoadFlowModel.AC;
940950
var postActionsNetworkResult = new PreContingencyNetworkResult(network, new AbstractNetworkResult.StateMonitorIndexes(monitorIndex, zeroImpedanceMonitoredIndex), createResultExtension,
@@ -958,7 +968,7 @@ protected OperatorStrategyResult runActionSimulation(LfNetwork network, C contex
958968
new NetworkResult(postActionsNetworkResult.getBranchResults(),
959969
postActionsNetworkResult.getBusResults(),
960970
postActionsNetworkResult.getThreeWindingsTransformerResults()),
961-
Double.NaN)
971+
result.getDistributedActivePower() * PerUnit.SB)
962972
));
963973
}
964974

@@ -972,8 +982,4 @@ protected void logActionEnd(LfNetwork network, OperatorStrategy operatorStrategy
972982
operatorStrategy.getContingencyContext().getContingencyId(), network, stopwatch.elapsed(TimeUnit.MILLISECONDS));
973983
}
974984

975-
protected PostContingencyComputationStatus runActionLoadFlow(C context) {
976-
R result = createLoadFlowEngine(context).run();
977-
return postContingencyStatusFromLoadFlowResult(result);
978-
}
979985
}

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.util.ServiceLoader;
2222

2323
/**
24+
* Handling of active power injection lost by contingency.
2425
* @author Damien Jeandemange {@literal <damien.jeandemange at artelys.com>}
2526
*/
2627
public interface ContingencyActivePowerLossDistribution {
@@ -37,6 +38,16 @@ static ContingencyActivePowerLossDistribution find(String name) {
3738

3839
String getName();
3940

40-
void run(LfNetwork network, LfContingency lfContingency, Contingency contingency, SecurityAnalysisParameters securityAnalysisParameters, LoadFlowParametersOverride loadFlowParametersOverride, ReportNode reportNode);
41+
/**
42+
* Called by the security analysis engine for each contingency. Pre-distributes active power imbalances created by contingencies (disconnection of loads, of generators, ...).
43+
* @param network the network
44+
* @param lfContingency the contingency in open-loadflow representation, including among others information about disconnected network elements, and how much active power has been lost
45+
* @param contingency the contingency definition
46+
* @param securityAnalysisParameters the security analysis parameters
47+
* @param loadFlowParametersOverride the contingency load flow parameters overrides if any
48+
* @param reportNode the contingency report node - so that the plugin may add any report message needed
49+
* @return the amount of distributed active power in per-unit
50+
*/
51+
double run(LfNetwork network, LfContingency lfContingency, Contingency contingency, SecurityAnalysisParameters securityAnalysisParameters, LoadFlowParametersOverride loadFlowParametersOverride, ReportNode reportNode);
4152

4253
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public String getName() {
3636
}
3737

3838
@Override
39-
public void run(LfNetwork network, LfContingency lfContingency, Contingency contingency, SecurityAnalysisParameters securityAnalysisParameters, LoadFlowParametersOverride loadFlowParametersOverride, ReportNode reportNode) {
39+
public double run(LfNetwork network, LfContingency lfContingency, Contingency contingency, SecurityAnalysisParameters securityAnalysisParameters, LoadFlowParametersOverride loadFlowParametersOverride, ReportNode reportNode) {
4040
Objects.requireNonNull(network);
4141
Objects.requireNonNull(lfContingency);
4242
Objects.requireNonNull(contingency);
@@ -51,7 +51,9 @@ public void run(LfNetwork network, LfContingency lfContingency, Contingency cont
5151
ActivePowerDistribution activePowerDistribution = ActivePowerDistribution.create(paramsOverride.getBalanceType(loadFlowParameters), openLoadFlowParameters.isLoadPowerFactorConstant(), openLoadFlowParameters.isUseActiveLimits());
5252
var result = activePowerDistribution.run(network, mismatch);
5353
Reports.reportContingencyActivePowerLossDistribution(reportNode, mismatch * PerUnit.SB, result.remainingMismatch() * PerUnit.SB);
54+
return mismatch - result.remainingMismatch();
5455
}
56+
return 0.0;
5557
}
5658

5759
}

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,13 +242,16 @@ private PostContingencyResult computePostContingencyResultFromPostContingencySta
242242
lfContingency.getDisconnectedGenerationActivePower() * PerUnit.SB,
243243
lfContingency.getDisconnectedElementIds());
244244

245-
return new PostContingencyResult(contingency,
245+
return new PostContingencyResult(
246+
contingency,
246247
PostContingencyComputationStatus.CONVERGED,
247248
new LimitViolationsResult(postContingencyLimitViolationManager.getLimitViolations()),
248249
new NetworkResult(postContingencyNetworkResult.getBranchResults(),
249250
postContingencyNetworkResult.getBusResults(),
250251
postContingencyNetworkResult.getThreeWindingsTransformerResults()),
251-
connectivityResult, Double.NaN);
252+
connectivityResult,
253+
Double.NaN // TODO: report distributed active power in Fast DC SA
254+
);
252255
}
253256

254257
/**
@@ -285,7 +288,7 @@ private OperatorStrategyResult computeOperatorStrategyResultFromPostContingencyA
285288
new NetworkResult(postActionsNetworkResult.getBranchResults(),
286289
postActionsNetworkResult.getBusResults(),
287290
postActionsNetworkResult.getThreeWindingsTransformerResults()),
288-
Double.NaN)
291+
Double.NaN) // TODO: report distributed active power in Fast DC SA
289292
)
290293
);
291294
}
@@ -519,7 +522,8 @@ protected SecurityAnalysisResult runSimulations(LfNetwork lfNetwork, List<Propag
519522
new PreContingencyResult(LoadFlowResult.ComponentResult.Status.CONVERGED,
520523
new LimitViolationsResult(preContingencyLimitViolationManager.getLimitViolations()),
521524
new NetworkResult(preContingencyNetworkResult.getBranchResults(), preContingencyNetworkResult.getBusResults(),
522-
preContingencyNetworkResult.getThreeWindingsTransformerResults()), Double.NaN),
525+
preContingencyNetworkResult.getThreeWindingsTransformerResults()),
526+
Double.NaN), // TODO: report distributed active power in Fast DC SA
523527
postContingencyResults, operatorStrategyResults);
524528
}
525529
}

0 commit comments

Comments
 (0)