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 8 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 @@ -930,7 +930,7 @@ static void updateBranchEquations(LfBranch branch) {
private static void createHvdcAcEmulationEquations(LfHvdc hvdc, EquationSystem<AcVariableType, AcEquationType> equationSystem) {
EquationTerm<AcVariableType, AcEquationType> p1 = null;
EquationTerm<AcVariableType, AcEquationType> p2 = null;
if (hvdc.getBus1() != null && hvdc.getBus2() != null) {
if (hvdc.getBus1() != null && hvdc.getBus2() != null && hvdc.isAcEmulation()) {
p1 = new HvdcAcEmulationSide1ActiveFlowEquationTerm(hvdc, hvdc.getBus1(), hvdc.getBus2(), equationSystem.getVariableSet());
p2 = new HvdcAcEmulationSide2ActiveFlowEquationTerm(hvdc, hvdc.getBus1(), hvdc.getBus2(), equationSystem.getVariableSet());
} else {
Expand Down
9 changes: 9 additions & 0 deletions src/main/java/com/powsybl/openloadflow/network/HvdcState.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,20 @@
*/
public class HvdcState extends ElementState<LfHvdc> {

private boolean acEmulation;

public HvdcState(LfHvdc hvdc) {
super(hvdc);
this.acEmulation = hvdc.isAcEmulation();
}

public static HvdcState save(LfHvdc hvdc) {
return new HvdcState(hvdc);
}

@Override
public void restore() {
super.restore();
element.setAcEmulation(acEmulation);
}
}
7 changes: 4 additions & 3 deletions src/main/java/com/powsybl/openloadflow/network/LfAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -365,9 +365,10 @@ public void apply(LfNetworkParameters networkParameters) {
}

if (hvdc != null) {
hvdc.setDisabled(true);
hvdc.getConverterStation1().setTargetP(-hvdc.getP1().eval());
hvdc.getConverterStation2().setTargetP(-hvdc.getP2().eval());
hvdc.setAcEmulation(false);
hvdc.setDisabled(true); // for equations only, but should be hidden
hvdc.getConverterStation1().setTargetP(-hvdc.getP1().eval()); // override
hvdc.getConverterStation2().setTargetP(-hvdc.getP2().eval()); // override
}
}
}
2 changes: 2 additions & 0 deletions src/main/java/com/powsybl/openloadflow/network/LfBus.java
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ default double getHighVoltageLimit() {

void addBranch(LfBranch branch);

List<LfHvdc> getHvdcs();

void addHvdc(LfHvdc hvdc);

void updateState(LfNetworkStateUpdateParameters parameters);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,18 @@ public class LfContingency {

private final Set<String> disconnectedElementIds;

private final Set<LfHvdc> hvdcsWithoutPower;

public LfContingency(String id, int index, int createdSynchronousComponentsCount, DisabledNetwork disabledNetwork, Map<LfShunt, AdmittanceShift> shuntsShift,
Map<LfLoad, LfLostLoad> lostLoads, Set<LfGenerator> lostGenerators) {
Map<LfLoad, LfLostLoad> lostLoads, Set<LfGenerator> lostGenerators, Set<LfHvdc> hvdcsWithoutPower) {
this.id = Objects.requireNonNull(id);
this.index = index;
this.createdSynchronousComponentsCount = createdSynchronousComponentsCount;
this.disabledNetwork = Objects.requireNonNull(disabledNetwork);
this.shuntsShift = Objects.requireNonNull(shuntsShift);
this.lostLoads = Objects.requireNonNull(lostLoads);
this.lostGenerators = Objects.requireNonNull(lostGenerators);
this.hvdcsWithoutPower = Objects.requireNonNull(hvdcsWithoutPower);
this.disconnectedLoadActivePower = 0.0;
this.disconnectedGenerationActivePower = 0.0;
this.disconnectedElementIds = new HashSet<>();
Expand Down Expand Up @@ -179,6 +182,10 @@ public void apply(LoadFlowParameters.BalanceType balanceType) {
bus.setGeneratorReactivePowerControlEnabled(false);
}
}
for (LfHvdc hvdc : hvdcsWithoutPower) {
hvdc.getConverterStation1().setTargetP(0.0);
hvdc.getConverterStation2().setTargetP(0.0);
}
}

private static double getUpdatedLoadP0(LfLoad load, LoadFlowParameters.BalanceType balanceType, double initialP0, double initialVariableActivePower) {
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/com/powsybl/openloadflow/network/LfHvdc.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public interface LfHvdc extends LfElement {

LfBus getBus2();

LfBus getOtherBus(LfBus bus);

void setP1(Evaluable p1);

Evaluable getP1();
Expand All @@ -29,6 +31,10 @@ public interface LfHvdc extends LfElement {

double getP0();

boolean isAcEmulation();

void setAcEmulation(boolean acEmulation);

LfVscConverterStation getConverterStation1();

LfVscConverterStation getConverterStation2();
Expand Down
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)) {
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 Expand Up @@ -482,6 +487,11 @@ public void addBranch(LfBranch branch) {
branches.add(Objects.requireNonNull(branch));
}

@Override
public List<LfHvdc> getHvdcs() {
return hvdcs;
}

@Override
public void addHvdc(LfHvdc hvdc) {
hvdcs.add(Objects.requireNonNull(hvdc));
Expand Down Expand Up @@ -711,6 +721,14 @@ public void setDisabled(boolean disabled) {
if (controllerShunt != null) {
controllerShunt.setDisabled(disabled);
}
for (LfHvdc hvdc : hvdcs) {
if (disabled) {
hvdc.setDisabled(true);
} else if (!hvdc.getOtherBus(this).isDisabled()) {
// if both buses enabled only
hvdc.setDisabled(false);
}
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,27 @@ public class LfHvdcImpl extends AbstractElement implements LfHvdc {

private Evaluable p2 = NAN;

private final double droop;
private double droop = Double.NaN;

private final double p0;
private double p0 = Double.NaN;

private LfVscConverterStation converterStation1;

private LfVscConverterStation converterStation2;

public LfHvdcImpl(String id, LfBus bus1, LfBus bus2, LfNetwork network, HvdcAngleDroopActivePowerControl control) {
private boolean acEmulation;

public LfHvdcImpl(String id, LfBus bus1, LfBus bus2, LfNetwork network, HvdcAngleDroopActivePowerControl control,
boolean acEmulation) {
super(network);
this.id = Objects.requireNonNull(id);
this.bus1 = bus1;
this.bus2 = bus2;
Objects.requireNonNull(control);
droop = control.getDroop();
p0 = control.getP0();
this.acEmulation = acEmulation && control != null && control.isEnabled();
if (this.acEmulation) {
droop = control.getDroop();
p0 = control.getP0();
}
}

@Override
Expand All @@ -68,6 +73,21 @@ public LfBus getBus2() {
return this.bus2;
}

@Override
public LfBus getOtherBus(LfBus bus) {
return bus.equals(bus1) ? bus2 : bus1;
}

@Override
public void setDisabled(boolean disabled) {
super.setDisabled(disabled); // for AC emulation equations only.
if (!acEmulation && !disabled) {
// re-active power transmission to initial target values.
converterStation1.setTargetP(converterStation1.getInitialTargetP());
converterStation2.setTargetP(converterStation2.getInitialTargetP());
}
}

@Override
public void setP1(Evaluable p1) {
this.p1 = Objects.requireNonNull(p1);
Expand Down Expand Up @@ -98,6 +118,16 @@ public double getP0() {
return p0 / PerUnit.SB;
}

@Override
public boolean isAcEmulation() {
return acEmulation;
}

@Override
public void setAcEmulation(boolean acEmulation) {
this.acEmulation = acEmulation;
}

@Override
public LfVscConverterStation getConverterStation1() {
return converterStation1;
Expand All @@ -122,7 +152,9 @@ public void setConverterStation2(LfVscConverterStation converterStation2) {

@Override
public void updateState() {
((LfVscConverterStationImpl) converterStation1).getStation().getTerminal().setP(p1.eval() * PerUnit.SB);
((LfVscConverterStationImpl) converterStation2).getStation().getTerminal().setP(p2.eval() * PerUnit.SB);
if (acEmulation) {
((LfVscConverterStationImpl) converterStation1).getStation().getTerminal().setP(p1.eval() * PerUnit.SB);
((LfVscConverterStationImpl) converterStation2).getStation().getTerminal().setP(p2.eval() * PerUnit.SB);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -482,23 +482,19 @@ private static void createBranches(List<LfBus> lfBuses, LfNetwork lfNetwork, LfT
}
}

if (parameters.isHvdcAcEmulation()) {
for (HvdcLine hvdcLine : loadingContext.hvdcLineSet) {
HvdcAngleDroopActivePowerControl control = hvdcLine.getExtension(HvdcAngleDroopActivePowerControl.class);
if (control != null && control.isEnabled()) {
LfBus lfBus1 = getLfBus(hvdcLine.getConverterStation1().getTerminal(), lfNetwork, parameters.isBreakers());
LfBus lfBus2 = getLfBus(hvdcLine.getConverterStation2().getTerminal(), lfNetwork, parameters.isBreakers());
LfVscConverterStationImpl cs1 = (LfVscConverterStationImpl) lfNetwork.getGeneratorById(hvdcLine.getConverterStation1().getId());
LfVscConverterStationImpl cs2 = (LfVscConverterStationImpl) lfNetwork.getGeneratorById(hvdcLine.getConverterStation2().getId());
if (cs1 != null && cs2 != null) {
LfHvdc lfHvdc = new LfHvdcImpl(hvdcLine.getId(), lfBus1, lfBus2, lfNetwork, control);
lfHvdc.setConverterStation1((LfVscConverterStationImpl) lfNetwork.getGeneratorById(hvdcLine.getConverterStation1().getId()));
lfHvdc.setConverterStation2((LfVscConverterStationImpl) lfNetwork.getGeneratorById(hvdcLine.getConverterStation2().getId()));
lfNetwork.addHvdc(lfHvdc);
} else {
LOGGER.warn("Hvdc line '{}' in AC emulation but converter stations are not in the same synchronous component: operated using active set point.", hvdcLine.getId());
}
}
for (HvdcLine hvdcLine : loadingContext.hvdcLineSet) {
LfBus lfBus1 = getLfBus(hvdcLine.getConverterStation1().getTerminal(), lfNetwork, parameters.isBreakers());
LfBus lfBus2 = getLfBus(hvdcLine.getConverterStation2().getTerminal(), lfNetwork, parameters.isBreakers());
LfVscConverterStationImpl cs1 = (LfVscConverterStationImpl) lfNetwork.getGeneratorById(hvdcLine.getConverterStation1().getId());
LfVscConverterStationImpl cs2 = (LfVscConverterStationImpl) lfNetwork.getGeneratorById(hvdcLine.getConverterStation2().getId());
HvdcAngleDroopActivePowerControl control = hvdcLine.getExtension(HvdcAngleDroopActivePowerControl.class);
if (cs1 != null && cs2 != null) {
LfHvdc lfHvdc = new LfHvdcImpl(hvdcLine.getId(), lfBus1, lfBus2, lfNetwork, control, parameters.isHvdcAcEmulation());
lfHvdc.setConverterStation1(cs1);
lfHvdc.setConverterStation2(cs2);
lfNetwork.addHvdc(lfHvdc);
} else {
LOGGER.warn("The converter stations of hvdc line {} are not in the same synchronous component: no hvdc link created to model active power flow.", hvdcLine.getId());
}
}
}
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 @@ -25,10 +31,13 @@ public class LfVscConverterStationImpl extends AbstractLfGenerator implements Lf

private final double lossFactor;

private LfHvdc hvdc; // set only when AC emulation is activated
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.isDisabled()) ? 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 @@ -96,8 +110,8 @@ public void updateState(LfNetworkStateUpdateParameters parameters) {
var station = getStation();
station.getTerminal()
.setQ(Double.isNaN(calculatedQ) ? -station.getReactivePowerSetpoint() : -calculatedQ * PerUnit.SB);
if (hvdc == null) { // because when AC emulation is activated, update of p is done in LFHvdcImpl
station.getTerminal().setP(-targetP * PerUnit.SB);
if (hvdc == null || !hvdc.isAcEmulation()) { // because when AC emulation is activated, update of p is done in LFHvdcImpl
station.getTerminal().setP(-getTargetP() * PerUnit.SB);
}
}
}
Loading