Skip to content

Commit

Permalink
Support HVDC disconnection in IIDM network
Browse files Browse the repository at this point in the history
Signed-off-by: VIDAL Didier (Externe) <[email protected]>
  • Loading branch information
vidaldid-rte committed Jan 23, 2024
1 parent 9df1b92 commit c8c3cd2
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.powsybl.iidm.network.*;
import com.powsybl.openloadflow.network.*;
import com.powsybl.openloadflow.util.Evaluable;
import com.powsybl.openloadflow.util.LfHvdcUtils;
import com.powsybl.openloadflow.util.PerUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -285,7 +286,11 @@ void addLoad(Load load, LfNetworkParameters parameters) {
}

void addLccConverterStation(LccConverterStation lccCs, LfNetworkParameters parameters) {
getOrCreateLfLoad(null, parameters).add(lccCs, parameters);
if (!LfHvdcUtils.isHvdcDandlingInIdm(lccCs, null)) {
// Note: Load is determined statically - contingencies or actions that change an LCC Station connectivity
// will continue to give incorrect result
getOrCreateLfLoad(null, parameters).add(lccCs, parameters);
}
}

protected void add(LfGenerator generator) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import com.powsybl.openloadflow.network.LfNetwork;
import com.powsybl.openloadflow.network.LfNetworkParameters;
import com.powsybl.openloadflow.network.LfVscConverterStation;
import com.powsybl.openloadflow.util.LfHvdcUtils;
import com.powsybl.openloadflow.util.PerUnit;

import java.util.Objects;
Expand All @@ -28,10 +29,13 @@ public class LfVscConverterStationImpl extends AbstractLfGenerator implements Lf

private final double lossFactor;

private final boolean hvdcDandlingInIDM;

private LfHvdc hvdc; // set only when AC emulation is activated

public LfVscConverterStationImpl(VscConverterStation station, LfNetwork network, LfNetworkParameters parameters, LfNetworkLoadingReport report) {
super(network, HvdcUtils.getConverterStationTargetP(station) / PerUnit.SB);
this.hvdcDandlingInIDM = LfHvdcUtils.isHvdcDandlingInIdm(station, network);
this.stationRef = Ref.create(station, parameters.isCacheEnabled());
this.lossFactor = station.getLossFactor();

Expand All @@ -58,8 +62,13 @@ public void setHvdc(LfHvdc hvdc) {

@Override
public double getTargetP() {
// because in case of AC emulation, active power is injected by HvdcAcEmulationSideXActiveFlowEquationTerm equations
return hvdc == null || !hvdc.isAcEmulation() ? super.getTargetP() : 0;
if (hvdc == null) {
// Because in case one node is not in the LfNetwork, the connectivty of that node is given by IDM
return hvdcDandlingInIDM ? 0 : super.getTargetP();
} else {
// Because in case of AC emulation, active power is injected by HvdcAcEmulationSideXActiveFlowEquationTerm equationsn
return hvdc.isAcEmulation() ? 0 : super.getTargetP();
}
}

@Override
Expand Down Expand Up @@ -100,7 +109,7 @@ public void updateState() {
station.getTerminal()
.setQ(Double.isNaN(calculatedQ) ? -station.getReactivePowerSetpoint() : -calculatedQ * PerUnit.SB);
if (hvdc == null || !hvdc.isAcEmulation()) { // because when AC emulation is activated, update of p is done in LFHvdcImpl
station.getTerminal().setP(-targetP * PerUnit.SB);
station.getTerminal().setP(-getTargetP() * PerUnit.SB);
}
}
}
36 changes: 36 additions & 0 deletions src/main/java/com/powsybl/openloadflow/util/LfHvdcUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.powsybl.openloadflow.util;

import com.powsybl.iidm.network.Bus;
import com.powsybl.iidm.network.HvdcConverterStation;
import com.powsybl.openloadflow.network.LfNetwork;

public final class LfHvdcUtils {

private LfHvdcUtils() {
}

public static boolean isHvdcDandlingInIdm(HvdcConverterStation<?> station, LfNetwork network) {

if (isIsolated(station.getTerminal().getBusBreakerView().getBus(), network)) {
return true;
} else {
return station.getOtherConverterStation().map(otherConverterStation -> {
Bus bus = otherConverterStation.getTerminal().getBusView().getBus();
return isIsolated(bus, network);
}).orElse(true); // it means there is no HVDC line connected to station
}
}

private static boolean isIsolated(Bus bus, LfNetwork network) {
if (bus == null) {
return true;
}
if (network != null && network.getBusById(bus.getId()) != null) {
// connectivity for that bus to be determined by LfNetwork
return false;
}
// Isolated if only connected to the station
return bus.getConnectedTerminalCount() == 1;
}

}
40 changes: 40 additions & 0 deletions src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowVscTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import com.powsybl.openloadflow.network.HvdcNetworkFactory;
import com.powsybl.openloadflow.network.SlackBusSelectionMode;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import static com.powsybl.openloadflow.util.LoadFlowAssert.*;
import static org.junit.jupiter.api.Assertions.assertTrue;
Expand Down Expand Up @@ -281,4 +283,42 @@ void testVscConverterWithoutHvdcLineNpe() {
LoadFlowResult result = loadFlowRunner.run(network);
assertTrue(result.isFullyConverged());
}

@ParameterizedTest
@ValueSource(strings = {"LCC", "VSC"})
void testHvdcDisconnectedInIDM(String testType) {
HvdcConverterStation.HvdcType hvdcType = switch (testType) {
case "LCC" -> HvdcConverterStation.HvdcType.LCC;
default -> HvdcConverterStation.HvdcType.VSC;
};

LoadFlowParameters parameters = new LoadFlowParameters();
parameters.setHvdcAcEmulation(
switch (testType) {
case "VSC-AcEmul" -> true;
default -> false;
});

Network network = HvdcNetworkFactory.createHvdcLinkedByTwoLinesAndSwitch(hvdcType);

LoadFlow.Runner loadFlowRunner = new LoadFlow.Runner(new OpenLoadFlowProvider(new DenseMatrixFactory()));
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());

assertTrue(network.getGenerator("g1").getTerminal().getP() < -299.99, "Generator expected to deliver enough power for the load");
assertTrue(network.getGenerator("g1").getTerminal().getP() > -310, "Power loss should be realistic");

Line l34 = network.getLine("l34");
l34.getTerminals().stream().forEach(Terminal::disconnect);
result = loadFlowRunner.run(network, parameters);
assertTrue(result.isPartiallyConverged() || result.isFullyConverged()); // disconnected line does not converge.... and this is reported..

double pcs2 = network.getHvdcConverterStation("cs2").getTerminal().getP();
double pcs3 = network.getHvdcConverterStation("cs3").getTerminal().getP();
assertTrue(network.getGenerator("g1").getTerminal().getP() < -299.99, "Generator expected to deliver enough power for the load - delivered only " + network.getGenerator("g1").getTerminal().getP());
assertTrue(network.getGenerator("g1").getTerminal().getP() > -310, "Power loss should be realistic");
assertTrue(pcs2 == 0 || Double.isNaN(pcs2), "HVDC Station should not generate power " + network.getHvdcConverterStation("cs2").getTerminal().getP());
assertTrue(pcs3 == 0 || Double.isNaN(pcs3), "HVDC Station should not generate power");
}

}

0 comments on commit c8c3cd2

Please sign in to comment.