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

Contingency refactoring #493

Merged
merged 45 commits into from
Jun 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
8f5b8d5
Refactor contingency application.
annetill Apr 5, 2022
31bdb33
Remove dependancy to IIDM network.
annetill Apr 5, 2022
2865304
Simplify.
annetill Apr 5, 2022
576d416
Add tests.
annetill Apr 5, 2022
b54a5f8
Remove useless code.
annetill Apr 5, 2022
289fb6b
Hvdc Ac emulation not supported yet.
annetill Apr 5, 2022
4cdc0aa
Add a unit test and clean code.
annetill Apr 5, 2022
6a0ced1
Start support of other contingencies for AC sensitivity analysis.
annetill Apr 5, 2022
94f0b06
Load and generator contingency support for AC sensitivity analysis.
annetill Apr 5, 2022
250d6bf
Merge.
annetill Apr 7, 2022
898779a
Small fixes after merge.
annetill Apr 7, 2022
4cd030d
Try to fix GLSK.
annetill Apr 8, 2022
62cdf98
Fix bug.
annetill Apr 8, 2022
7611b6b
Merge.
annetill Apr 8, 2022
4fe7423
Merge.
annetill Apr 10, 2022
494aeed
Save work.
annetill Apr 11, 2022
932e746
Fix checkstyle.
annetill Apr 11, 2022
596b85f
Refactoring.
annetill Apr 11, 2022
f6f86ab
Merge.
annetill Apr 13, 2022
2c0300b
Clarify.
annetill Apr 13, 2022
894c441
Merge branch 'main' into hvdc-contingency-refactoring
annetill Apr 14, 2022
b60a6ca
Fix bug.
annetill Apr 14, 2022
f232df7
Merge.
annetill Apr 21, 2022
bf3880b
Merge branch 'main' into hvdc-contingency-refactoring
annetill May 9, 2022
4fa8542
Merge.
annetill May 13, 2022
1dd1bc6
Merge branch 'main' into hvdc-contingency-refactoring
annetill May 16, 2022
dde2c31
Merge branch 'main' into hvdc-contingency-refactoring
annetill May 17, 2022
128f7c0
Merge branch 'main' into hvdc-contingency-refactoring
annetill May 18, 2022
8822df9
Support of a contingency with an HVDC in AC emulation.
annetill May 19, 2022
b8fac53
Add test for AC sensitivity analysis.
annetill May 19, 2022
8f02c7d
Add a unit test.
annetill May 25, 2022
6cfe4b1
Add unit test and clean.
annetill May 25, 2022
8a34d3c
Fix and factorize the case where a disabled line is the function of a…
Hadrien-Godard May 25, 2022
b9e84c5
New test
Hadrien-Godard May 25, 2022
770757d
Fix isElementConnectedToComponent removing disabled lines from compon…
Hadrien-Godard May 27, 2022
2272d5c
Revert "Fix isElementConnectedToComponent removing disabled lines fro…
annetill May 30, 2022
f1c4a3b
Revert "New test"
annetill May 30, 2022
522b3ed
Merge.
annetill May 30, 2022
d27724f
Refactoring.
annetill May 30, 2022
1758b1d
Merge branch 'main' into hvdc-contingency-refactoring
annetill Jun 1, 2022
37a9594
Squashed commit of the following:
geofjamg Jun 1, 2022
6f8c934
Clean
geofjamg Jun 1, 2022
e557675
Merge branch 'main' into hvdc-contingency-refactoring
geofjamg Jun 2, 2022
7f4f07b
Apply review comments.
annetill Jun 2, 2022
2b0ca27
Merge branch 'hvdc-contingency-refactoring' of https://github.com/pow…
annetill Jun 2, 2022
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 @@ -113,6 +113,9 @@ public void onDisableChange(LfElement element, boolean disabled) {
LfShunt shunt = (LfShunt) element;
shunt.getVoltageControl().ifPresent(voltageControl -> AcEquationSystem.updateShuntVoltageControlEquations(voltageControl, equationSystem));
break;
case HVDC:
// nothing to do
break;
default:
throw new IllegalStateException("Unknown element type: " + element.getType());
}
Expand Down
56 changes: 39 additions & 17 deletions src/main/java/com/powsybl/openloadflow/network/LfContingency.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@
import java.io.IOException;
import java.io.UncheckedIOException;
import java.io.Writer;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.*;

