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 Hvdc line open at one side #738

Merged
merged 6 commits into from
Feb 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 6 additions & 4 deletions src/main/java/com/powsybl/openloadflow/OpenLoadFlowProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,8 @@ private LoadFlowResult runAc(Network network, LoadFlowParameters parameters, Rep
parameters.isPhaseShifterRegulationOn(),
parameters.isTransformerVoltageControlOn(),
parameters.isDistributedSlack() && (parameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_LOAD || parameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD) && parametersExt.isLoadPowerFactorConstant(),
parameters.isDc());
parameters.isDc(),
acParameters.getNetworkParameters().isBreakers());
result.getNetwork().updateState(updateParameters);

// zero or low impedance branch flows computation
Expand Down Expand Up @@ -180,12 +181,12 @@ private LoadFlowResult runDc(Network network, LoadFlowParameters parameters, Rep

Networks.resetState(network);

List<LoadFlowResult.ComponentResult> componentsResult = results.stream().map(r -> processResult(network, r, parameters)).collect(Collectors.toList());
List<LoadFlowResult.ComponentResult> componentsResult = results.stream().map(r -> processResult(network, r, parameters, dcParameters.getNetworkParameters().isBreakers())).collect(Collectors.toList());
boolean ok = results.stream().anyMatch(DcLoadFlowResult::isSucceeded);
return new LoadFlowResultImpl(ok, Collections.emptyMap(), null, componentsResult);
}

