AcLoadFlowSvcTest.java
/**
* Copyright (c) 2019, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.openloadflow.ac;
import com.powsybl.iidm.network.*;
import com.powsybl.iidm.network.extensions.StandbyAutomatonAdder;
import com.powsybl.iidm.network.extensions.VoltagePerReactivePowerControlAdder;
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.SlackBusSelectionMode;
import com.powsybl.openloadflow.network.VoltageControlNetworkFactory;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static com.powsybl.openloadflow.util.LoadFlowAssert.*;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* SVC test case.
*<pre>
* g1 ld1
* | |
* b1---------b2
* l1 |
* svc1
*</pre>
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
*/
class AcLoadFlowSvcTest {
private Network network;
private Bus bus1;
private Bus bus2;
private Line l1;
private StaticVarCompensator svc1;
private LoadFlow.Runner loadFlowRunner;
private LoadFlowParameters parameters;
private OpenLoadFlowParameters parametersExt;
private Network createNetwork() {
Network network = VoltageControlNetworkFactory.createWithStaticVarCompensator();
bus1 = network.getBusBreakerView().getBus("b1");
bus2 = network.getBusBreakerView().getBus("b2");
svc1 = network.getStaticVarCompensator("svc1");
l1 = network.getLine("l1");
return network;
}
@BeforeEach
void setUp() {
network = createNetwork();
loadFlowRunner = new LoadFlow.Runner(new OpenLoadFlowProvider(new DenseMatrixFactory()));
parameters = new LoadFlowParameters().setUseReactiveLimits(true)
.setDistributedSlack(false);
parametersExt = OpenLoadFlowParameters.create(parameters)
.setSlackBusSelectionMode(SlackBusSelectionMode.MOST_MESHED)
.setVoltagePerReactivePowerControl(false)
.setSvcVoltageMonitoring(false);
}
@Test
void test() {
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
assertVoltageEquals(390, bus1);
assertAngleEquals(0, bus1);
assertVoltageEquals(388.581824, bus2);
assertAngleEquals(-0.057845, bus2);
assertActivePowerEquals(101.216, l1.getTerminal1());
assertReactivePowerEquals(150.649, l1.getTerminal1());
assertActivePowerEquals(-101, l1.getTerminal2());
assertReactivePowerEquals(-150, l1.getTerminal2());
// SVC is OFF
assertActivePowerEquals(0, svc1.getTerminal());
assertReactivePowerEquals(0, svc1.getTerminal());
svc1.setVoltageSetpoint(385)
.setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE);
result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
assertVoltageEquals(390, bus1);
assertAngleEquals(0, bus1);
assertVoltageEquals(385, bus2);
assertAngleEquals(0.116345, bus2);
assertActivePowerEquals(103.562, l1.getTerminal1());
assertReactivePowerEquals(615.582, l1.getTerminal1());
assertActivePowerEquals(-101, l1.getTerminal2());
assertReactivePowerEquals(-607.897, l1.getTerminal2());
assertActivePowerEquals(0, svc1.getTerminal());
assertReactivePowerEquals(457.896, svc1.getTerminal());
}
@Test
void shouldReachReactiveMaxLimit() {
svc1.setBmin(-0.002)
.setVoltageSetpoint(385)
.setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE);
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
Bus bus = svc1.getTerminal().getBusView().getBus();
assertVoltageEquals(386.256, bus);
assertReactivePowerEquals(-svc1.getBmin() * bus.getV() * bus.getV(), svc1.getTerminal()); // min reactive limit has been correctly reached
}
@Test
void testSvcWithSlope() {
svc1.setVoltageSetpoint(385)
.setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE);
svc1.newExtension(VoltagePerReactivePowerControlAdder.class).withSlope(0.03).add();
parametersExt.setVoltagePerReactivePowerControl(true);
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
assertVoltageEquals(390, bus1);
assertAngleEquals(0, bus1);
assertVoltageEquals(387.845, bus2);
assertAngleEquals(-0.022026, bus2);
assertActivePowerEquals(101.466, l1.getTerminal1());
assertReactivePowerEquals(246.252, l1.getTerminal1());
assertActivePowerEquals(-101, l1.getTerminal2());
assertReactivePowerEquals(-244.853, l1.getTerminal2());
assertActivePowerEquals(0, svc1.getTerminal());
assertReactivePowerEquals(94.853, svc1.getTerminal());
}
@Test
void testSvcWithSlope2() {
// Test switch PV to PQ
svc1.setVoltageSetpoint(440)
.setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE);
svc1.newExtension(VoltagePerReactivePowerControlAdder.class).withSlope(0.03).add();
parametersExt.setVoltagePerReactivePowerControl(true);
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
assertVoltageEquals(390, bus1);
assertAngleEquals(0, bus1);
assertVoltageEquals(398.155, bus2);
assertAngleEquals(-0.524413, bus2);
assertActivePowerEquals(108.952, l1.getTerminal1());
assertReactivePowerEquals(-1094.367, l1.getTerminal1());
assertActivePowerEquals(-101, l1.getTerminal2());
assertReactivePowerEquals(1118.223, l1.getTerminal2());
assertActivePowerEquals(0, svc1.getTerminal());
assertReactivePowerEquals(-1268.223, svc1.getTerminal());
}
@Test
void testSvcWithSlope3() {
Generator gen = network.getVoltageLevel("vl2").newGenerator()
.setId("gen")
.setBus("b2")
.setConnectableBus("b2")
.setTargetP(0)
.setTargetV(385)
.setTargetQ(100)
.setMaxP(100)
.setMinP(0)
.setVoltageRegulatorOn(true)
.add();
svc1.setVoltageSetpoint(385)
.setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE);
parametersExt.setVoltagePerReactivePowerControl(true);
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
assertVoltageEquals(390, bus1);
assertAngleEquals(0, bus1);
assertVoltageEquals(385, bus2);
assertAngleEquals(0.116345, bus2);
assertReactivePowerEquals(228.948, svc1.getTerminal()); // same behaviour as slope = 0
assertReactivePowerEquals(228.948, gen.getTerminal()); // same behaviour as slope = 0
}
@Test
void testSvcWithSlope4() {
StaticVarCompensator svc2 = network.getVoltageLevel("vl2").newStaticVarCompensator()
.setId("svc2")
.setConnectableBus("b2")
.setBus("b2")
.setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE)
.setVoltageSetpoint(385)
.setBmin(-0.008)
.setBmax(0.008)
.add();
svc1.setVoltageSetpoint(385)
.setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE);
svc2.newExtension(VoltagePerReactivePowerControlAdder.class).withSlope(0.03).add();
svc1.newExtension(VoltagePerReactivePowerControlAdder.class).withSlope(0.03).add();
parametersExt.setVoltagePerReactivePowerControl(true);
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
assertVoltageEquals(390, bus1);
assertAngleEquals(0, bus1);
assertVoltageEquals(385, bus2);
assertAngleEquals(0.116345, bus2);
assertReactivePowerEquals(228.948, svc1.getTerminal()); // same behaviour as slope = 0
assertReactivePowerEquals(228.948, svc2.getTerminal()); // same behaviour as slope = 0
}
@Test
void testSvcWithSlope5() {
// With a generator at bus2 not controlling voltage
svc1.setVoltageSetpoint(385)
.setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE);
svc1.newExtension(VoltagePerReactivePowerControlAdder.class).withSlope(0.03).add();
network.getVoltageLevel("vl2").newGenerator()
.setId("gen")
.setBus("b2")
.setConnectableBus("b2")
.setTargetP(0)
.setTargetV(385)
.setTargetQ(100)
.setMaxP(100)
.setMinP(0)
.setVoltageRegulatorOn(false)
.add();
parametersExt.setVoltagePerReactivePowerControl(true);
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
assertVoltageEquals(390, bus1);
assertAngleEquals(0, bus1);
assertVoltageEquals(388.462, bus2);
assertAngleEquals(-0.052034, bus2);
assertActivePowerEquals(101.249, l1.getTerminal1());
assertReactivePowerEquals(166.160, l1.getTerminal1());
assertActivePowerEquals(-101, l1.getTerminal2());
assertReactivePowerEquals(-165.413, l1.getTerminal2());
assertActivePowerEquals(0, svc1.getTerminal());
assertReactivePowerEquals(115.413, svc1.getTerminal());
}
@Test
void testRegulationModeReactivePower() {
svc1.setReactivePowerSetpoint(100)
.setRegulationMode(StaticVarCompensator.RegulationMode.REACTIVE_POWER);
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
assertReactivePowerEquals(100, svc1.getTerminal());
}
@Test
void testStandByAutomaton() {
svc1.setVoltageSetpoint(385)
.setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE);
svc1.newExtension(StandbyAutomatonAdder.class)
.withHighVoltageThreshold(400)
.withLowVoltageThreshold(380)
.withLowVoltageSetpoint(385)
.withHighVoltageSetpoint(395)
.withB0(-0.001f)
.withStandbyStatus(true)
.add();
parametersExt.setSvcVoltageMonitoring(true);
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
assertReactivePowerEquals(150.091, svc1.getTerminal());
assertVoltageEquals(387.415, bus2);
}
@Test
void testStandByAutomatonAndSlope() {
svc1.setVoltageSetpoint(385)
.setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE);
svc1.newExtension(VoltagePerReactivePowerControlAdder.class).withSlope(0.03).add();
svc1.newExtension(StandbyAutomatonAdder.class)
.withHighVoltageThreshold(400)
.withLowVoltageThreshold(380)
.withLowVoltageSetpoint(385)
.withHighVoltageSetpoint(395)
.withB0(-0.001f)
.withStandbyStatus(true)
.add();
parametersExt
.setSvcVoltageMonitoring(true)
.setVoltagePerReactivePowerControl(true);
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
assertReactivePowerEquals(150.091, svc1.getTerminal()); // same as testStandByAutomaton
assertVoltageEquals(387.415, bus2); // same as testStandByAutomaton
}
@Test
void testStandByAutomaton2() {
svc1.setVoltageSetpoint(385)
.setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE);
svc1.newExtension(StandbyAutomatonAdder.class)
.withHighVoltageThreshold(397)
.withLowVoltageThreshold(383)
.withLowVoltageSetpoint(384)
.withHighVoltageSetpoint(395)
.withB0(-0.005)
.withStandbyStatus(true)
.add();
parametersExt.setSvcVoltageMonitoring(true);
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
assertReactivePowerEquals(584.129, svc1.getTerminal());
assertVoltageEquals(384.0, bus2);
}
@Test
void testStandByAutomaton3() {
svc1.setVoltageSetpoint(385)
.setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE);
network.getGenerator("g1").setTargetV(405);
svc1.newExtension(StandbyAutomatonAdder.class)
.withHighVoltageThreshold(397)
.withLowVoltageThreshold(383)
.withLowVoltageSetpoint(384)
.withHighVoltageSetpoint(395)
.withB0(-0.005f)
.withStandbyStatus(true)
.add();
parametersExt.setSvcVoltageMonitoring(true);
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
assertReactivePowerEquals(1132.001, svc1.getTerminal());
assertVoltageEquals(395.0, bus2);
}
@Test
void testStandByAutomaton4() {
// Test a voltage controller and a voltage monitor connected to the same bus.
// Voltage monitor is discarded.
svc1.setVoltageSetpoint(385)
.setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE);
svc1.newExtension(StandbyAutomatonAdder.class)
.withHighVoltageThreshold(397)
.withLowVoltageThreshold(383)
.withLowVoltageSetpoint(384)
.withHighVoltageSetpoint(395)
.withB0(-0.005f)
.withStandbyStatus(true)
.add();
network.getVoltageLevel("vl2").newGenerator()
.setMinP(-100)
.setMaxP(100)
.setTargetP(0.0)
.setTargetV(392)
.setVoltageRegulatorOn(true)
.setId("g3")
.setBus(bus2.getId())
.add();
parametersExt.setSvcVoltageMonitoring(true);
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
assertReactivePowerEquals(768.320, svc1.getTerminal());
assertVoltageEquals(392.0, bus2);
}
@Test
void testStandByAutomaton5() {
StaticVarCompensator svc2 = network.getVoltageLevel("vl2").newStaticVarCompensator()
.setId("svc2")
.setConnectableBus("b2")
.setBus("b2")
.setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE)
.setVoltageSetpoint(385)
.setBmin(-0.008)
.setBmax(0.008)
.add();
svc2.newExtension(StandbyAutomatonAdder.class)
.withHighVoltageThreshold(397)
.withLowVoltageThreshold(383)
.withLowVoltageSetpoint(384)
.withHighVoltageSetpoint(395)
.withB0(-0.005f)
.withStandbyStatus(true)
.add();
svc1.setVoltageSetpoint(385)
.setRegulationMode(StaticVarCompensator.RegulationMode.VOLTAGE);
svc1.newExtension(StandbyAutomatonAdder.class)
.withHighVoltageThreshold(397)
.withLowVoltageThreshold(383)
.withLowVoltageSetpoint(384)
.withHighVoltageSetpoint(395)
.withB0(-0.005f)
.withStandbyStatus(true)
.add();
parametersExt.setSvcVoltageMonitoring(true);
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
assertVoltageEquals(390, bus1);
assertAngleEquals(0, bus1);
assertVoltageEquals(385, bus2);
assertAngleEquals(0.116346, bus2);
assertReactivePowerEquals(599.51, svc1.getTerminal()); // same behaviour as classical voltage control.
assertReactivePowerEquals(599.51, svc2.getTerminal()); // same behaviour as classical voltage control.
}
}