Skip to content

Commit

Permalink
Contingency refactoring (#493)
Browse files Browse the repository at this point in the history
Signed-off-by: Anne Tilloy <anne.tilloy@rte-france.com>
Signed-off-by: Hadrien <hadrien.godard@artelys.com>
  • Loading branch information
annetill authored Jun 2, 2022
1 parent 2a22847 commit 4e049ff
Show file tree
Hide file tree
Showing 15 changed files with 588 additions and 236 deletions.
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

0 comments on commit 4e049ff

Please sign in to comment.