private LoadFlowResult.ComponentResult processResult(Network network, DcLoadFlowResult result, LoadFlowParameters parameters) {
private LoadFlowResult.ComponentResult processResult(Network network, DcLoadFlowResult result, LoadFlowParameters parameters, boolean breakers) {
if (result.isSucceeded() && parameters.isWriteSlackBus()) {
SlackTerminal.reset(network);
}
Expand All @@ -196,7 +197,8 @@ private LoadFlowResult.ComponentResult processResult(Network network, DcLoadFlow
parameters.isPhaseShifterRegulationOn(),
parameters.isTransformerVoltageControlOn(),
false,
true);
true,
breakers);
result.getNetwork().updateState(updateParameters);

// zero or low impedance branch flows computation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,18 @@ public class LfNetworkStateUpdateParameters {

private final boolean dc;

private final boolean breakers;

public LfNetworkStateUpdateParameters(boolean reactiveLimits, boolean writeSlackBus, boolean phaseShifterRegulationOn,
boolean transformerVoltageControlOn, boolean loadPowerFactorConstant, boolean dc) {
boolean transformerVoltageControlOn, boolean loadPowerFactorConstant, boolean dc,
boolean breakers) {
this.reactiveLimits = reactiveLimits;
this.writeSlackBus = writeSlackBus;
this.phaseShifterRegulationOn = phaseShifterRegulationOn;
this.transformerVoltageControlOn = transformerVoltageControlOn;
this.loadPowerFactorConstant = loadPowerFactorConstant;
this.dc = dc;
this.breakers = breakers;
}

public boolean isReactiveLimits() {
Expand All @@ -56,4 +60,8 @@ public boolean isLoadPowerFactorConstant() {
public boolean isDc() {
return dc;
}

public boolean isBreakers() {
return breakers;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -211,10 +211,10 @@ void addLoad(Load load, LfNetworkParameters parameters) {
void addLccConverterStation(LccConverterStation lccCs, LfNetworkParameters parameters) {
// note that LCC converter station are out of the slack distribution.
lccCsRefs.add(Ref.create(lccCs, parameters.isCacheEnabled()));
double targetP = HvdcConverterStations.getConverterStationTargetP(lccCs);
double targetP = HvdcConverterStations.getConverterStationTargetP(lccCs, parameters.isBreakers());
loadTargetP += targetP;
initialLoadTargetP += targetP;
loadTargetQ += HvdcConverterStations.getLccConverterStationLoadTargetQ(lccCs);
loadTargetQ += HvdcConverterStations.getLccConverterStationLoadTargetQ(lccCs, parameters.isBreakers());
}

protected void add(LfGenerator generator) {
Expand Down Expand Up @@ -477,8 +477,8 @@ public void updateState(LfNetworkStateUpdateParameters parameters) {
// update lcc converter station power
for (Ref<LccConverterStation> lccCsRef : lccCsRefs) {
LccConverterStation lccCs = lccCsRef.get();
double pCs = HvdcConverterStations.getConverterStationTargetP(lccCs); // A LCC station has active losses.
double qCs = HvdcConverterStations.getLccConverterStationLoadTargetQ(lccCs); // A LCC station always consumes reactive power.
double pCs = HvdcConverterStations.getConverterStationTargetP(lccCs, parameters.isBreakers()); // A LCC station has active losses.
double qCs = HvdcConverterStations.getLccConverterStationLoadTargetQ(lccCs, parameters.isBreakers()); // A LCC station always consumes reactive power.
lccCs.getTerminal()
.setP(pCs)
.setQ(qCs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@
package com.powsybl.openloadflow.network.impl;

import com.powsybl.commons.PowsyblException;
import com.powsybl.iidm.network.HvdcConverterStation;
import com.powsybl.iidm.network.HvdcLine;
import com.powsybl.iidm.network.LccConverterStation;
import com.powsybl.iidm.network.VscConverterStation;
import com.powsybl.iidm.network.*;

import java.util.Objects;

Expand Down Expand Up @@ -46,7 +43,7 @@ public static double getSign(HvdcConverterStation<?> station) {
/**
* Gets targetP of an VSC converter station or load target P for a LCC converter station.
*/
public static double getConverterStationTargetP(HvdcConverterStation<?> station) {
public static double getConverterStationTargetP(HvdcConverterStation<?> station, boolean breakers) {
// For a VSC converter station, we are in generator convention.
// If the converter station is at side 1 and is rectifier, targetP should be negative.
// If the converter station is at side 1 and is inverter, targetP should be positive.
Expand All @@ -57,19 +54,23 @@ public static double getConverterStationTargetP(HvdcConverterStation<?> station)
// If the converter station is at side 1 and is inverter, p should be negative.
// If the converter station is at side 2 and is rectifier, p should be positive.
// If the converter station is at side 2 and is inverter, p should be negative.
return getSign(station) * getAbsoluteValuePAc(station);
boolean disconnectedAtOtherSide = station.getOtherConverterStation().map(otherConverterStation -> {
Bus bus = Networks.getBus(otherConverterStation.getTerminal(), breakers);
return bus == null;
}).orElse(true); // it means there is no HVDC line connected to station
return disconnectedAtOtherSide ? 0.0 : getSign(station) * getAbsoluteValuePAc(station);
}

/**
* Gets reactive power for an LCC converter station.
*/
public static double getLccConverterStationLoadTargetQ(LccConverterStation lccCs) {
public static double getLccConverterStationLoadTargetQ(LccConverterStation lccCs, boolean breakers) {
// Load convention.
// If the converter station is at side 1 and is rectifier, p should be positive.
// If the converter station is at side 1 and is inverter, p should be negative.
// If the converter station is at side 2 and is rectifier, p should be positive.
// If the converter station is at side 2 and is inverter, p should be negative.
double pCs = getConverterStationTargetP(lccCs);
double pCs = getConverterStationTargetP(lccCs, breakers);
return Math.abs(pCs * Math.tan(Math.acos(lccCs.getPowerFactor()))); // A LCC station always consumes reactive power.
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class LfVscConverterStationImpl extends AbstractLfGenerator implements Lf
private LfHvdc hvdc; // set only when AC emulation is activated

public LfVscConverterStationImpl(VscConverterStation station, LfNetwork network, LfNetworkParameters parameters, LfNetworkLoadingReport report) {
super(network, HvdcConverterStations.getConverterStationTargetP(station));
super(network, HvdcConverterStations.getConverterStationTargetP(station, parameters.isBreakers()));
this.stationRef = Ref.create(station, parameters.isCacheEnabled());
this.lossFactor = station.getLossFactor();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ private void complete(boolean shuntCompensatorVoltageControlOn, boolean slackDis
generatorIdsToLose.add(connectable.getId());
} else {
LccConverterStation lcc = (LccConverterStation) connectable;
PowerShift lccPowerShift = new PowerShift(HvdcConverterStations.getConverterStationTargetP(lcc) / PerUnit.SB, 0,
HvdcConverterStations.getLccConverterStationLoadTargetQ(lcc) / PerUnit.SB);
PowerShift lccPowerShift = new PowerShift(HvdcConverterStations.getConverterStationTargetP(lcc, breakers) / PerUnit.SB, 0,
HvdcConverterStations.getLccConverterStationLoadTargetQ(lcc, breakers) / PerUnit.SB);
originalPowerShiftIds.add(lcc.getId());
addPowerShift(lcc.getTerminal(), busIdsToShift, lccPowerShift, breakers);
}
Expand Down
43 changes: 43 additions & 0 deletions src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowVscTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,49 @@ void testHvdcAcEmulationNonSupported2() {

VscConverterStation cs4 = network.getVscConverterStation("cs4");
assertActivePowerEquals(2.0, cs4.getTerminal());
}

@Test
void testHvdcDisconnectedAtOneSide() {
Network network = HvdcNetworkFactory.createVsc();
network.getVscConverterStation("cs3").getTerminal().disconnect();
LoadFlow.Runner loadFlowRunner = new LoadFlow.Runner(new OpenLoadFlowProvider(new DenseMatrixFactory()));
LoadFlowParameters parameters = new LoadFlowParameters()
.setUseReactiveLimits(false)
.setDistributedSlack(false);
OpenLoadFlowParameters.create(parameters)
.setSlackBusSelectionMode(SlackBusSelectionMode.MOST_MESHED);
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isOk());

Bus bus1 = network.getBusView().getBus("vl1_0");
assertVoltageEquals(390, bus1);
assertAngleEquals(0, bus1);

Bus bus2 = network.getBusView().getBus("vl2_0");
assertVoltageEquals(385, bus2);
assertAngleEquals(0.18116, bus2);

Bus bus3 = network.getBusView().getBus("vl3_0");
assertVoltageEquals(Double.NaN, bus3);
assertAngleEquals(Double.NaN, bus3);

Generator g1 = network.getGenerator("g1");
assertActivePowerEquals(-102.56, g1.getTerminal());
assertReactivePowerEquals(-632.700, g1.getTerminal());

VscConverterStation cs2 = network.getVscConverterStation("cs2");
assertActivePowerEquals(0.00, cs2.getTerminal());
assertReactivePowerEquals(614.750, cs2.getTerminal());

VscConverterStation cs3 = network.getVscConverterStation("cs3");
assertActivePowerEquals(Double.NaN, cs3.getTerminal());
assertReactivePowerEquals(Double.NaN, cs3.getTerminal());

Line l12 = network.getLine("l12");
assertActivePowerEquals(52.65, l12.getTerminal1());
assertReactivePowerEquals(632.700, l12.getTerminal1());
assertActivePowerEquals(-50.00, l12.getTerminal2());
assertReactivePowerEquals(-624.750, l12.getTerminal2());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ void busBreakerAndNonImpedantBranchIssue() {
new AcloadFlowEngine(context)
.run();
}
lfNetwork.updateState(new LfNetworkStateUpdateParameters(false, false, false, false, false, false));
lfNetwork.updateState(new LfNetworkStateUpdateParameters(false, false, false, false, false, false, false));
for (Bus bus : network.getBusView().getBuses()) {
assertEquals(400, bus.getV(), 0);
assertEquals(0, bus.getAngle(), 0);
Expand All @@ -68,7 +68,7 @@ void busBreakerAndNonImpedantBranchIssueRef() {
new AcloadFlowEngine(context)
.run();
}
lfNetwork.updateState(new LfNetworkStateUpdateParameters(false, false, false, false, false, false));
lfNetwork.updateState(new LfNetworkStateUpdateParameters(false, false, false, false, false, false, false));
assertEquals(-100, network.getGenerator("G1").getTerminal().getQ(), 0);
assertEquals(-100, network.getGenerator("G2").getTerminal().getQ(), 0);
}
Expand Down