Skip to content

Commit

Permalink
Fix zero impedance subgraph (#718)
Browse files Browse the repository at this point in the history
Signed-off-by: Geoffroy Jamgotchian <geoffroy.jamgotchian@gmail.com>
  • Loading branch information
geofjamg authored Mar 31, 2023
1 parent 52ee46b commit cd1136b
Show file tree
Hide file tree
Showing 31 changed files with 1,097 additions and 495 deletions.
14 changes: 5 additions & 9 deletions src/main/java/com/powsybl/openloadflow/OpenLoadFlowProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,12 @@
import com.powsybl.openloadflow.dc.DcLoadFlowResult;
import com.powsybl.openloadflow.graph.EvenShiloachGraphDecrementalConnectivityFactory;
import com.powsybl.openloadflow.graph.GraphConnectivityFactory;
import com.powsybl.openloadflow.network.LfBranch;
import com.powsybl.openloadflow.network.LfBus;
import com.powsybl.openloadflow.network.LfNetwork;
import com.powsybl.openloadflow.network.LfNetworkStateUpdateParameters;
import com.powsybl.openloadflow.network.*;
import com.powsybl.openloadflow.network.impl.LfNetworkLoaderImpl;
import com.powsybl.openloadflow.network.impl.Networks;
import com.powsybl.openloadflow.network.util.ZeroImpedanceFlows;
import com.powsybl.openloadflow.util.*;
import com.powsybl.tools.PowsyblCoreVersion;
import org.jgrapht.Graph;
import org.jgrapht.alg.interfaces.SpanningTreeAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -161,9 +156,10 @@ private LoadFlowResult runAc(Network network, LoadFlowParameters parameters, Ope
}

private void computeZeroImpedanceFlows(LfNetwork network, boolean dc) {
Graph<LfBus, LfBranch> zeroImpedanceSubGraph = network.getZeroImpedanceNetwork(dc).getSubGraph();
SpanningTreeAlgorithm.SpanningTree<LfBranch> spanningTree = network.getZeroImpedanceNetwork(dc).getSpanningTree();
new ZeroImpedanceFlows(zeroImpedanceSubGraph, spanningTree, dc).compute();
for (LfZeroImpedanceNetwork zeroImpedanceNetwork : network.getZeroImpedanceNetworks(dc)) {
new ZeroImpedanceFlows(zeroImpedanceNetwork.getGraph(), zeroImpedanceNetwork.getSpanningTree(), dc)
.compute();
}
}

private LoadFlowResult runDc(Network network, LoadFlowParameters parameters, OpenLoadFlowParameters parametersExt, Reporter reporter) {
Expand Down
20 changes: 4 additions & 16 deletions src/main/java/com/powsybl/openloadflow/ac/AcTargetVector.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import com.powsybl.openloadflow.network.*;

import java.util.Objects;
import java.util.Optional;

/**
* @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
Expand All @@ -24,11 +23,9 @@ public class AcTargetVector extends TargetVector<AcVariableType, AcEquationType>

private static double getBusTargetV(LfBus bus) {
Objects.requireNonNull(bus);
double targetV = bus.getShuntVoltageControl().filter(dvc -> bus.isShuntVoltageControlled())
.map(ShuntVoltageControl::getTargetValue)
.orElse(bus.getTransformerVoltageControl().filter(dvc -> bus.isTransformerVoltageControlled())
.map(TransformerVoltageControl::getTargetValue)
.orElse(getVoltageControlledTargetValue(bus).orElse(Double.NaN)));
double targetV = bus.getHighestPriorityVoltageControl()
.map(Control::getTargetValue)
.orElseThrow(() -> new IllegalStateException("No active voltage control has been found for bus '" + bus.getId() + "'"));
if (bus.hasGeneratorsWithSlope()) {
// take first generator with slope: network loading ensures that there's only one generator with slope
double slope = bus.getGeneratorsControllingVoltageWithSlope().get(0).getSlope();
Expand All @@ -37,19 +34,10 @@ private static double getBusTargetV(LfBus bus) {
return targetV;
}

private static Optional<Double> getVoltageControlledTargetValue(LfBus bus) {
return bus.getGeneratorVoltageControl().filter(vc -> bus.isGeneratorVoltageControlled()).map(vc -> {
if (vc.getControllerElements().stream().noneMatch(LfBus::isGeneratorVoltageControlEnabled)) {
throw new IllegalStateException("None of the controller buses of bus '" + bus.getId() + "'has voltage control on");
}
return vc.getTargetValue();
});
}

private static double getReactivePowerDistributionTarget(LfNetwork network, int busNum) {
LfBus controllerBus = network.getBus(busNum);
double target = (controllerBus.getRemoteVoltageControlReactivePercent() - 1) * controllerBus.getTargetQ();
for (LfBus otherControllerBus : controllerBus.getGeneratorVoltageControl().orElseThrow().getControllerElements()) {
for (LfBus otherControllerBus : controllerBus.getGeneratorVoltageControl().orElseThrow().getMergedControllerElements()) {
if (otherControllerBus != controllerBus) {
target += controllerBus.getRemoteVoltageControlReactivePercent() * otherControllerBus.getTargetQ();
}
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,31 @@
import com.powsybl.openloadflow.lf.AbstractEquationSystemUpdater;
import com.powsybl.openloadflow.network.*;

import java.util.List;
import java.util.Objects;

/**
* @author Geoffroy Jamgotchian <geoffroy.jamgotchian at rte-france.com>
*/
public class AcEquationSystemUpdater extends AbstractEquationSystemUpdater<AcVariableType, AcEquationType> {

public AcEquationSystemUpdater(EquationSystem<AcVariableType, AcEquationType> equationSystem) {
private final AcEquationSystemCreationParameters parameters;

public AcEquationSystemUpdater(EquationSystem<AcVariableType, AcEquationType> equationSystem,
AcEquationSystemCreationParameters parameters) {
super(equationSystem, false);
this.parameters = Objects.requireNonNull(parameters);
}

private void updateVoltageControls(LfBus bus) {
bus.getGeneratorVoltageControl().ifPresent(voltageControl -> AcEquationSystemCreator.updateGeneratorVoltageControl(voltageControl.getMainVoltageControl(), equationSystem));
bus.getTransformerVoltageControl().ifPresent(voltageControl -> AcEquationSystemCreator.updateTransformerVoltageControlEquations(voltageControl.getMainVoltageControl(), equationSystem));
bus.getShuntVoltageControl().ifPresent(voltageControl -> AcEquationSystemCreator.updateShuntVoltageControlEquations(voltageControl.getMainVoltageControl(), equationSystem));
}

@Override
public void onGeneratorVoltageControlChange(LfBus controllerBus, boolean newVoltageControllerEnabled) {
controllerBus.getGeneratorVoltageControl().ifPresent(voltageControl -> AcEquationSystemCreator.updateGeneratorVoltageControl(voltageControl, equationSystem));
updateVoltageControls(controllerBus.getGeneratorVoltageControl().orElseThrow().getControlledBus());
controllerBus.getReactivePowerControl().ifPresent(reactivePowerControl -> AcEquationSystemCreator.updateReactivePowerControlBranchEquations(reactivePowerControl, equationSystem));
}

Expand All @@ -32,12 +45,12 @@ public void onTransformerPhaseControlChange(LfBranch controllerBranch, boolean n

@Override
public void onTransformerVoltageControlChange(LfBranch controllerBranch, boolean newVoltageControllerEnabled) {
AcEquationSystemCreator.updateTransformerVoltageControlEquations(controllerBranch.getVoltageControl().orElseThrow(), equationSystem);
updateVoltageControls(controllerBranch.getVoltageControl().orElseThrow().getControlledBus());
}

@Override
public void onShuntVoltageControlChange(LfShunt controllerShunt, boolean newVoltageControllerEnabled) {
AcEquationSystemCreator.updateShuntVoltageControlEquations(controllerShunt.getVoltageControl().orElseThrow(), equationSystem);
updateVoltageControls(controllerShunt.getVoltageControl().orElseThrow().getControlledBus());
}

@Override
Expand Down Expand Up @@ -74,9 +87,7 @@ public void onDisableChange(LfElement element, boolean disabled) {
equationSystem.getEquation(bus.getNum(), AcEquationType.BUS_TARGET_V)
.orElseThrow()
.setActive(false);
bus.getGeneratorVoltageControl().ifPresent(voltageControl -> AcEquationSystemCreator.updateGeneratorVoltageControl(voltageControl, equationSystem));
bus.getTransformerVoltageControl().ifPresent(voltageControl -> AcEquationSystemCreator.updateTransformerVoltageControlEquations(voltageControl, equationSystem));
bus.getShuntVoltageControl().ifPresent(voltageControl -> AcEquationSystemCreator.updateShuntVoltageControlEquations(voltageControl, equationSystem));
updateVoltageControls(bus);
bus.getReactivePowerControl().ifPresent(reactivePowerControl -> AcEquationSystemCreator.updateReactivePowerControlBranchEquations(reactivePowerControl, equationSystem));
break;
case BRANCH:
Expand All @@ -96,4 +107,41 @@ public void onDisableChange(LfElement element, boolean disabled) {
throw new IllegalStateException("Unknown element type: " + element.getType());
}
}

private void recreateDistributionEquations(LfZeroImpedanceNetwork network) {
for (LfBus bus : network.getGraph().vertexSet()) {
bus.getGeneratorVoltageControl()
.filter(voltageControl -> voltageControl.getMergeStatus() == VoltageControl.MergeStatus.MAIN)
.ifPresent(voltageControl -> AcEquationSystemCreator.recreateReactivePowerDistributionEquations(voltageControl, equationSystem, parameters));
bus.getTransformerVoltageControl()
.filter(voltageControl -> voltageControl.getMergeStatus() == VoltageControl.MergeStatus.MAIN)
.ifPresent(voltageControl -> AcEquationSystemCreator.recreateR1DistributionEquations(voltageControl, equationSystem));
bus.getShuntVoltageControl()
.filter(voltageControl -> voltageControl.getMergeStatus() == VoltageControl.MergeStatus.MAIN)
.ifPresent(voltageControl -> AcEquationSystemCreator.recreateShuntSusceptanceDistributionEquations(voltageControl, equationSystem));
}
}

@Override
public void onZeroImpedanceNetworkSplit(LfZeroImpedanceNetwork initialNetwork, List<LfZeroImpedanceNetwork> splitNetworks, boolean dc) {
if (!dc) {
// TODO
// only recreate distribution equations if controllers buses are redistributed on the different
// split networks (should be a rare case) and not only ate the end on only one of the split network
for (LfZeroImpedanceNetwork splitNetwork : splitNetworks) {
recreateDistributionEquations(splitNetwork);
}
}
}

@Override
public void onZeroImpedanceNetworkMerge(LfZeroImpedanceNetwork network1, LfZeroImpedanceNetwork network2, LfZeroImpedanceNetwork mergedNetwork, boolean dc) {
if (!dc) {
// TODO
// only recreate distribution equations if controllers buses are merged (should be a rare case)
// so we have to check here that controllers were spread over network1 and network2 and were not
// already only on network1 or network2
recreateDistributionEquations(mergedNetwork);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,14 @@ public OuterLoopStatus check(OuterLoopContext context, Reporter reporter) {
.filter(LfBus::isShuntVoltageControlled)
.forEach(controlledBus -> {
ShuntVoltageControl voltageControl = controlledBus.getShuntVoltageControl().orElseThrow();
double diffV = voltageControl.getTargetValue() - voltageControl.getControlledBus().getV();
List<LfShunt> sortedControllers = voltageControl.getControllerElements().stream()
.filter(shunt -> !shunt.isDisabled() && shunt.hasVoltageControlCapability())
.sorted(Comparator.comparingDouble(LfShunt::getBMagnitude).reversed())
.collect(Collectors.toList());
adjustB(voltageControl, sortedControllers, controlledBus, contextData, sensitivityContext, diffV, status);
if (voltageControl.getMergeStatus() == VoltageControl.MergeStatus.MAIN) {
double diffV = voltageControl.getTargetValue() - voltageControl.getControlledBus().getV();
List<LfShunt> sortedControllers = voltageControl.getMergedControllerElements().stream()
.filter(shunt -> !shunt.isDisabled() && shunt.hasVoltageControlCapability())
.sorted(Comparator.comparingDouble(LfShunt::getBMagnitude).reversed())
.collect(Collectors.toList());
adjustB(voltageControl, sortedControllers, controlledBus, contextData, sensitivityContext, diffV, status);
}
});
return status.getValue();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,22 +208,24 @@ public OuterLoopStatus check(OuterLoopContext context, Reporter reporter) {

controlledBuses.forEach(controlledBus -> {
TransformerVoltageControl voltageControl = controlledBus.getTransformerVoltageControl().orElseThrow();
double diffV = getDiffV(voltageControl);
double halfTargetDeadband = getHalfTargetDeadband(voltageControl);
if (Math.abs(diffV) > halfTargetDeadband) {
controlledBusesOutsideOfDeadband.add(controlledBus.getId());
List<LfBranch> controllers = voltageControl.getControllerElements();
LOGGER.trace("Controlled bus '{}' ({} controllers) is outside of its deadband (half is {} kV) and could need a voltage adjustment of {} kV",
controlledBus.getId(), controllers.size(), halfTargetDeadband * controlledBus.getNominalV(), diffV * controlledBus.getNominalV());
boolean adjusted;
if (controllers.size() == 1) {
adjusted = adjustWithOneController(controllers.get(0), controlledBus, contextData, sensitivityContext, diffV, controlledBusesWithAllItsControllersToLimit);
} else {
adjusted = adjustWithSeveralControllers(controllers, controlledBus, contextData, sensitivityContext, diffV, halfTargetDeadband, controlledBusesWithAllItsControllersToLimit);
}
if (adjusted) {
controlledBusesAdjusted.add(controlledBus.getId());
status.setValue(OuterLoopStatus.UNSTABLE);
if (voltageControl.getMergeStatus() == VoltageControl.MergeStatus.MAIN) {
double diffV = getDiffV(voltageControl);
double halfTargetDeadband = getHalfTargetDeadband(voltageControl);
if (Math.abs(diffV) > halfTargetDeadband) {
controlledBusesOutsideOfDeadband.add(controlledBus.getId());
List<LfBranch> controllers = voltageControl.getMergedControllerElements();
LOGGER.trace("Controlled bus '{}' ({} controllers) is outside of its deadband (half is {} kV) and could need a voltage adjustment of {} kV",
controlledBus.getId(), controllers.size(), halfTargetDeadband * controlledBus.getNominalV(), diffV * controlledBus.getNominalV());
boolean adjusted;
if (controllers.size() == 1) {
adjusted = adjustWithOneController(controllers.get(0), controlledBus, contextData, sensitivityContext, diffV, controlledBusesWithAllItsControllersToLimit);
} else {
adjusted = adjustWithSeveralControllers(controllers, controlledBus, contextData, sensitivityContext, diffV, halfTargetDeadband, controlledBusesWithAllItsControllersToLimit);
}
if (adjusted) {
controlledBusesAdjusted.add(controlledBus.getId());
status.setValue(OuterLoopStatus.UNSTABLE);
}
}
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
import com.powsybl.openloadflow.ac.OuterLoop;
import com.powsybl.openloadflow.ac.OuterLoopContext;
import com.powsybl.openloadflow.ac.OuterLoopStatus;
import com.powsybl.openloadflow.network.LfBus;
import com.powsybl.openloadflow.network.GeneratorVoltageControl;
import com.powsybl.openloadflow.network.LfBus;
import com.powsybl.openloadflow.util.PerUnit;
import com.powsybl.openloadflow.util.Reports;
import org.apache.commons.lang3.mutable.MutableInt;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ private static boolean isValid(LfBus bus) {

private static List<LfBus> getControllerBuses(LfBus controlledBus) {
return controlledBus.getGeneratorVoltageControl()
.filter(voltageControl -> voltageControl.getMergeStatus() == VoltageControl.MergeStatus.MAIN)
.orElseThrow()
.getControllerElements()
.getMergedControllerElements()
.stream().filter(SecondaryVoltageControlOuterLoop::isValid)
.collect(Collectors.toList());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.powsybl.openloadflow.ac.OuterLoopStatus;
import com.powsybl.openloadflow.network.LfBranch;
import com.powsybl.openloadflow.network.LfBus;
import com.powsybl.openloadflow.network.VoltageControl;
import org.apache.commons.lang3.mutable.MutableObject;

import java.util.ArrayList;
Expand Down Expand Up @@ -79,14 +80,16 @@ public OuterLoopStatus check(OuterLoopContext context, Reporter reporter) {
for (LfBus bus : context.getNetwork().getBuses()) {
if (!bus.isDisabled() && bus.isGeneratorVoltageControlled() && bus.getNominalV() <= maxControlledNominalVoltage) {
var voltageControl = bus.getGeneratorVoltageControl().orElseThrow();
voltageControl.getControllerElements().forEach(controllerBus -> {
if (controllerBus.isGeneratorVoltageControlEnabled()) {
controllerBus.setGenerationTargetQ(controllerBus.getQ().eval());
controllerBus.setGeneratorVoltageControlEnabled(false);
contextData.getBusesWithVoltageControlDisabled().add(controllerBus);
}
});
status.setValue(OuterLoopStatus.UNSTABLE);
if (voltageControl.getMergeStatus() == VoltageControl.MergeStatus.MAIN) {
voltageControl.getMergedControllerElements().forEach(controllerBus -> {
if (controllerBus.isGeneratorVoltageControlEnabled()) {
controllerBus.setGenerationTargetQ(controllerBus.getQ().eval());
controllerBus.setGeneratorVoltageControlEnabled(false);
contextData.getBusesWithVoltageControlDisabled().add(controllerBus);
}
});
status.setValue(OuterLoopStatus.UNSTABLE);
}
}
}
for (LfBranch branch : getControllerBranches(context.getNetwork())) {
Expand Down
Loading

0 comments on commit cd1136b

Please sign in to comment.