Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix flow computation of HVDC connected at only one side #965

Merged
merged 24 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
68fa131
Proposal to handle lost of a VSC converter station (ac emulation or n…
annetill Jan 20, 2024
01e3fa7
Fix dc sensi. Bus contingency still missing...
annetill Jan 23, 2024
9df1b92
Clean after sonar analysis.
annetill Jan 23, 2024
b5e099e
Merge branch 'main' into rework-hvdc
geofjamg Jan 24, 2024
79db2b4
Fix
geofjamg Jan 24, 2024
9b7b84d
Clean comment.
annetill Jan 24, 2024
10d1976
Refactoring.
annetill Jan 24, 2024
78dcfe7
Support HVDC disconnection in IIDM network
vidaldid-rte Jan 23, 2024
365e5e4
PR review + typos
vidaldid-rte Jan 24, 2024
0a25a81
Merge branch 'main' into hvdc-loss-in-N
vidaldid-rte Jan 25, 2024
99df3ae
fix typo
vidaldid-rte Jan 26, 2024
063e0b7
backport test from PR 957
vidaldid-rte Jan 26, 2024
d4f86f5
adapt test to factory (in the factory thehvdc pushes power to the gen…
vidaldid-rte Jan 26, 2024
0c1a72b
Fix N state restoration.
annetill Jan 26, 2024
6cbcd3e
Align isolated bus in IIDM with Networks.isIsolatedBusForHvdc and mod…
vidaldid-rte Jan 26, 2024
8b43547
Merge branch 'main' into hvdc-loss-in-N
vidaldid-rte Jan 26, 2024
78a8497
Add a unit test and fix code smells.
annetill Jan 26, 2024
b74239b
Merge branch 'hvdc-loss-in-N' of https://github.com/powsybl/powsybl-o…
annetill Jan 26, 2024
dca7925
Add unit test.
annetill Jan 26, 2024
1ad88db
Merge branch 'main' into hvdc-loss-in-N
annetill Jan 29, 2024
1875d34
Move utility method.
annetill Jan 29, 2024
d930f03
Fix unit test (1).
annetill Jan 29, 2024
e598e51
Clean unit test (2).
annetill Jan 29, 2024
d9193e4
Merge branch 'main' into hvdc-loss-in-N
annetill Jan 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.isHvdcDandlingInIidm(lccCs, null)) {
vidaldid-rte marked this conversation as resolved.
Show resolved Hide resolved
// 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 hvdcDandlingInIidm;

public LfVscConverterStationImpl(VscConverterStation station, LfNetwork network, LfNetworkParameters parameters, LfNetworkLoadingReport report) {
super(network, HvdcUtils.getConverterStationTargetP(station) / PerUnit.SB);
this.hvdcDandlingInIidm = LfHvdcUtils.isHvdcDandlingInIidm(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 connectivity of that node is given by IIDM
return hvdcDandlingInIidm ? 0 : super.getTargetP();
} else {
// Because in case of AC emulation, active power is injected by HvdcAcEmulationSideXActiveFlowEquationTerm equations
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
jeandemanged marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.powsybl.openloadflow.util;
jeandemanged marked this conversation as resolved.
Show resolved Hide resolved

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

public final class LfHvdcUtils {
jeandemanged marked this conversation as resolved.
Show resolved Hide resolved

private LfHvdcUtils() {
}

public static boolean isHvdcDandlingInIidm(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) {
annetill marked this conversation as resolved.
Show resolved Hide resolved
// connectivity for that bus to be determined by LfNetwork
return false;
}
// Isolated if only connected to the station
return bus.getConnectedTerminalCount() == 1;
annetill marked this conversation as resolved.
Show resolved Hide resolved
}

}
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");
annetill marked this conversation as resolved.
Show resolved Hide resolved

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..
annetill marked this conversation as resolved.
Show resolved Hide resolved

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");
annetill marked this conversation as resolved.
Show resolved Hide resolved
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");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: we get 0MW for VSC and NaN for LCC, we might leave like this for now but add a comment/note here because it is not straightforward / it is inconsistent today in OLF

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, and I am not sure it is the good solution to put NaN.

}

}