Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,12 @@ public DcLoadFlowResult run() {
double distributedActivePower = 0.0;

boolean isAreaInterchangeControl = outerLoops.stream().anyMatch(DcAreaInterchangeControlOuterLoop.class::isInstance);
if (parameters.isDistributedSlack() || isAreaInterchangeControl) {
// In DC LoadFlow slack mismatch is distributed when mismatch is above epsilon (P_RESIDUE_EPS 1e-3 MW).
// This is different from AC LoadFlow distributing slack when mismatch is above OLF parameter slackBusPMaxMismatch (default 1 MW).
// The reason of the difference is that in DC we can eliminate completely (within epsilon) the slack mismatch
// in a single distribution (unless all generator are hitting limits), whereas in AC reaching epsilon would require too many solver iterations.
if ((parameters.isDistributedSlack() || isAreaInterchangeControl) &&
Math.abs(initialSlackBusActivePowerMismatch) > ActivePowerDistribution.P_RESIDUE_EPS) {
LoadFlowParameters.BalanceType balanceType = parameters.getBalanceType();
boolean useActiveLimits = parameters.getNetworkParameters().isUseActiveLimits();
ActivePowerDistribution activePowerDistribution = ActivePowerDistribution.create(balanceType, false, useActiveLimits);
Expand All @@ -228,6 +233,8 @@ public DcLoadFlowResult run() {
);
double remainingMismatch = resultWbh.remainingMismatch();
distributedActivePower = initialSlackBusActivePowerMismatch - remainingMismatch;
// In the case of slack mismatch not being fully distributed due to e.g. all generators hitting limits, the remaining mismatch is
// checked against OLF parameter slackBusPMaxMismatch (and not epsilon) for appropriate reporting of distribution success or failure.
if (Math.abs(remainingMismatch) > context.getParameters().getSlackBusPMaxMismatch() / PerUnit.SB) {
Reports.reportMismatchDistributionFailure(reportNode, remainingMismatch * PerUnit.SB);
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,6 @@ void outerLoopMaxTotalIterationTest() throws IOException {
Network balance: active generation=140 MW, active load=140 MW, reactive generation=0 MVar, reactive load=55 MVar
Angle reference bus: VL1_0
Slack bus: VL1_0
Slack bus active power (0 MW) distributed in 0 distribution iteration(s)
+ Outer loop IncrementalPhaseControl
Outer loop unsuccessful with status: UNSTABLE
Maximum number of outerloop iterations reached: 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1955,7 +1955,28 @@ void reportTest() throws IOException {
.setLoadFlowParameters(loadFlowParameters);
runSecurityAnalysis(network, contingencies, Collections.emptyList(), securityAnalysisParameters, reportNode);

assertReportEquals("/saReport.txt", reportNode);
assertReportEquals("/saReportAC.txt", reportNode);
}

@Test
void reportTestDc() throws IOException {
var network = EurostagFactory.fix(EurostagTutorialExample1Factory.create());

List<Contingency> contingencies = createAllBranchesContingencies(network);

ReportNode reportNode = ReportNode.newRootReportNode()
.withResourceBundles(PowsyblOpenLoadFlowReportResourceBundle.BASE_NAME, PowsyblTestReportResourceBundle.TEST_BASE_NAME)
.withMessageTemplate("TestSecurityAnalysis")
.build();

LoadFlowParameters loadFlowParameters = new LoadFlowParameters()
.setDc(true)
.setHvdcAcEmulation(false);
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to not have the outerloop in the report, but probably a fix to do in another PR to not create the outerloop if no HVDC in DC emulation in the network

SecurityAnalysisParameters securityAnalysisParameters = new SecurityAnalysisParameters()
.setLoadFlowParameters(loadFlowParameters);
runSecurityAnalysis(network, contingencies, Collections.emptyList(), securityAnalysisParameters, reportNode);

assertReportEquals("/saReportDC.txt", reportNode);
}

@Test
Expand Down
File renamed without changes.
22 changes: 22 additions & 0 deletions src/test/resources/saReportDC.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
+ Test security analysis report
+ DC security analysis on network 'sim1'
+ Network CC0 SC0
+ Network info
Network has 4 buses and 4 branches
Network balance: active generation=607 MW, active load=600 MW, reactive generation=0 MVar, reactive load=200 MVar
Angle reference bus: VLHV1_0
Slack bus: VLHV1_0
+ Pre-contingency simulation
Slack bus active power (-7 MW) distributed in 1 distribution iteration(s)
DC load flow completed (solverSuccess=true, outerloopStatus=STABLE)
+ Post-contingency simulation 'NHV1_NHV2_1'
DC load flow completed (solverSuccess=true, outerloopStatus=STABLE)
+ Post-contingency simulation 'NHV1_NHV2_2'
DC load flow completed (solverSuccess=true, outerloopStatus=STABLE)
+ Post-contingency simulation 'NGEN_NHV1'
Contingency caused the loss of 600 MW injection: 0 MW distributed, 600 MW remaining.
Failed to distribute slack bus active power mismatch, 600 MW remains
DC load flow completed (solverSuccess=false, outerloopStatus=FAILED)
+ Post-contingency simulation 'NHV2_NLOAD'
Contingency caused the loss of -600 MW injection: -600 MW distributed, 0 MW remaining.
DC load flow completed (solverSuccess=true, outerloopStatus=STABLE)
Loading