/**
* @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
Expand All @@ -32,30 +29,33 @@ public class LfContingency {

private final Set<LfBranch> disabledBranches;

private final Set<LfHvdc> disabledHvdcs;

private final Map<LfShunt, Double> shuntsShift;

private final Map<LfBus, PowerShift> busesLoadShift;

private final Set<LfGenerator> generators;
private final Set<LfGenerator> lostGenerators;

private double activePowerLoss = 0;

public LfContingency(String id, int index, Set<LfBus> disabledBuses, Set<LfBranch> disabledBranches, Map<LfShunt, Double> shuntsShift,
Map<LfBus, PowerShift> busesLoadShift, Set<LfGenerator> generators) {
Map<LfBus, PowerShift> busesLoadShift, Set<LfGenerator> lostGenerators, Set<LfHvdc> disabledHvdcs) {
this.id = Objects.requireNonNull(id);
this.index = index;
this.disabledBuses = Objects.requireNonNull(disabledBuses);
this.disabledBranches = Objects.requireNonNull(disabledBranches);
this.disabledHvdcs = Objects.requireNonNull(disabledHvdcs);
this.shuntsShift = Objects.requireNonNull(shuntsShift);
this.busesLoadShift = Objects.requireNonNull(busesLoadShift);
this.generators = Objects.requireNonNull(generators);
this.lostGenerators = Objects.requireNonNull(lostGenerators);
for (LfBus bus : disabledBuses) {
activePowerLoss += bus.getGenerationTargetP() - bus.getLoadTargetP();
}
for (Map.Entry<LfBus, PowerShift> e : busesLoadShift.entrySet()) {
activePowerLoss -= e.getValue().getActive();
}
for (LfGenerator generator : generators) {
for (LfGenerator generator : lostGenerators) {
activePowerLoss += generator.getTargetP();
}
}
Expand Down Expand Up @@ -84,18 +84,21 @@ public Map<LfBus, PowerShift> getBusesLoadShift() {
return busesLoadShift;
}

public Set<LfGenerator> getGenerators() {
return generators;
public Set<LfGenerator> getLostGenerators() {
return lostGenerators;
}

public double getActivePowerLoss() {
return activePowerLoss;
}

public void apply(LoadFlowParameters parameters) {
public void apply(LoadFlowParameters.BalanceType balanceType) {
for (LfBranch branch : disabledBranches) {
branch.setDisabled(true);
}
for (LfHvdc hvdc : disabledHvdcs) {
hvdc.setDisabled(true);
}
for (LfBus bus : disabledBuses) {
bus.setDisabled(true);
}
Expand All @@ -106,12 +109,12 @@ public void apply(LoadFlowParameters parameters) {
for (var e : busesLoadShift.entrySet()) {
LfBus bus = e.getKey();
PowerShift shift = e.getValue();
bus.setLoadTargetP(bus.getLoadTargetP() - getUpdatedLoadP0(bus, parameters.getBalanceType(), shift.getActive(), shift.getVariableActive()));
bus.setLoadTargetP(bus.getLoadTargetP() - getUpdatedLoadP0(bus, balanceType, shift.getActive(), shift.getVariableActive()));
bus.setLoadTargetQ(bus.getLoadTargetQ() - shift.getReactive());
bus.getLoads().setAbsVariableLoadTargetP(bus.getLoads().getAbsVariableLoadTargetP() - Math.abs(shift.getVariableActive()) * PerUnit.SB);
}
Set<LfBus> generatorBuses = new HashSet<>();
for (LfGenerator generator : generators) {
for (LfGenerator generator : lostGenerators) {
generator.setTargetP(0);
LfBus bus = generator.getBus();
generatorBuses.add(bus);
Expand All @@ -131,14 +134,33 @@ public void apply(LoadFlowParameters parameters) {

public static double getUpdatedLoadP0(LfBus bus, LoadFlowParameters.BalanceType balanceType, double initialP0, double initialVariableActivePower) {
double factor = 0.0;
if (balanceType == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_LOAD) {
factor = Math.abs(initialP0) / (bus.getLoads().getAbsVariableLoadTargetP() / PerUnit.SB);
} else if (balanceType == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD) {
factor = initialVariableActivePower / (bus.getLoads().getAbsVariableLoadTargetP() / PerUnit.SB);
if (bus.getLoads().getLoadCount() > 0) {
if (balanceType == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_LOAD) {
factor = Math.abs(initialP0) / (bus.getLoads().getAbsVariableLoadTargetP() / PerUnit.SB);
} else if (balanceType == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD) {
factor = initialVariableActivePower / (bus.getLoads().getAbsVariableLoadTargetP() / PerUnit.SB);
}
}
return initialP0 + (bus.getLoadTargetP() - bus.getInitialLoadTargetP()) * factor;
}

public Set<LfBus> getLoadAndGeneratorBuses() {
Set<LfBus> buses = new HashSet<>();
for (var e : busesLoadShift.entrySet()) {
LfBus bus = e.getKey();
if (bus != null) {
buses.add(bus);
}
}
for (LfGenerator generator : lostGenerators) {
LfBus bus = generator.getBus();
if (bus != null) {
buses.add(bus);
}
}
return buses;
}

public void writeJson(Writer writer) {
Objects.requireNonNull(writer);
try (JsonGenerator jsonGenerator = new JsonFactory()
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/com/powsybl/openloadflow/network/LfNetwork.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ public class LfNetwork extends AbstractPropertyBag implements PropertyBag {

private final List<LfHvdc> hvdcs = new ArrayList<>();

private final Map<String, LfHvdc> hvdcsById = new HashMap<>();

private final List<LfNetworkListener> listeners = new ArrayList<>();

private boolean valid = true;
Expand Down Expand Up @@ -198,6 +200,7 @@ public void addHvdc(LfHvdc hvdc) {
Objects.requireNonNull(hvdc);
hvdc.setNum(hvdcs.size());
hvdcs.add(hvdc);
hvdcsById.put(hvdc.getId(), hvdc);

// create bus -> branches link
if (hvdc.getBus1() != null) {
Expand All @@ -212,6 +215,11 @@ public List<LfHvdc> getHvdcs() {
return hvdcs;
}

public LfHvdc getHvdcById(String id) {
Objects.requireNonNull(id);
return hvdcsById.get(id);
}

public void updateState(boolean reactiveLimits, boolean writeSlackBus, boolean phaseShifterRegulationOn,
boolean transformerVoltageControlOn, boolean distributedOnConformLoad, boolean loadPowerFactorConstant,
boolean dc) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.powsybl.contingency.Contingency;
import com.powsybl.contingency.ContingencyElement;
import com.powsybl.iidm.network.*;
import com.powsybl.iidm.network.extensions.HvdcAngleDroopActivePowerControl;
import com.powsybl.iidm.network.extensions.LoadDetail;
import com.powsybl.openloadflow.graph.GraphDecrementalConnectivity;
import com.powsybl.openloadflow.network.*;
Expand All @@ -36,7 +37,7 @@ public class PropagatedContingency {

private final Set<Switch> switchesToOpen;

private final Set<String> hvdcIdsToOpen;
private final Set<String> hvdcIdsToOpen; // for HVDC in AC emulation

private final Set<String> generatorIdsToLose;

Expand Down Expand Up @@ -108,11 +109,11 @@ private static PowerShift getLoadPowerShift(Load load, boolean slackDistribution
}

public static List<PropagatedContingency> createListForSensitivityAnalysis(Network network, List<Contingency> contingencies,
boolean slackDistributionOnConformLoad) {
boolean slackDistributionOnConformLoad, boolean hvdcAcEmulation) {
List<PropagatedContingency> propagatedContingencies = new ArrayList<>();
for (int index = 0; index < contingencies.size(); index++) {
Contingency contingency = contingencies.get(index);
PropagatedContingency propagatedContingency = PropagatedContingency.create(network, contingency, index, false, false, slackDistributionOnConformLoad);
PropagatedContingency propagatedContingency = PropagatedContingency.create(network, contingency, index, false, false, slackDistributionOnConformLoad, hvdcAcEmulation);
Optional<Switch> coupler = propagatedContingency.switchesToOpen.stream().filter(PropagatedContingency::isCoupler).findFirst();
if (coupler.isEmpty()) {
propagatedContingencies.add(propagatedContingency);
Expand All @@ -127,24 +128,26 @@ public static List<PropagatedContingency> createListForSensitivityAnalysis(Netwo

public static List<PropagatedContingency> createListForSecurityAnalysis(Network network, List<Contingency> contingencies,
Set<Switch> allSwitchesToOpen, boolean shuntCompensatorVoltageControlOn,
boolean slackDistributionOnConformLoad) {
boolean slackDistributionOnConformLoad, boolean hvdcAcEmulation) {
List<PropagatedContingency> propagatedContingencies = new ArrayList<>();
for (int index = 0; index < contingencies.size(); index++) {
Contingency contingency = contingencies.get(index);
PropagatedContingency propagatedContingency =
PropagatedContingency.create(network, contingency, index, shuntCompensatorVoltageControlOn, true, slackDistributionOnConformLoad);
PropagatedContingency.create(network, contingency, index, shuntCompensatorVoltageControlOn, true, slackDistributionOnConformLoad, hvdcAcEmulation);
propagatedContingencies.add(propagatedContingency);
allSwitchesToOpen.addAll(propagatedContingency.switchesToOpen);
}
return propagatedContingencies;
}

private static PropagatedContingency create(Network network, Contingency contingency, int index, boolean shuntCompensatorVoltageControlOn,
boolean withBreakers, boolean slackDistributionOnConformLoad) {
boolean withBreakers, boolean slackDistributionOnConformLoad, boolean hvdcAcEmulation) {
Set<Switch> switchesToOpen = new HashSet<>();
Set<Terminal> terminalsToDisconnect = new HashSet<>();
Set<String> branchIdsToOpen = new LinkedHashSet<>();
Set<String> hvdcIdsToOpen = new HashSet<>();
Set<VscConverterStation> vscsToLose = new HashSet<>();
Set<LccConverterStation> lccsToLose = new HashSet<>();
Set<Load> loadsToLose = new HashSet<>();
Set<Generator> generatorsToLose = new HashSet<>();
Set<ShuntCompensator> shuntsToLose = new HashSet<>();
Expand All @@ -164,7 +167,24 @@ private static PropagatedContingency create(Network network, Contingency conting
if (hvdcLine == null) {
throw new PowsyblException("HVDC line '" + element.getId() + "' not found in the network");
}
hvdcIdsToOpen.add(element.getId());
HvdcAngleDroopActivePowerControl control = hvdcLine.getExtension(HvdcAngleDroopActivePowerControl.class);
if (control != null && control.isEnabled() && hvdcAcEmulation) {
hvdcIdsToOpen.add(element.getId());
}
if (hvdcLine.getConverterStation1() instanceof VscConverterStation) {
VscConverterStation vsc1 = (VscConverterStation) hvdcLine.getConverterStation1();
vscsToLose.add(vsc1);
} else {
LccConverterStation lcc1 = (LccConverterStation) hvdcLine.getConverterStation1();
lccsToLose.add(lcc1);
}
if (hvdcLine.getConverterStation2() instanceof VscConverterStation) {
VscConverterStation vsc2 = (VscConverterStation) hvdcLine.getConverterStation2();
vscsToLose.add(vsc2);
} else {
LccConverterStation lcc2 = (LccConverterStation) hvdcLine.getConverterStation2();
lccsToLose.add(lcc2);
}
break;
case DANGLING_LINE:
// dangling line check is done inside tripping
Expand Down Expand Up @@ -229,6 +249,20 @@ private static PropagatedContingency create(Network network, Contingency conting
shuntsToLose.add((ShuntCompensator) connectable);
break;

case HVDC_CONVERTER_STATION:
HvdcConverterStation<?> station = (HvdcConverterStation) connectable;
HvdcAngleDroopActivePowerControl control = station.getHvdcLine().getExtension(HvdcAngleDroopActivePowerControl.class);
if (control != null && control.isEnabled() && hvdcAcEmulation) {
hvdcIdsToOpen.add(station.getHvdcLine().getId());
} else {
if (connectable instanceof VscConverterStation) {
vscsToLose.add((VscConverterStation) connectable);
} else {
lccsToLose.add((LccConverterStation) connectable);
}
}
break;

case BUSBAR_SECTION:
// we don't care
break;
Expand All @@ -246,6 +280,9 @@ private static PropagatedContingency create(Network network, Contingency conting
for (Generator generator : generatorsToLose) {
generatorIdsToLose.add(generator.getId());
}
for (VscConverterStation vsc : vscsToLose) {
generatorIdsToLose.add(vsc.getId());
}
for (Load load : loadsToLose) {
Bus bus = withBreakers ? load.getTerminal().getBusBreakerView().getBus()
: load.getTerminal().getBusView().getBus();
Expand All @@ -254,6 +291,16 @@ private static PropagatedContingency create(Network network, Contingency conting
.add(getLoadPowerShift(load, slackDistributionOnConformLoad));
}
}
for (LccConverterStation lcc : lccsToLose) {
Bus bus = withBreakers ? lcc.getTerminal().getBusBreakerView().getBus()
: lcc.getTerminal().getBusView().getBus();
if (bus != null) {
// No variable active part for a LCC.
loadIdsToShift.computeIfAbsent(bus.getId(), k -> new PowerShift())
.add(new PowerShift(HvdcConverterStations.getConverterStationTargetP(lcc) / PerUnit.SB, 0,
HvdcConverterStations.getLccConverterStationLoadTargetQ(lcc) / PerUnit.SB));
}
}
for (ShuntCompensator shunt : shuntsToLose) {
double nominalV = shunt.getTerminal().getVoltageLevel().getNominalV();
shuntIdsToShift.put(shunt.getId(), shunt.getB() * nominalV * nominalV / PerUnit.SB);
Expand Down Expand Up @@ -302,10 +349,6 @@ public Optional<LfContingency> toLfContingency(LfNetwork network, boolean useSma
// reset connectivity to discard triggered branches
connectivity.reset();

if (!hvdcIdsToOpen.isEmpty()) {
throw new UnsupportedOperationException("HVDC line contingency not supported");
}

Map<LfShunt, Double> shunts = new HashMap<>(1);
for (var e : shuntIdsToShift.entrySet()) {
LfShunt shunt = network.getShuntById(e.getKey());
Expand Down Expand Up @@ -333,14 +376,21 @@ public Optional<LfContingency> toLfContingency(LfNetwork network, boolean useSma
}
}

// find hvdc lines that are part of this network
Set<LfHvdc> hvdcs = hvdcIdsToOpen.stream()
.map(network::getHvdcById)
.filter(Objects::nonNull) // could be in another component
.collect(Collectors.toSet());

if (branches.isEmpty()
&& buses.isEmpty()
&& shunts.isEmpty()
&& busesLoadShift.isEmpty()
&& generators.isEmpty()) {
&& generators.isEmpty()
&& hvdcs.isEmpty()) {
return Optional.empty();
}

return Optional.of(new LfContingency(contingency.getId(), index, buses, branches, shunts, busesLoadShift, generators));
return Optional.of(new LfContingency(contingency.getId(), index, buses, branches, shunts, busesLoadShift, generators, hvdcs));
}
}
Loading