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 24, 2024
1 parent 10d1976 commit 78dcfe7
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 5 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 @@ -10,7 +10,13 @@
import com.powsybl.iidm.network.ReactiveLimits;
import com.powsybl.iidm.network.VscConverterStation;
import com.powsybl.iidm.network.util.HvdcUtils;
import com.powsybl.openloadflow.network.*;

import com.powsybl.openloadflow.network.LfHvdc;
import com.powsybl.openloadflow.network.LfNetwork;
import com.powsybl.openloadflow.network.LfNetworkParameters;
import com.powsybl.openloadflow.network.LfNetworkStateUpdateParameters;
import com.powsybl.openloadflow.network.LfVscConverterStation;
import com.powsybl.openloadflow.util.LfHvdcUtils;
import com.powsybl.openloadflow.util.PerUnit;

import java.util.Objects;
Expand All @@ -27,8 +33,11 @@ public class LfVscConverterStationImpl extends AbstractLfGenerator implements Lf

private LfHvdc hvdc;

private final boolean hvdcDandlingInIDM;

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 @@ -55,8 +64,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 @@ -97,7 +111,7 @@ public void updateState(LfNetworkStateUpdateParameters parameters) {
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.assertEquals;
Expand Down Expand Up @@ -335,4 +337,42 @@ void testHvdcDirectionChangeAcEmulation() {
assertTrue(pcs1 < 0, "Power delivered by cs1");
assertTrue(Math.abs(pcs2) > Math.abs(pcs1), "Loss at HVDC output");
}

@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 78dcfe7

Please sign in to comment.