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