Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DC Load Flow reference bus and multi slack support #1118

Merged
merged 14 commits into from
Nov 25, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -1921,8 +1921,9 @@ public static DcLoadFlowParameters createDcParameters(LoadFlowParameters paramet
.setHvdcAcEmulation(parameters.isHvdcAcEmulation())
.setLowImpedanceThreshold(parametersExt.getLowImpedanceThreshold())
.setSvcVoltageMonitoring(false)
.setMaxSlackBusCount(1)
.setLinePerUnitMode(parametersExt.getLinePerUnitMode());
.setMaxSlackBusCount(parametersExt.getMaxSlackBusCount())
.setLinePerUnitMode(parametersExt.getLinePerUnitMode())
.setReferenceBusSelector(ReferenceBusSelector.fromMode(parametersExt.getReferenceBusSelectionMode()));

var equationSystemCreationParameters = new DcEquationSystemCreationParameters()
.setUpdateFlows(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.powsybl.openloadflow.equations.EquationSystem;
import com.powsybl.openloadflow.equations.TargetVector;
import com.powsybl.openloadflow.network.LfBranch;
import com.powsybl.openloadflow.network.LfBus;
import com.powsybl.openloadflow.network.LfNetwork;

/**
Expand All @@ -24,7 +25,12 @@ public class DcTargetVector extends TargetVector<DcVariableType, DcEquationType>
public static void init(Equation<DcVariableType, DcEquationType> equation, LfNetwork network, double[] targets) {
switch (equation.getType()) {
case BUS_TARGET_P:
targets[equation.getColumn()] = network.getBus(equation.getElementNum()).getTargetP();
LfBus bus = network.getBus(equation.getElementNum());
targets[equation.getColumn()] = bus.getTargetP();
jeandemanged marked this conversation as resolved.
Show resolved Hide resolved
// Only used for multi slack (BUS_TARGET_P equation is disabled for first slack bus)
if (bus.isSlack()) {
targets[equation.getColumn()] += DcLoadFlowEngine.getActivePowerMismatch(network.getBuses()) / network.getSlackBuses().size();
jeandemanged marked this conversation as resolved.
Show resolved Hide resolved
}
break;

case BUS_TARGET_PHI,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@ private void createBuses(EquationSystem<DcVariableType, DcEquationType> equation
for (LfBus bus : network.getBuses()) {
var p = equationSystem.createEquation(bus, DcEquationType.BUS_TARGET_P);
bus.setP(p);
if (bus.isSlack()) {
if (bus.isReference()) {
equationSystem.createEquation(bus, DcEquationType.BUS_TARGET_PHI)
.addTerm(equationSystem.getVariable(bus.getNum(), DcVariableType.BUS_PHI).createTerm());
}
if (bus == network.getSlackBus()) {
p.setActive(false);
}
jeandemanged marked this conversation as resolved.
Show resolved Hide resolved
}
Expand Down Expand Up @@ -77,7 +79,7 @@ public static void createNonImpedantBranch(EquationSystem<DcVariableType, DcEqua
.addTerm(dummyP.createTerm())
.setActive(branch.isDisabled() || !spanningTree); // inverted logic
} else {
throw new IllegalStateException("Cannot happen because only there is one slack bus per model");
throw new IllegalStateException("Cannot happen because there is only one reference bus per model");
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
/**
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
*/
class MultipleSlackBusesTest {
class AcMultipleSlackBusesTest {

private Network network;

Expand Down
jeandemanged marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we imagine parametrizing the tests in AcMultipleSlackBusesTests rather than having a whole class DcMultipleSlackBusesTest that implements the same cases ? (To do so maybe a condition can be added in the test to differentiate asserts values between AC and DC)
By doing so, when adding new tests in the future, we would be sure to implement them in both AC and DC mode.

Copy link
Member Author

Choose a reason for hiding this comment

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

I agree, here a proposal for this : 2b39a11, what do you think ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you ! It is good for me. #1116 has been merged so the values can be changed for the corresponding test.

Copy link
Member Author

Choose a reason for hiding this comment

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

I updated the values in a6ab981

Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package com.powsybl.openloadflow.dc;

import com.powsybl.iidm.network.Bus;
import com.powsybl.iidm.network.Line;
import com.powsybl.iidm.network.Load;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.TwoWindingsTransformer;
import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
import com.powsybl.loadflow.LoadFlow;
import com.powsybl.loadflow.LoadFlowParameters;
import com.powsybl.loadflow.LoadFlowResult;
import com.powsybl.math.matrix.DenseMatrixFactory;
import com.powsybl.openloadflow.OpenLoadFlowParameters;
import com.powsybl.openloadflow.OpenLoadFlowProvider;
import com.powsybl.openloadflow.network.EurostagFactory;
import com.powsybl.openloadflow.network.ReferenceBusSelectionMode;
import com.powsybl.openloadflow.network.SlackBusSelectionMode;
import com.powsybl.openloadflow.util.LoadFlowAssert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.List;

import static com.powsybl.openloadflow.util.LoadFlowAssert.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

class DcMultipleSlackBusesTest {

private Network network;

private LoadFlow.Runner loadFlowRunner;

private LoadFlowParameters parameters;

private OpenLoadFlowParameters parametersExt;

@BeforeEach
void setUp() {
network = EurostagFactory.fix(EurostagTutorialExample1Factory.create());
loadFlowRunner = new LoadFlow.Runner(new OpenLoadFlowProvider(new DenseMatrixFactory()));
parameters = new LoadFlowParameters()
.setDc(true)
.setUseReactiveLimits(false)
.setDistributedSlack(false);
parametersExt = OpenLoadFlowParameters.create(parameters)
.setMaxSlackBusCount(2);
}

@Test
void dcMultiSlackTest() {
parametersExt.setReferenceBusSelectionMode(ReferenceBusSelectionMode.GENERATOR_REFERENCE_PRIORITY);
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
LoadFlowResult.ComponentResult componentResult = result.getComponentResults().get(0);
List<LoadFlowResult.SlackBusResult> slackBusResults = componentResult.getSlackBusResults();
assertEquals(2, slackBusResults.size());

Bus nGen = network.getBusBreakerView().getBus("NGEN");
Line l12A = network.getLine("NHV1_NHV2_1");
Line l12B = network.getLine("NHV1_NHV2_2");
TwoWindingsTransformer t2wtGen = network.getTwoWindingsTransformer("NGEN_NHV1");
TwoWindingsTransformer t2wtLoad = network.getTwoWindingsTransformer("NHV2_NLOAD");

assertAngleEquals(0.0, nGen);
assertActivePowerEquals(301.75, l12A.getTerminal1());
assertActivePowerEquals(301.75, l12B.getTerminal1());
assertActivePowerEquals(600, t2wtLoad.getTerminal1());
assertActivePowerEquals(607, t2wtGen.getTerminal1());

assertEquals(List.of("VLHV1_0", "VLHV2_0"), result.getComponentResults().get(0).getSlackBusResults().stream().map(r -> r.getId()).toList());
assertEquals(-3.5, slackBusResults.get(0).getActivePowerMismatch(), LoadFlowAssert.DELTA_POWER);
assertEquals(-3.5, slackBusResults.get(1).getActivePowerMismatch(), LoadFlowAssert.DELTA_POWER);

parameters.setDistributedSlack(true);
result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
componentResult = result.getComponentResults().get(0);
slackBusResults = componentResult.getSlackBusResults();
assertEquals(2, slackBusResults.size());
assertEquals(0, slackBusResults.get(0).getActivePowerMismatch(), LoadFlowAssert.DELTA_POWER);
assertEquals(0, slackBusResults.get(1).getActivePowerMismatch(), LoadFlowAssert.DELTA_POWER);
}

@Test
void dcNonImpedantBranchTest() {
network.getLine("NHV1_NHV2_1")
.setR(0)
.setX(0);
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
LoadFlowResult.ComponentResult componentResult = result.getComponentResults().get(0);
List<LoadFlowResult.SlackBusResult> slackBusResults = componentResult.getSlackBusResults();
assertEquals(2, slackBusResults.size());
assertEquals(-3.5, slackBusResults.get(0).getActivePowerMismatch(), LoadFlowAssert.DELTA_POWER);
assertEquals(-3.5, slackBusResults.get(1).getActivePowerMismatch(), LoadFlowAssert.DELTA_POWER);

Line l12A = network.getLine("NHV1_NHV2_1");
Line l12B = network.getLine("NHV1_NHV2_2");
TwoWindingsTransformer t2wtGen = network.getTwoWindingsTransformer("NGEN_NHV1");
TwoWindingsTransformer t2wtLoad = network.getTwoWindingsTransformer("NHV2_NLOAD");

assertActivePowerEquals(603.5, l12A.getTerminal1());
assertActivePowerEquals(0.0, l12B.getTerminal1());
assertActivePowerEquals(600, t2wtLoad.getTerminal1());
assertActivePowerEquals(607, t2wtGen.getTerminal1());

parameters.setDistributedSlack(true);
result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
componentResult = result.getComponentResults().get(0);
slackBusResults = componentResult.getSlackBusResults();
assertEquals(2, slackBusResults.size());
assertEquals(0, slackBusResults.get(0).getActivePowerMismatch(), LoadFlowAssert.DELTA_POWER);
assertEquals(0, slackBusResults.get(1).getActivePowerMismatch(), LoadFlowAssert.DELTA_POWER);
}

@Test
void dcMultiSlackWithLoadOnSlackBus() {
parametersExt.setSlackBusSelectionMode(SlackBusSelectionMode.NAME);
parametersExt.setSlackBusesIds(List.of("VLHV2", "VLLOAD"));
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
LoadFlowResult.ComponentResult componentResult = result.getComponentResults().get(0);
List<LoadFlowResult.SlackBusResult> slackBusResults = componentResult.getSlackBusResults();
assertEquals(2, slackBusResults.size());
TwoWindingsTransformer t2wtLoad = network.getTwoWindingsTransformer("NHV2_NLOAD");
Load load = network.getLoad("LOAD");

assertActivePowerEquals(-603.5, t2wtLoad.getTerminal2());
assertActivePowerEquals(600.0, load.getTerminal());

assertEquals(-3.5, slackBusResults.get(0).getActivePowerMismatch(), LoadFlowAssert.DELTA_POWER);
assertEquals(-3.5, slackBusResults.get(1).getActivePowerMismatch(), LoadFlowAssert.DELTA_POWER);
}

}