From 47e62afd3f3d0e3f2527df0bd931547d8e37a63b Mon Sep 17 00:00:00 2001 From: HugoKulesza <94374655+HugoKulesza@users.noreply.github.com> Date: Tue, 23 Jan 2024 16:11:36 +0100 Subject: [PATCH] Fix vsc replacement by regulating generator (#2867) Signed-off-by: Hugo KULESZA Signed-off-by: Anne Tilloy --- iidm/iidm-reducer/pom.xml | 5 ++ .../iidm/reducer/DefaultNetworkReducer.java | 37 ++++++++++++-- .../reducer/DefaultNetworkReducerTest.java | 50 +++++++++++++++++-- 3 files changed, 84 insertions(+), 8 deletions(-) diff --git a/iidm/iidm-reducer/pom.xml b/iidm/iidm-reducer/pom.xml index 6817944e0af..95585d0f5a3 100644 --- a/iidm/iidm-reducer/pom.xml +++ b/iidm/iidm-reducer/pom.xml @@ -45,6 +45,11 @@ powsybl-iidm-api ${project.version} + + ${project.groupId} + powsybl-iidm-extensions + ${project.version} + diff --git a/iidm/iidm-reducer/src/main/java/com/powsybl/iidm/reducer/DefaultNetworkReducer.java b/iidm/iidm-reducer/src/main/java/com/powsybl/iidm/reducer/DefaultNetworkReducer.java index bdc522e96c0..d615dba838d 100644 --- a/iidm/iidm-reducer/src/main/java/com/powsybl/iidm/reducer/DefaultNetworkReducer.java +++ b/iidm/iidm-reducer/src/main/java/com/powsybl/iidm/reducer/DefaultNetworkReducer.java @@ -7,6 +7,7 @@ package com.powsybl.iidm.reducer; import com.powsybl.iidm.network.*; +import com.powsybl.iidm.network.extensions.ActivePowerControlAdder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -209,7 +210,7 @@ private void replaceHvdcLine(HvdcLine hvdcLine, VoltageLevel vl, Terminal termin if (station.getHvdcType() == HvdcConverterStation.HvdcType.VSC) { VscConverterStation vscStation = (VscConverterStation) station; if (vscStation.isVoltageRegulatorOn()) { - replaceHvdcLineByGenerator(hvdcLine, vl, terminal); + replaceHvdcLineByGenerator(hvdcLine, vl, terminal, vscStation); } else { replaceHvdcLineByLoad(hvdcLine, vl, terminal); } @@ -242,21 +243,23 @@ private void replaceHvdcLineByLoad(HvdcLine hvdcLine, VoltageLevel vl, Terminal observers.forEach(o -> o.hvdcLineReplaced(hvdcLine, load)); } - private void replaceHvdcLineByGenerator(HvdcLine hvdcLine, VoltageLevel vl, Terminal terminal) { + private void replaceHvdcLineByGenerator(HvdcLine hvdcLine, VoltageLevel vl, Terminal terminal, VscConverterStation station) { double maxP = hvdcLine.getMaxP(); GeneratorAdder genAdder = vl.newGenerator() .setId(hvdcLine.getId()) .setName(hvdcLine.getOptionalName().orElse(null)) .setEnergySource(EnergySource.OTHER) - .setVoltageRegulatorOn(false) + .setVoltageRegulatorOn(true) .setMaxP(maxP) .setMinP(-maxP) - .setTargetP(checkP(terminal)) - .setTargetQ(checkQ(terminal)); + .setTargetP(-checkP(terminal)) + .setTargetV(station.getVoltageSetpoint()); fillNodeOrBus(genAdder, terminal); double p = terminal.getP(); double q = terminal.getQ(); + ReactiveLimits stationLimits = station.getReactiveLimits(); + HvdcConverterStation converter1 = hvdcLine.getConverterStation1(); HvdcConverterStation converter2 = hvdcLine.getConverterStation2(); hvdcLine.remove(); @@ -267,6 +270,30 @@ private void replaceHvdcLineByGenerator(HvdcLine hvdcLine, VoltageLevel vl, Term generator.getTerminal() .setP(p) .setQ(q); + + if (stationLimits != null) { + if (stationLimits.getKind() == ReactiveLimitsKind.MIN_MAX) { + MinMaxReactiveLimits minMaxLimits = (MinMaxReactiveLimits) stationLimits; + generator.newMinMaxReactiveLimits() + .setMinQ(minMaxLimits.getMinQ()) + .setMaxQ(minMaxLimits.getMaxQ()) + .add(); + } else if (stationLimits.getKind() == ReactiveLimitsKind.CURVE) { + ReactiveCapabilityCurve reactiveCurve = (ReactiveCapabilityCurve) stationLimits; + ReactiveCapabilityCurveAdder curveAdder = generator.newReactiveCapabilityCurve(); + reactiveCurve.getPoints().forEach(point -> + curveAdder.beginPoint() + .setP(point.getP()) + .setMinQ(point.getMinQ()) + .setMaxQ(point.getMaxQ()) + .endPoint() + ); + curveAdder.add(); + } + } + + generator.newExtension(ActivePowerControlAdder.class).withParticipate(false).add(); + observers.forEach(o -> o.hvdcLineReplaced(hvdcLine, generator)); } diff --git a/iidm/iidm-reducer/src/test/java/com/powsybl/iidm/reducer/DefaultNetworkReducerTest.java b/iidm/iidm-reducer/src/test/java/com/powsybl/iidm/reducer/DefaultNetworkReducerTest.java index 4a7d2450195..c26e504a9fd 100644 --- a/iidm/iidm-reducer/src/test/java/com/powsybl/iidm/reducer/DefaultNetworkReducerTest.java +++ b/iidm/iidm-reducer/src/test/java/com/powsybl/iidm/reducer/DefaultNetworkReducerTest.java @@ -7,6 +7,7 @@ package com.powsybl.iidm.reducer; import com.powsybl.iidm.network.*; +import com.powsybl.iidm.network.extensions.ActivePowerControl; import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; import com.powsybl.iidm.network.test.FictitiousSwitchFactory; import com.powsybl.iidm.network.test.HvdcTestNetwork; @@ -14,6 +15,7 @@ import org.junit.jupiter.api.Test; import java.util.Collections; +import java.util.Iterator; import static org.junit.jupiter.api.Assertions.*; @@ -248,23 +250,35 @@ void testHvdc() { @Test void testHvdcReplacement() { + testHvdcReplacementLcc(); + testHvdcReplacementVscWithMinMaxReactiveLimits(); + tetHvdcReplacementVscWithReactiveCapabilityCurve(); + } + + private static void testHvdcReplacementLcc() { NetworkReducerObserverImpl observerLcc = new NetworkReducerObserverImpl(); Network networkLcc = HvdcTestNetwork.createLcc(); assertEquals(0, networkLcc.getLoadCount()); assertEquals(2, networkLcc.getHvdcConverterStationCount()); NetworkReducer reducerLcc = NetworkReducer.builder() - .withNetworkPredicate(IdentifierNetworkPredicate.of("VL1")) - .withObservers(observerLcc) - .build(); + .withNetworkPredicate(IdentifierNetworkPredicate.of("VL1")) + .withObservers(observerLcc) + .build(); reducerLcc.reduce(networkLcc); assertEquals(0, networkLcc.getHvdcLineCount()); assertEquals(1, observerLcc.getHvdcLineReplacedCount()); assertEquals(1, observerLcc.getHvdcLineRemovedCount()); assertEquals(1, networkLcc.getLoadCount()); assertEquals(0, networkLcc.getHvdcConverterStationCount()); + } + private static void testHvdcReplacementVscWithMinMaxReactiveLimits() { NetworkReducerObserverImpl observerVsc = new NetworkReducerObserverImpl(); Network networkVsc = HvdcTestNetwork.createVsc(); + VscConverterStation station = networkVsc.getVscConverterStation("C1"); + double targetV = station.getVoltageSetpoint(); + station.newMinMaxReactiveLimits().setMaxQ(200).setMinQ(-200).add(); + double p = station.getTerminal().getP(); assertEquals(0, networkVsc.getGeneratorCount()); assertEquals(2, networkVsc.getHvdcConverterStationCount()); NetworkReducer reducerVsc = NetworkReducer.builder() @@ -279,7 +293,37 @@ void testHvdcReplacement() { Generator gen = networkVsc.getGenerator("L"); assertEquals(300, gen.getMaxP()); assertEquals(-300, gen.getMinP()); + assertEquals(-p, gen.getTargetP()); + assertTrue(gen.isVoltageRegulatorOn()); + assertEquals(targetV, gen.getTargetV()); + assertEquals(200, gen.getReactiveLimits(MinMaxReactiveLimits.class).getMaxQ()); + assertFalse(gen.getExtension(ActivePowerControl.class).isParticipate()); + } + private static void tetHvdcReplacementVscWithReactiveCapabilityCurve() { + NetworkReducerObserverImpl observerVsc2 = new NetworkReducerObserverImpl(); + Network networkVsc2 = HvdcTestNetwork.createVsc(); + VscConverterStation station2 = networkVsc2.getVscConverterStation("C1"); + station2.newReactiveCapabilityCurve() + .beginPoint().setP(0.0).setMinQ(-200).setMaxQ(200).endPoint() + .beginPoint().setP(100.0).setMinQ(-200).setMaxQ(200).endPoint() + .add(); + NetworkReducer reducerVsc2 = NetworkReducer.builder() + .withNetworkPredicate(IdentifierNetworkPredicate.of("VL1")) + .withObservers(observerVsc2) + .build(); + reducerVsc2.reduce(networkVsc2); + Generator gen2 = networkVsc2.getGenerator("L"); + assertEquals(2, gen2.getReactiveLimits(ReactiveCapabilityCurve.class).getPointCount()); + Iterator pointIt = gen2.getReactiveLimits(ReactiveCapabilityCurve.class).getPoints().iterator(); + ReactiveCapabilityCurve.Point point = pointIt.next(); + assertEquals(0.0, point.getP(), 0.001); + assertEquals(-200.0, point.getMinQ(), 0.001); + assertEquals(200.0, point.getMaxQ(), 0.001); + point = pointIt.next(); + assertEquals(100.0, point.getP(), 0.001); + assertEquals(-200.0, point.getMinQ(), 0.001); + assertEquals(200.0, point.getMaxQ(), 0.001); } @Test