From 7613da0ab4e2d8c4fa71ac9e7b5651ab5ad15591 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Fri, 5 Feb 2021 16:10:41 +0100 Subject: [PATCH 01/10] Refactor common code DcLoadFlowEngine/DcSensitivityAnalysis Signed-off-by: Florian Dupuy Signed-off-by: Gael Macherel --- .../openloadflow/dc/DcLoadFlowEngine.java | 97 ++++++++++++------- ...nShiloachGraphDecrementalConnectivity.java | 16 +++ .../graph/GraphDecrementalConnectivity.java | 2 + ...nningTreeGraphDecrementalConnectivity.java | 12 ++- .../NaiveGraphDecrementalConnectivity.java | 6 ++ .../openloadflow/network/LfNetwork.java | 19 ---- .../network/util/ActivePowerDistribution.java | 10 +- ...GenerationActionPowerDistributionStep.java | 8 +- .../util/LoadActivePowerDistributionStep.java | 7 +- .../sensi/AbstractSensitivityAnalysis.java | 2 +- .../sensi/DcSensitivityAnalysis.java | 73 +++++--------- 11 files changed, 136 insertions(+), 116 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java b/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java index 1247f27ec9..b81a020b79 100644 --- a/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java +++ b/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java @@ -10,10 +10,7 @@ import com.powsybl.math.matrix.MatrixFactory; import com.powsybl.openloadflow.dc.equations.DcEquationSystem; import com.powsybl.openloadflow.dc.equations.DcEquationSystemCreationParameters; -import com.powsybl.openloadflow.equations.EquationSystem; -import com.powsybl.openloadflow.equations.JacobianMatrix; -import com.powsybl.openloadflow.equations.UniformValueVoltageInitializer; -import com.powsybl.openloadflow.equations.VariableSet; +import com.powsybl.openloadflow.equations.*; import com.powsybl.openloadflow.network.FirstSlackBusSelector; import com.powsybl.openloadflow.network.LfBus; import com.powsybl.openloadflow.network.LfNetwork; @@ -22,10 +19,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Objects; +import java.util.*; /** * @author Geoffroy Jamgotchian @@ -38,6 +32,8 @@ public class DcLoadFlowEngine { private final DcLoadFlowParameters parameters; + private double[] dx; + public DcLoadFlowEngine(LfNetwork network, MatrixFactory matrixFactory) { this.networks = Collections.singletonList(network); parameters = new DcLoadFlowParameters(new FirstSlackBusSelector(), matrixFactory); @@ -53,52 +49,85 @@ public DcLoadFlowEngine(List networks, DcLoadFlowParameters parameter this.parameters = Objects.requireNonNull(parameters); } - private void distributeSlack(LfNetwork network) { - double mismatch = network.getActivePowerMismatch(); + protected void distributeSlack(Collection buses) { + double mismatch = getActivePowerMismatch(buses); ActivePowerDistribution activePowerDistribution = ActivePowerDistribution.create(parameters.getBalanceType(), false); - activePowerDistribution.run(network, mismatch); + activePowerDistribution.run(buses, mismatch); + } + + public static double getActivePowerMismatch(Collection buses) { + double mismatch = 0; + for (LfBus b : buses) { + mismatch += b.getGenerationTargetP() - b.getLoadTargetP(); + } + return -mismatch; } public DcLoadFlowResult run() { // only process main (largest) connected component LfNetwork network = networks.get(0); - if (parameters.isDistributedSlack()) { - distributeSlack(network); - } - DcEquationSystemCreationParameters creationParameters = new DcEquationSystemCreationParameters(parameters.isUpdateFlows(), false, parameters.isForcePhaseControlOffAndAddAngle1Var(), parameters.isUseTransformerRatio()); EquationSystem equationSystem = DcEquationSystem.create(network, new VariableSet(), creationParameters); + LoadFlowResult.ComponentResult.Status status = LoadFlowResult.ComponentResult.Status.FAILED; + try (JacobianMatrix j = new JacobianMatrix(equationSystem, parameters.getMatrixFactory())) { + + status = runWithLu(equationSystem, j, network.getBuses()); + } catch (Exception e) { + LOGGER.error("Failed to solve linear system for DC load flow", e); + } + + return new DcLoadFlowResult(network, getActivePowerMismatch(network.getBuses()), status); + } + + public LoadFlowResult.ComponentResult.Status runWithLu(EquationSystem equationSystem, JacobianMatrix j, Collection buses) { double[] x = equationSystem.createStateVector(new UniformValueVoltageInitializer()); + if (parameters.isDistributedSlack()) { + distributeSlack(buses); + } equationSystem.updateEquations(x); double[] targets = equationSystem.createTargetVector(); - try (JacobianMatrix j = new JacobianMatrix(equationSystem, parameters.getMatrixFactory())) { - double[] dx = Arrays.copyOf(targets, targets.length); - - LoadFlowResult.ComponentResult.Status status; - try { - j.solveTransposed(dx); - status = LoadFlowResult.ComponentResult.Status.CONVERGED; - } catch (Exception e) { - status = LoadFlowResult.ComponentResult.Status.FAILED; - LOGGER.error("Failed to solve linear system for DC load flow", e); - } + this.dx = Arrays.copyOf(targets, targets.length); - equationSystem.updateEquations(dx); - equationSystem.updateNetwork(dx); + // only process main (largest) connected component + LfNetwork network = networks.get(0); + if (network.getBuses().size() > buses.size()) { + // set buses injections and transformers to 0 outside the main connected component + network.getBuses().stream() + .filter(lfBus -> !buses.contains(lfBus)) + .map(lfBus -> equationSystem.getEquation(lfBus.getNum(), EquationType.BUS_P)) + .filter(Optional::isPresent) + .map(Optional::get) + .map(Equation::getColumn) + .forEach(column -> dx[column] = 0); + } - // set all calculated voltages to NaN - for (LfBus bus : network.getBuses()) { - bus.setV(Double.NaN); - } + LoadFlowResult.ComponentResult.Status status; + try { + j.solveTransposed(dx); + status = LoadFlowResult.ComponentResult.Status.CONVERGED; + } catch (Exception e) { + status = LoadFlowResult.ComponentResult.Status.FAILED; + LOGGER.error("Failed to solve linear system for DC load flow", e); + } - LOGGER.info("Dc loadflow complete (status={})", status); + equationSystem.updateEquations(dx); + equationSystem.updateNetwork(dx); - return new DcLoadFlowResult(network, network.getActivePowerMismatch(), status); + // set all calculated voltages to NaN + for (LfBus bus : network.getBuses()) { + bus.setV(Double.NaN); } + + LOGGER.info("Dc loadflow complete (status={})", status); + return status; + } + + public double[] getTargetVector() { + return dx; } } diff --git a/src/main/java/com/powsybl/openloadflow/graph/EvenShiloachGraphDecrementalConnectivity.java b/src/main/java/com/powsybl/openloadflow/graph/EvenShiloachGraphDecrementalConnectivity.java index d94a037c30..0f98407ed7 100644 --- a/src/main/java/com/powsybl/openloadflow/graph/EvenShiloachGraphDecrementalConnectivity.java +++ b/src/main/java/com/powsybl/openloadflow/graph/EvenShiloachGraphDecrementalConnectivity.java @@ -16,6 +16,7 @@ import org.slf4j.LoggerFactory; import java.util.*; +import java.util.stream.Collectors; /** * Implementing the Even-Shiloach algorithm (see https://dl.acm.org/doi/10.1145/322234.322235) @@ -142,6 +143,21 @@ public List> getSmallComponents() { return newConnectedComponents; } + @Override + public Set getConnectedComponent(V vertex) { + lazyComputeConnectivity(); + updateVertexMapCache(); + int cn = vertexToConnectedComponent.get(vertex); + if (cn >= 0) { + return cn == 0 ? getMainConnectedComponent() : newConnectedComponents.get(cn - 1); + } + return Collections.emptySet(); + } + + private Set getMainConnectedComponent() { + return vertices.stream().filter(v -> newConnectedComponents.stream().noneMatch(cc -> cc.contains(v))).collect(Collectors.toSet()); + } + private void lazyComputeConnectivity() { if (init && unprocessedCutEdges.isEmpty()) { return; diff --git a/src/main/java/com/powsybl/openloadflow/graph/GraphDecrementalConnectivity.java b/src/main/java/com/powsybl/openloadflow/graph/GraphDecrementalConnectivity.java index 071004e9dc..ebceefc814 100644 --- a/src/main/java/com/powsybl/openloadflow/graph/GraphDecrementalConnectivity.java +++ b/src/main/java/com/powsybl/openloadflow/graph/GraphDecrementalConnectivity.java @@ -44,4 +44,6 @@ public interface GraphDecrementalConnectivity { * @return the collection of small connected components */ Collection> getSmallComponents(); + + Set getConnectedComponent(V vertex); } diff --git a/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphDecrementalConnectivity.java b/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphDecrementalConnectivity.java index b34f191ce9..05c1059b52 100644 --- a/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphDecrementalConnectivity.java +++ b/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphDecrementalConnectivity.java @@ -110,6 +110,11 @@ public List> getSmallComponents() { this.parentMap = mst.forest.getParentMap(); this.sortedRoots = mst.forest.getSortedRoots(); } + List> components = getConnectedComponents(); + return components.subList(1, components.size()); + } + + private List> getConnectedComponents() { List> components = new ArrayList<>(); for (V root : sortedRoots) { Set set = parentMap.entrySet().stream() @@ -117,7 +122,12 @@ public List> getSmallComponents() { .map(Map.Entry::getKey).collect(Collectors.toSet()); components.add(set); } - return components.subList(1, components.size()); + return components; + } + + @Override + public Set getConnectedComponent(V vertex) { + return getConnectedComponents().get(getComponentNumber(vertex)); } class KruskalMinimumSpanningTrees implements SpanningTreeAlgorithm { diff --git a/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphDecrementalConnectivity.java b/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphDecrementalConnectivity.java index 6fe86f2f8c..ee1ffebce0 100644 --- a/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphDecrementalConnectivity.java +++ b/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphDecrementalConnectivity.java @@ -101,4 +101,10 @@ public Collection> getSmallComponents() { updateComponents(); return componentSets.subList(1, componentSets.size()); } + + @Override + public Set getConnectedComponent(V vertex) { + updateComponents(); + return componentSets.get(components[numGetter.applyAsInt(vertex)]); + } } diff --git a/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java b/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java index ee864de84d..c023592fe3 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java @@ -365,25 +365,6 @@ public void logBalance() { num, activeGeneration, activeLoad, reactiveGeneration, reactiveLoad); } - public double getActivePowerMismatch() { - double mismatch = 0; - for (LfBus b : busesById.values()) { - mismatch += b.getGenerationTargetP() - b.getLoadTargetP(); - } - return -mismatch; - } - - public double getActivePowerMismatchInMainComponent(GraphDecrementalConnectivity connectivity) { - double mismatch = 0; - int mainComponent = connectivity.getComponentNumber(getSlackBus()); - for (LfBus b : busesById.values()) { - if (connectivity.getComponentNumber(b) == mainComponent) { - mismatch += b.getGenerationTargetP() - b.getLoadTargetP(); - } - } - return -mismatch; - } - private static void fix(LfNetwork network, boolean minImpedance) { if (minImpedance) { for (LfBranch branch : network.getBranches()) { diff --git a/src/main/java/com/powsybl/openloadflow/network/util/ActivePowerDistribution.java b/src/main/java/com/powsybl/openloadflow/network/util/ActivePowerDistribution.java index bdd4ebaf5e..90ea85e3e3 100644 --- a/src/main/java/com/powsybl/openloadflow/network/util/ActivePowerDistribution.java +++ b/src/main/java/com/powsybl/openloadflow/network/util/ActivePowerDistribution.java @@ -7,8 +7,10 @@ package com.powsybl.openloadflow.network.util; import com.powsybl.loadflow.LoadFlowParameters; +import com.powsybl.openloadflow.network.LfBus; import com.powsybl.openloadflow.network.LfNetwork; +import java.util.Collection; import java.util.List; import java.util.Objects; @@ -26,7 +28,7 @@ public interface Step { String getElementType(); - List getParticipatingElements(LfNetwork network); + List getParticipatingElements(Collection buses); double run(List participatingElements, int iteration, double remainingMismatch); } @@ -62,7 +64,11 @@ public String getElementType() { } public Result run(LfNetwork network, double activePowerMismatch) { - List participatingElements = step.getParticipatingElements(network); + return run(network.getBuses(), activePowerMismatch); + } + + public Result run(Collection buses, double activePowerMismatch) { + List participatingElements = step.getParticipatingElements(buses); int iteration = 0; double remainingMismatch = activePowerMismatch; diff --git a/src/main/java/com/powsybl/openloadflow/network/util/GenerationActionPowerDistributionStep.java b/src/main/java/com/powsybl/openloadflow/network/util/GenerationActionPowerDistributionStep.java index 4b18121a5a..b828554ad9 100644 --- a/src/main/java/com/powsybl/openloadflow/network/util/GenerationActionPowerDistributionStep.java +++ b/src/main/java/com/powsybl/openloadflow/network/util/GenerationActionPowerDistributionStep.java @@ -6,12 +6,13 @@ */ package com.powsybl.openloadflow.network.util; +import com.powsybl.openloadflow.network.LfBus; import com.powsybl.openloadflow.network.LfGenerator; -import com.powsybl.openloadflow.network.LfNetwork; import com.powsybl.openloadflow.network.PerUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.stream.Collectors; @@ -29,9 +30,8 @@ public String getElementType() { } @Override - public List getParticipatingElements(LfNetwork network) { - return network.getBuses() - .stream() + public List getParticipatingElements(Collection buses) { + return buses.stream() .filter(bus -> !(bus.isDisabled() || bus.isFictitious())) .flatMap(bus -> bus.getGenerators().stream()) .filter(generator -> generator.isParticipating() && generator.getParticipationFactor() != 0) diff --git a/src/main/java/com/powsybl/openloadflow/network/util/LoadActivePowerDistributionStep.java b/src/main/java/com/powsybl/openloadflow/network/util/LoadActivePowerDistributionStep.java index 78a96a2d14..7765561c95 100644 --- a/src/main/java/com/powsybl/openloadflow/network/util/LoadActivePowerDistributionStep.java +++ b/src/main/java/com/powsybl/openloadflow/network/util/LoadActivePowerDistributionStep.java @@ -7,11 +7,11 @@ package com.powsybl.openloadflow.network.util; import com.powsybl.openloadflow.network.LfBus; -import com.powsybl.openloadflow.network.LfNetwork; import com.powsybl.openloadflow.network.PerUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.stream.Collectors; @@ -38,9 +38,8 @@ public String getElementType() { } @Override - public List getParticipatingElements(LfNetwork network) { - return network.getBuses() - .stream() + public List getParticipatingElements(Collection buses) { + return buses.stream() .filter(bus -> bus.getPositiveLoadCount() > 0 && getVariableLoadTargetP(bus) > 0 && !(bus.isFictitious() || bus.isDisabled())) .map(bus -> new ParticipatingElement(bus, getVariableLoadTargetP(bus))) .collect(Collectors.toList()); diff --git a/src/main/java/com/powsybl/openloadflow/sensi/AbstractSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/AbstractSensitivityAnalysis.java index 138838e542..d292e6530b 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/AbstractSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/AbstractSensitivityAnalysis.java @@ -437,7 +437,7 @@ protected List createFactorGrou protected List getParticipatingElements(LfNetwork lfNetwork, LoadFlowParameters loadFlowParameters, OpenLoadFlowParameters openLoadFlowParameters, Function filter) { ActivePowerDistribution.Step step = ActivePowerDistribution.getStep(loadFlowParameters.getBalanceType(), openLoadFlowParameters.isLoadPowerFactorConstant()); - List participatingElements = step.getParticipatingElements(lfNetwork).stream().filter(filter::apply).collect(Collectors.toList()); + List participatingElements = step.getParticipatingElements(lfNetwork.getBuses()).stream().filter(filter::apply).collect(Collectors.toList()); ParticipatingElement.normalizeParticipationFactors(participatingElements, "bus"); return participatingElements; } diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index 3e11441872..8b0258b8f0 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -15,13 +15,14 @@ import com.powsybl.math.matrix.Matrix; import com.powsybl.math.matrix.MatrixFactory; import com.powsybl.openloadflow.OpenLoadFlowParameters; +import com.powsybl.openloadflow.dc.DcLoadFlowEngine; +import com.powsybl.openloadflow.dc.DcLoadFlowParameters; import com.powsybl.openloadflow.dc.equations.ClosedBranchSide1DcFlowEquationTerm; import com.powsybl.openloadflow.dc.equations.DcEquationSystem; import com.powsybl.openloadflow.dc.equations.DcEquationSystemCreationParameters; import com.powsybl.openloadflow.equations.*; import com.powsybl.openloadflow.graph.GraphDecrementalConnectivity; import com.powsybl.openloadflow.network.*; -import com.powsybl.openloadflow.network.util.ActivePowerDistribution; import com.powsybl.openloadflow.network.util.ParticipatingElement; import com.powsybl.openloadflow.util.BusState; import com.powsybl.openloadflow.util.PropagatedContingency; @@ -121,59 +122,19 @@ public DcSensitivityAnalysis(MatrixFactory matrixFactory) { super(matrixFactory); } - protected DenseMatrix setReferenceActivePowerFlows(LfNetwork network, EquationSystem equationSystem, JacobianMatrix j, List> factors, - LoadFlowParameters lfParameters, List participatingElements, GraphDecrementalConnectivity connectivity) { + protected DenseMatrix setReferenceActivePowerFlows(DcLoadFlowEngine dcLoadFlowEngine, EquationSystem equationSystem, JacobianMatrix j, + List> factors, LoadFlowParameters lfParameters, + List participatingElements, Collection buses) { - double[] x = equationSystem.createStateVector(new UniformValueVoltageInitializer()); Map busStates = new HashMap<>(); if (lfParameters.isDistributedSlack()) { - double mismatch; - if (connectivity != null) { - mismatch = network.getActivePowerMismatchInMainComponent(connectivity); - } else { - mismatch = network.getActivePowerMismatch(); - } busStates = BusState.createBusStates(participatingElements.stream() - .map(ParticipatingElement::getLfBus) - .collect(Collectors.toSet())); - int iteration = 0; - ActivePowerDistribution.Step step = ActivePowerDistribution.getStep(lfParameters.getBalanceType(), false); - while (!participatingElements.isEmpty() - && Math.abs(mismatch) > ActivePowerDistribution.P_RESIDUE_EPS) { - mismatch -= step.run(participatingElements, iteration, mismatch); - - iteration++; - } - } - - equationSystem.updateEquations(x); - - double[] dx = equationSystem.createTargetVector(); - - if (connectivity != null) { - // set buses injections and transformers to 0 outside the main connected component - int mainComponentNumber = connectivity.getComponentNumber(network.getSlackBus()); - Set columnsToSetToZero = network.getBuses().stream() - .filter(lfBus -> connectivity.getComponentNumber(lfBus) != mainComponentNumber) - .map(lfBus -> equationSystem.getEquation(lfBus.getNum(), EquationType.BUS_P)) - .filter(Optional::isPresent) - .map(Optional::get) - .map(Equation::getColumn) - .collect(Collectors.toSet()); - for (Integer column : columnsToSetToZero) { - dx[column] = 0; - } + .map(ParticipatingElement::getLfBus) + .collect(Collectors.toSet())); } - j.solveTransposed(dx); - - equationSystem.updateEquations(dx); - equationSystem.updateNetwork(dx); + dcLoadFlowEngine.runWithLu(equationSystem, j, buses); - // set all calculated voltages to NaN - for (LfBus bus : network.getBuses()) { - bus.setV(Double.NaN); - } for (LfSensitivityFactor factor : factors) { factor.setFunctionReference(factor.getFunctionLfBranch().getP1()); } @@ -182,6 +143,7 @@ protected DenseMatrix setReferenceActivePowerFlows(LfNetwork network, EquationSy BusState.restoreDcBusStates(busStates); } + double[] dx = dcLoadFlowEngine.getTargetVector(); return new DenseMatrix(dx.length, 1, dx); } @@ -391,9 +353,17 @@ public Pair, Map>> analyse checkContingencies(lfNetwork, contingencies); checkSensitivities(network, lfNetwork, factors); checkLoadFlowParameters(lfParameters); + + // create dc load flow engine for setting reference + DcLoadFlowParameters dcLoadFlowParameters = new DcLoadFlowParameters(lfParametersExt.getSlackBusSelector(), matrixFactory, + true, lfParametersExt.isDcUseTransformerRatio(), lfParameters.isDistributedSlack(), lfParameters.getBalanceType(), true, + lfParametersExt.getPlausibleActivePowerLimit()); + DcLoadFlowEngine dcLoadFlowEngine = new DcLoadFlowEngine(lfNetworks, dcLoadFlowParameters); + // create DC equation system for sensitivity analysis - EquationSystem equationSystem = DcEquationSystem.create(lfNetwork, new VariableSet(), - new DcEquationSystemCreationParameters(true, true, true, lfParametersExt.isDcUseTransformerRatio())); + DcEquationSystemCreationParameters dcEquationSystemCreationParameters = new DcEquationSystemCreationParameters(dcLoadFlowParameters.isUpdateFlows(), true, + dcLoadFlowParameters.isForcePhaseControlOffAndAddAngle1Var(), lfParametersExt.isDcUseTransformerRatio()); + EquationSystem equationSystem = DcEquationSystem.create(lfNetwork, new VariableSet(), dcEquationSystemCreationParameters); // we wrap the factor into a class that allows us to have access to their branch and EquationTerm instantly List> lfFactors = factors.stream().map(factor -> LfSensitivityFactor.create(factor, network, lfNetwork, equationSystem, ClosedBranchSide1DcFlowEquationTerm.class)).collect(Collectors.toList()); @@ -441,7 +411,7 @@ public Pair, Map>> analyse try (JacobianMatrix j = createJacobianMatrix(equationSystem, voltageInitializer)) { // run DC load on pre-contingency network - DenseMatrix flowStates = setReferenceActivePowerFlows(lfNetwork, equationSystem, j, lfFactors, lfParameters, participatingElements, null); + DenseMatrix flowStates = setReferenceActivePowerFlows(dcLoadFlowEngine, equationSystem, j, lfFactors, lfParameters, participatingElements, lfNetwork.getBuses()); // compute the pre-contingency sensitivity values + the states with +1 -1 to model the contingencies DenseMatrix factorsStates = initFactorsRhs(lfNetwork, equationSystem, factorGroups); // this is the rhs for the moment @@ -515,7 +485,8 @@ public Pair, Map>> analyse setBaseCaseSensitivityValues(factorGroups, factorsStates); // use this state to compute the base sensitivity (without +1-1) } - flowStates = setReferenceActivePowerFlows(lfNetwork, equationSystem, j, lfFactors, lfParameters, participatingElementsForThisConnectivity, connectivity); + flowStates = setReferenceActivePowerFlows(dcLoadFlowEngine, equationSystem, j, lfFactors, lfParameters, participatingElementsForThisConnectivity, + connectivity.getConnectedComponent(lfNetwork.getSlackBus())); Set elementsToReconnect = getElementsToReconnect(connectivity, breakingConnectivityCandidates); From 02cb15bb90589fa75354cbf26d70b430c8e859c7 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Fri, 5 Feb 2021 17:20:04 +0100 Subject: [PATCH 02/10] Avoid redondant use of connectivity interface Signed-off-by: Florian Dupuy Signed-off-by: Gael Macherel --- .../sensi/AbstractSensitivityAnalysis.java | 13 ++++--------- .../openloadflow/sensi/AcSensitivityAnalysis.java | 10 ++++++---- .../openloadflow/sensi/DcSensitivityAnalysis.java | 10 ++++++---- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sensi/AbstractSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/AbstractSensitivityAnalysis.java index d292e6530b..8e9bfa3c46 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/AbstractSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/AbstractSensitivityAnalysis.java @@ -37,7 +37,6 @@ import org.slf4j.LoggerFactory; import java.util.*; -import java.util.function.Function; import java.util.stream.Collectors; /** @@ -435,17 +434,13 @@ protected List createFactorGrou return new ArrayList<>(groupIndexedById.values()); } - protected List getParticipatingElements(LfNetwork lfNetwork, LoadFlowParameters loadFlowParameters, OpenLoadFlowParameters openLoadFlowParameters, Function filter) { + protected List getParticipatingElements(Collection buses, LoadFlowParameters loadFlowParameters, OpenLoadFlowParameters openLoadFlowParameters) { ActivePowerDistribution.Step step = ActivePowerDistribution.getStep(loadFlowParameters.getBalanceType(), openLoadFlowParameters.isLoadPowerFactorConstant()); - List participatingElements = step.getParticipatingElements(lfNetwork.getBuses()).stream().filter(filter::apply).collect(Collectors.toList()); + List participatingElements = step.getParticipatingElements(buses); ParticipatingElement.normalizeParticipationFactors(participatingElements, "bus"); return participatingElements; } - protected List getParticipatingElements(LfNetwork lfNetwork, LoadFlowParameters loadFlowParameters, OpenLoadFlowParameters openLoadFlowParameters) { - return getParticipatingElements(lfNetwork, loadFlowParameters, openLoadFlowParameters, element -> true); - } - protected void computeInjectionFactors(Map participationFactorByBus, List factorGroups) { // compute the corresponding injection (including participation) for each factor for (SensitivityFactorGroup factorGroup : factorGroups) { @@ -485,7 +480,7 @@ protected void setPredefinedResults(Collection factorGroups, GraphDecrementalConnectivity connectivity, Integer mainComponentNumber) { + protected void rescaleGlsk(List factorGroups, Set slackConnectedComponent) { // compute the corresponding injection (with participation) for each factor for (SensitivityFactorGroup factorGroup : factorGroups) { if (!(factorGroup instanceof LinearGlskGroup)) { @@ -493,7 +488,7 @@ protected void rescaleGlsk(List factorGroups, GraphDecre } LinearGlskGroup glskGroup = (LinearGlskGroup) factorGroup; Map remainingGlskInjections = glskGroup.getGlskMap().entrySet().stream() - .filter(entry -> connectivity.getComponentNumber(entry.getKey()) == mainComponentNumber) + .filter(entry -> slackConnectedComponent.contains(entry.getKey())) .collect(Collectors.toMap(entry -> entry.getKey().getId(), Map.Entry::getValue)); glskGroup.setGlskMapInMainComponent(remainingGlskInjections); } diff --git a/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java index 2a22e51134..7401262803 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java @@ -157,7 +157,7 @@ public Pair, Map>> analyse Map slackParticipationByBus; if (lfParameters.isDistributedSlack()) { - List participatingElements = getParticipatingElements(lfNetwork, lfParameters, lfParametersExt); + List participatingElements = getParticipatingElements(lfNetwork.getBuses(), lfParameters, lfParametersExt); slackParticipationByBus = participatingElements.stream().collect(Collectors.toMap( element -> element.getLfBus().getId(), element -> -element.getFactor(), @@ -208,18 +208,20 @@ public Pair, Map>> analyse for (LfContingency lfContingency : lfContingencies.stream().filter(lfContingency -> !lfContingency.getBuses().isEmpty()).collect(Collectors.toSet())) { lfFactors.forEach(lfFactor -> lfFactor.setPredefinedResult(null)); - int mainComponent = connectivity.getComponentNumber(lfNetwork.getSlackBus()); cutConnectivity(lfNetwork, connectivity, propagatedContingencyMap.get(lfContingency.getContingency())); + int mainComponent = connectivity.getComponentNumber(lfNetwork.getSlackBus()); + Set slackConnectedComponent = connectivity.getConnectedComponent(lfNetwork.getSlackBus()); setPredefinedResults(lfFactors, connectivity, mainComponent); // check if factors are still in the main component - rescaleGlsk(factorGroups, connectivity, mainComponent); + rescaleGlsk(factorGroups, slackConnectedComponent); // compute the participation for each injection factor (+1 on the injection and then -participation factor on all // buses that contain elements participating to slack distribution Map slackParticipationByBusForThisConnectivity; if (lfParameters.isDistributedSlack()) { - List participatingElementsForThisConnectivity = getParticipatingElements(lfNetwork, lfParameters, lfParametersExt, element -> connectivity.getComponentNumber(element.getLfBus()) == mainComponent); // will also be used to recompute the loadflow + List participatingElementsForThisConnectivity = getParticipatingElements( + slackConnectedComponent, lfParameters, lfParametersExt); // will also be used to recompute the loadflow slackParticipationByBusForThisConnectivity = participatingElementsForThisConnectivity.stream().collect(Collectors.toMap( element -> element.getLfBus().getId(), element -> -element.getFactor(), diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index 8b0258b8f0..229515c87d 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -381,7 +381,7 @@ public Pair, Map>> analyse List participatingElements = null; Map slackParticipationByBus; if (lfParameters.isDistributedSlack()) { - participatingElements = getParticipatingElements(lfNetwork, lfParameters, lfParametersExt); + participatingElements = getParticipatingElements(lfNetwork.getBuses(), lfParameters, lfParametersExt); slackParticipationByBus = participatingElements.stream().collect(Collectors.toMap( element -> element.getLfBus().getId(), element -> -element.getFactor(), @@ -455,10 +455,12 @@ public Pair, Map>> analyse lfFactors.forEach(factor -> factor.setPredefinedResult(null)); cutConnectivity(lfNetwork, connectivity, breakingConnectivityCandidates.stream().map(ComputedContingencyElement::getElement).map(ContingencyElement::getId).collect(Collectors.toSet())); int mainComponent = connectivity.getComponentNumber(lfNetwork.getSlackBus()); + Set slackConnectedComponent = connectivity.getConnectedComponent(lfNetwork.getSlackBus()); + setPredefinedResults(lfFactors, connectivity, mainComponent); // check if factors are still in the main component // some elements of the GLSK may not be in the connected component anymore, we recompute the injections - rescaleGlsk(factorGroups, connectivity, mainComponent); + rescaleGlsk(factorGroups, slackConnectedComponent); // null and unused if slack is not distributed List participatingElementsForThisConnectivity = participatingElements; @@ -468,7 +470,7 @@ public Pair, Map>> analyse Map slackParticipationByBusForThisConnectivity; if (lfParameters.isDistributedSlack()) { - participatingElementsForThisConnectivity = getParticipatingElements(lfNetwork, lfParameters, lfParametersExt, element -> connectivity.getComponentNumber(element.getLfBus()) == mainComponent); // will also be used to recompute the loadflow + participatingElementsForThisConnectivity = getParticipatingElements(slackConnectedComponent, lfParameters, lfParametersExt); // will also be used to recompute the loadflow slackParticipationByBusForThisConnectivity = participatingElementsForThisConnectivity.stream().collect(Collectors.toMap( element -> element.getLfBus().getId(), element -> -element.getFactor(), @@ -486,7 +488,7 @@ public Pair, Map>> analyse } flowStates = setReferenceActivePowerFlows(dcLoadFlowEngine, equationSystem, j, lfFactors, lfParameters, participatingElementsForThisConnectivity, - connectivity.getConnectedComponent(lfNetwork.getSlackBus())); + slackConnectedComponent); Set elementsToReconnect = getElementsToReconnect(connectivity, breakingConnectivityCandidates); From 0f2cdcecbe04e4e7087aeadbe42865a6a55c231c Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Fri, 5 Feb 2021 17:31:23 +0100 Subject: [PATCH 03/10] Working with removed buses instead of remaining buses Signed-off-by: Florian Dupuy Signed-off-by: Gael Macherel --- .../openloadflow/dc/DcLoadFlowEngine.java | 23 +++++++++++-------- ...nShiloachGraphDecrementalConnectivity.java | 14 +++++++++++ .../graph/GraphDecrementalConnectivity.java | 2 ++ ...nningTreeGraphDecrementalConnectivity.java | 6 +++++ .../NaiveGraphDecrementalConnectivity.java | 7 ++++++ .../sensi/AbstractSensitivityAnalysis.java | 4 ++-- .../sensi/AcSensitivityAnalysis.java | 6 +++-- .../sensi/DcSensitivityAnalysis.java | 16 +++++++------ 8 files changed, 58 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java b/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java index b81a020b79..7bdd7a67f7 100644 --- a/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java +++ b/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java @@ -73,7 +73,7 @@ public DcLoadFlowResult run() { LoadFlowResult.ComponentResult.Status status = LoadFlowResult.ComponentResult.Status.FAILED; try (JacobianMatrix j = new JacobianMatrix(equationSystem, parameters.getMatrixFactory())) { - status = runWithLu(equationSystem, j, network.getBuses()); + status = runWithLu(equationSystem, j, Collections.emptyList()); } catch (Exception e) { LOGGER.error("Failed to solve linear system for DC load flow", e); } @@ -81,10 +81,18 @@ public DcLoadFlowResult run() { return new DcLoadFlowResult(network, getActivePowerMismatch(network.getBuses()), status); } - public LoadFlowResult.ComponentResult.Status runWithLu(EquationSystem equationSystem, JacobianMatrix j, Collection buses) { + public LoadFlowResult.ComponentResult.Status runWithLu(EquationSystem equationSystem, JacobianMatrix j, Collection removedBuses) { + double[] x = equationSystem.createStateVector(new UniformValueVoltageInitializer()); + + // only process main (largest) connected component + LfNetwork network = networks.get(0); + + Collection remainingBuses = new HashSet<>(network.getBuses()); + remainingBuses.removeAll(removedBuses); + if (parameters.isDistributedSlack()) { - distributeSlack(buses); + distributeSlack(remainingBuses); } equationSystem.updateEquations(x); @@ -93,12 +101,9 @@ public LoadFlowResult.ComponentResult.Status runWithLu(EquationSystem equationSy this.dx = Arrays.copyOf(targets, targets.length); - // only process main (largest) connected component - LfNetwork network = networks.get(0); - if (network.getBuses().size() > buses.size()) { - // set buses injections and transformers to 0 outside the main connected component - network.getBuses().stream() - .filter(lfBus -> !buses.contains(lfBus)) + if (!removedBuses.isEmpty()) { + // set buses injections and transformers to 0 + removedBuses.stream() .map(lfBus -> equationSystem.getEquation(lfBus.getNum(), EquationType.BUS_P)) .filter(Optional::isPresent) .map(Optional::get) diff --git a/src/main/java/com/powsybl/openloadflow/graph/EvenShiloachGraphDecrementalConnectivity.java b/src/main/java/com/powsybl/openloadflow/graph/EvenShiloachGraphDecrementalConnectivity.java index 0f98407ed7..ee077d43f6 100644 --- a/src/main/java/com/powsybl/openloadflow/graph/EvenShiloachGraphDecrementalConnectivity.java +++ b/src/main/java/com/powsybl/openloadflow/graph/EvenShiloachGraphDecrementalConnectivity.java @@ -158,6 +158,20 @@ private Set getMainConnectedComponent() { return vertices.stream().filter(v -> newConnectedComponents.stream().noneMatch(cc -> cc.contains(v))).collect(Collectors.toSet()); } + @Override + public Set getNonConnectedVertices(V vertex) { + lazyComputeConnectivity(); + if (!vertices.contains(vertex)) { + throw new AssertionError("given vertex is not in the graph"); + } + List> nonConnectedComponents = new ArrayList<>(newConnectedComponents); + newConnectedComponents.stream().filter(c -> c.contains(vertex)).findFirst().ifPresent(c -> { + nonConnectedComponents.remove(c); + nonConnectedComponents.add(getMainConnectedComponent()); + }); + return nonConnectedComponents.stream().flatMap(Collection::stream).collect(Collectors.toSet()); + } + private void lazyComputeConnectivity() { if (init && unprocessedCutEdges.isEmpty()) { return; diff --git a/src/main/java/com/powsybl/openloadflow/graph/GraphDecrementalConnectivity.java b/src/main/java/com/powsybl/openloadflow/graph/GraphDecrementalConnectivity.java index ebceefc814..632390b4a2 100644 --- a/src/main/java/com/powsybl/openloadflow/graph/GraphDecrementalConnectivity.java +++ b/src/main/java/com/powsybl/openloadflow/graph/GraphDecrementalConnectivity.java @@ -46,4 +46,6 @@ public interface GraphDecrementalConnectivity { Collection> getSmallComponents(); Set getConnectedComponent(V vertex); + + Set getNonConnectedVertices(V vertex); } diff --git a/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphDecrementalConnectivity.java b/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphDecrementalConnectivity.java index 05c1059b52..6cb658bdc2 100644 --- a/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphDecrementalConnectivity.java +++ b/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphDecrementalConnectivity.java @@ -130,6 +130,12 @@ public Set getConnectedComponent(V vertex) { return getConnectedComponents().get(getComponentNumber(vertex)); } + @Override + public Set getNonConnectedVertices(V vertex) { + return getConnectedComponents().stream().filter(component -> !component.contains(vertex)) + .flatMap(Collection::stream).collect(Collectors.toSet()); + } + class KruskalMinimumSpanningTrees implements SpanningTreeAlgorithm { @Override diff --git a/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphDecrementalConnectivity.java b/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphDecrementalConnectivity.java index ee1ffebce0..b51f0c3ed9 100644 --- a/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphDecrementalConnectivity.java +++ b/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphDecrementalConnectivity.java @@ -107,4 +107,11 @@ public Set getConnectedComponent(V vertex) { updateComponents(); return componentSets.get(components[numGetter.applyAsInt(vertex)]); } + + @Override + public Set getNonConnectedVertices(V vertex) { + updateComponents(); + return componentSets.stream().filter(component -> !component.contains(vertex)) + .flatMap(Collection::stream).collect(Collectors.toSet()); + } } diff --git a/src/main/java/com/powsybl/openloadflow/sensi/AbstractSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/AbstractSensitivityAnalysis.java index 8e9bfa3c46..73d1ad36e2 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/AbstractSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/AbstractSensitivityAnalysis.java @@ -480,7 +480,7 @@ protected void setPredefinedResults(Collection factorGroups, Set slackConnectedComponent) { + protected void rescaleGlsk(List factorGroups, Set nonConnectedBuses) { // compute the corresponding injection (with participation) for each factor for (SensitivityFactorGroup factorGroup : factorGroups) { if (!(factorGroup instanceof LinearGlskGroup)) { @@ -488,7 +488,7 @@ protected void rescaleGlsk(List factorGroups, Set } LinearGlskGroup glskGroup = (LinearGlskGroup) factorGroup; Map remainingGlskInjections = glskGroup.getGlskMap().entrySet().stream() - .filter(entry -> slackConnectedComponent.contains(entry.getKey())) + .filter(entry -> !nonConnectedBuses.contains(entry.getKey())) .collect(Collectors.toMap(entry -> entry.getKey().getId(), Map.Entry::getValue)); glskGroup.setGlskMapInMainComponent(remainingGlskInjections); } diff --git a/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java index 7401262803..d309286d01 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java @@ -210,10 +210,12 @@ public Pair, Map>> analyse cutConnectivity(lfNetwork, connectivity, propagatedContingencyMap.get(lfContingency.getContingency())); int mainComponent = connectivity.getComponentNumber(lfNetwork.getSlackBus()); - Set slackConnectedComponent = connectivity.getConnectedComponent(lfNetwork.getSlackBus()); + Set nonConnectedBuses = connectivity.getNonConnectedVertices(lfNetwork.getSlackBus()); + Collection slackConnectedComponent = new ArrayList<>(lfNetwork.getBuses()); + slackConnectedComponent.removeAll(nonConnectedBuses); setPredefinedResults(lfFactors, connectivity, mainComponent); // check if factors are still in the main component - rescaleGlsk(factorGroups, slackConnectedComponent); + rescaleGlsk(factorGroups, nonConnectedBuses); // compute the participation for each injection factor (+1 on the injection and then -participation factor on all // buses that contain elements participating to slack distribution diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index 229515c87d..5cc2518452 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -124,7 +124,7 @@ public DcSensitivityAnalysis(MatrixFactory matrixFactory) { protected DenseMatrix setReferenceActivePowerFlows(DcLoadFlowEngine dcLoadFlowEngine, EquationSystem equationSystem, JacobianMatrix j, List> factors, LoadFlowParameters lfParameters, - List participatingElements, Collection buses) { + List participatingElements, Collection removedBuses) { Map busStates = new HashMap<>(); if (lfParameters.isDistributedSlack()) { @@ -133,7 +133,7 @@ protected DenseMatrix setReferenceActivePowerFlows(DcLoadFlowEngine dcLoadFlowEn .collect(Collectors.toSet())); } - dcLoadFlowEngine.runWithLu(equationSystem, j, buses); + dcLoadFlowEngine.runWithLu(equationSystem, j, removedBuses); for (LfSensitivityFactor factor : factors) { factor.setFunctionReference(factor.getFunctionLfBranch().getP1()); @@ -411,7 +411,7 @@ public Pair, Map>> analyse try (JacobianMatrix j = createJacobianMatrix(equationSystem, voltageInitializer)) { // run DC load on pre-contingency network - DenseMatrix flowStates = setReferenceActivePowerFlows(dcLoadFlowEngine, equationSystem, j, lfFactors, lfParameters, participatingElements, lfNetwork.getBuses()); + DenseMatrix flowStates = setReferenceActivePowerFlows(dcLoadFlowEngine, equationSystem, j, lfFactors, lfParameters, participatingElements, Collections.emptyList()); // compute the pre-contingency sensitivity values + the states with +1 -1 to model the contingencies DenseMatrix factorsStates = initFactorsRhs(lfNetwork, equationSystem, factorGroups); // this is the rhs for the moment @@ -455,12 +455,14 @@ public Pair, Map>> analyse lfFactors.forEach(factor -> factor.setPredefinedResult(null)); cutConnectivity(lfNetwork, connectivity, breakingConnectivityCandidates.stream().map(ComputedContingencyElement::getElement).map(ContingencyElement::getId).collect(Collectors.toSet())); int mainComponent = connectivity.getComponentNumber(lfNetwork.getSlackBus()); - Set slackConnectedComponent = connectivity.getConnectedComponent(lfNetwork.getSlackBus()); + Set nonConnectedBuses = connectivity.getNonConnectedVertices(lfNetwork.getSlackBus()); + Collection slackConnectedComponent = new ArrayList<>(lfNetwork.getBuses()); + slackConnectedComponent.removeAll(nonConnectedBuses); setPredefinedResults(lfFactors, connectivity, mainComponent); // check if factors are still in the main component // some elements of the GLSK may not be in the connected component anymore, we recompute the injections - rescaleGlsk(factorGroups, slackConnectedComponent); + rescaleGlsk(factorGroups, nonConnectedBuses); // null and unused if slack is not distributed List participatingElementsForThisConnectivity = participatingElements; @@ -487,8 +489,8 @@ public Pair, Map>> analyse setBaseCaseSensitivityValues(factorGroups, factorsStates); // use this state to compute the base sensitivity (without +1-1) } - flowStates = setReferenceActivePowerFlows(dcLoadFlowEngine, equationSystem, j, lfFactors, lfParameters, participatingElementsForThisConnectivity, - slackConnectedComponent); + flowStates = setReferenceActivePowerFlows(dcLoadFlowEngine, equationSystem, j, lfFactors, lfParameters, + participatingElementsForThisConnectivity, nonConnectedBuses); Set elementsToReconnect = getElementsToReconnect(connectivity, breakingConnectivityCandidates); From 92bbb364af8e46327c4b26cc10fadff57188b0cd Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Thu, 25 Feb 2021 15:58:34 +0100 Subject: [PATCH 04/10] Restrict visibility of distributeSlack / getActivePowerMismatch Signed-off-by: Florian Dupuy --- .../java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java b/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java index 7bdd7a67f7..918fc5df20 100644 --- a/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java +++ b/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java @@ -49,13 +49,13 @@ public DcLoadFlowEngine(List networks, DcLoadFlowParameters parameter this.parameters = Objects.requireNonNull(parameters); } - protected void distributeSlack(Collection buses) { + private void distributeSlack(Collection buses) { double mismatch = getActivePowerMismatch(buses); ActivePowerDistribution activePowerDistribution = ActivePowerDistribution.create(parameters.getBalanceType(), false); activePowerDistribution.run(buses, mismatch); } - public static double getActivePowerMismatch(Collection buses) { + private static double getActivePowerMismatch(Collection buses) { double mismatch = 0; for (LfBus b : buses) { mismatch += b.getGenerationTargetP() - b.getLoadTargetP(); From fd96a365b70dbca755685aa2bd95a3fe751511fc Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Thu, 25 Feb 2021 16:00:01 +0100 Subject: [PATCH 05/10] Renaming runWithLu (as lu not visible anymore) Signed-off-by: Florian Dupuy Signed-off-by: Gael Macherel --- .../java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java | 4 ++-- .../com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java b/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java index 918fc5df20..27ac3af1ab 100644 --- a/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java +++ b/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java @@ -73,7 +73,7 @@ public DcLoadFlowResult run() { LoadFlowResult.ComponentResult.Status status = LoadFlowResult.ComponentResult.Status.FAILED; try (JacobianMatrix j = new JacobianMatrix(equationSystem, parameters.getMatrixFactory())) { - status = runWithLu(equationSystem, j, Collections.emptyList()); + status = run(equationSystem, j, Collections.emptyList()); } catch (Exception e) { LOGGER.error("Failed to solve linear system for DC load flow", e); } @@ -81,7 +81,7 @@ public DcLoadFlowResult run() { return new DcLoadFlowResult(network, getActivePowerMismatch(network.getBuses()), status); } - public LoadFlowResult.ComponentResult.Status runWithLu(EquationSystem equationSystem, JacobianMatrix j, Collection removedBuses) { + public LoadFlowResult.ComponentResult.Status run(EquationSystem equationSystem, JacobianMatrix j, Collection removedBuses) { double[] x = equationSystem.createStateVector(new UniformValueVoltageInitializer()); diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index 5cc2518452..d0e5823f70 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -133,7 +133,7 @@ protected DenseMatrix setReferenceActivePowerFlows(DcLoadFlowEngine dcLoadFlowEn .collect(Collectors.toSet())); } - dcLoadFlowEngine.runWithLu(equationSystem, j, removedBuses); + dcLoadFlowEngine.run(equationSystem, j, removedBuses); for (LfSensitivityFactor factor : factors) { factor.setFunctionReference(factor.getFunctionLfBranch().getP1()); From d2bcae447a3a4661567518eefbb0de51e5162679 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Thu, 25 Feb 2021 16:08:10 +0100 Subject: [PATCH 06/10] Remove duplicate dx/targetVector Signed-off-by: Florian Dupuy --- .../openloadflow/dc/DcLoadFlowEngine.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java b/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java index 27ac3af1ab..c2be1ed38e 100644 --- a/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java +++ b/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java @@ -32,7 +32,7 @@ public class DcLoadFlowEngine { private final DcLoadFlowParameters parameters; - private double[] dx; + private double[] targetVector; public DcLoadFlowEngine(LfNetwork network, MatrixFactory matrixFactory) { this.networks = Collections.singletonList(network); @@ -97,9 +97,7 @@ public LoadFlowResult.ComponentResult.Status run(EquationSystem equationSystem, equationSystem.updateEquations(x); - double[] targets = equationSystem.createTargetVector(); - - this.dx = Arrays.copyOf(targets, targets.length); + this.targetVector = equationSystem.createTargetVector(); if (!removedBuses.isEmpty()) { // set buses injections and transformers to 0 @@ -108,20 +106,20 @@ public LoadFlowResult.ComponentResult.Status run(EquationSystem equationSystem, .filter(Optional::isPresent) .map(Optional::get) .map(Equation::getColumn) - .forEach(column -> dx[column] = 0); + .forEach(column -> targetVector[column] = 0); } LoadFlowResult.ComponentResult.Status status; try { - j.solveTransposed(dx); + j.solveTransposed(targetVector); status = LoadFlowResult.ComponentResult.Status.CONVERGED; } catch (Exception e) { status = LoadFlowResult.ComponentResult.Status.FAILED; LOGGER.error("Failed to solve linear system for DC load flow", e); } - equationSystem.updateEquations(dx); - equationSystem.updateNetwork(dx); + equationSystem.updateEquations(targetVector); + equationSystem.updateNetwork(targetVector); // set all calculated voltages to NaN for (LfBus bus : network.getBuses()) { @@ -133,6 +131,6 @@ public LoadFlowResult.ComponentResult.Status run(EquationSystem equationSystem, } public double[] getTargetVector() { - return dx; + return targetVector; } } From 9fc820f35df2596cf2f64b853626087a290f57f1 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Thu, 25 Feb 2021 21:50:47 +0100 Subject: [PATCH 07/10] Change isConnectedToComponent signature: now takes Set Signed-off-by: Florian Dupuy Signed-off-by: Gael Macherel --- .../sensi/AbstractSensitivityAnalysis.java | 23 ++++++++++--------- .../sensi/AcSensitivityAnalysis.java | 5 ++-- .../sensi/DcSensitivityAnalysis.java | 5 ++-- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sensi/AbstractSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/AbstractSensitivityAnalysis.java index 73d1ad36e2..04f44dcf07 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/AbstractSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/AbstractSensitivityAnalysis.java @@ -184,7 +184,7 @@ public boolean areVariableAndFunctionDisconnected(GraphDecrementalConnectivity connectivity) { + public boolean isConnectedToComponent(Set connectedComponent) { throw new NotImplementedException("isConnectedToComponent should have an override"); } } @@ -205,8 +205,8 @@ public boolean areVariableAndFunctionDisconnected(final GraphDecrementalConnecti } @Override - public boolean isConnectedToComponent(Integer componentNumber, GraphDecrementalConnectivity connectivity) { - return connectivity.getComponentNumber(injectionLfBus) == componentNumber; + public boolean isConnectedToComponent(Set connectedComponent) { + return connectedComponent.contains(injectionLfBus); } public LfBus getInjectionLfBus() { @@ -230,8 +230,8 @@ public boolean areVariableAndFunctionDisconnected(final GraphDecrementalConnecti } @Override - public boolean isConnectedToComponent(Integer componentNumber, GraphDecrementalConnectivity connectivity) { - return componentNumber == connectivity.getComponentNumber(phaseTapChangerLfBranch.getBus1()); + public boolean isConnectedToComponent(Set connectedComponent) { + return connectedComponent.contains(phaseTapChangerLfBranch.getBus1()); } } @@ -264,13 +264,13 @@ public boolean areVariableAndFunctionDisconnected(final GraphDecrementalConnecti } @Override - public boolean isConnectedToComponent(Integer componentNumber, GraphDecrementalConnectivity connectivity) { - if (connectivity.getComponentNumber(getFunctionLfBranch().getBus1()) != componentNumber - || connectivity.getComponentNumber(getFunctionLfBranch().getBus2()) != componentNumber) { + public boolean isConnectedToComponent(Set connectedComponent) { + if (!connectedComponent.contains(getFunctionLfBranch().getBus1()) + || !connectedComponent.contains(getFunctionLfBranch().getBus2())) { return false; } for (LfBus lfBus : injectionBuses.keySet()) { - if (connectivity.getComponentNumber(lfBus) == componentNumber) { + if (connectedComponent.contains(lfBus)) { return true; } } @@ -469,12 +469,13 @@ public void cutConnectivity(LfNetwork lfNetwork, GraphDecrementalConnectivity connectivity.cut(lfBranch.getBus1(), lfBranch.getBus2())); } - protected void setPredefinedResults(Collection> lfFactors, GraphDecrementalConnectivity connectivity, int mainComponent) { + protected void setPredefinedResults(Collection> lfFactors, Set connectedComponent, + GraphDecrementalConnectivity connectivity) { for (LfSensitivityFactor factor : lfFactors) { // check if the factor function and variable are in different connected components if (factor.areVariableAndFunctionDisconnected(connectivity)) { factor.setPredefinedResult(0d); - } else if (!factor.isConnectedToComponent(mainComponent, connectivity)) { + } else if (!factor.isConnectedToComponent(connectedComponent)) { factor.setPredefinedResult(Double.NaN); // works for sensitivity and function reference } } diff --git a/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java index d309286d01..21b5dae94e 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java @@ -209,11 +209,10 @@ public Pair, Map>> analyse lfFactors.forEach(lfFactor -> lfFactor.setPredefinedResult(null)); cutConnectivity(lfNetwork, connectivity, propagatedContingencyMap.get(lfContingency.getContingency())); - int mainComponent = connectivity.getComponentNumber(lfNetwork.getSlackBus()); Set nonConnectedBuses = connectivity.getNonConnectedVertices(lfNetwork.getSlackBus()); - Collection slackConnectedComponent = new ArrayList<>(lfNetwork.getBuses()); + Set slackConnectedComponent = new HashSet<>(lfNetwork.getBuses()); slackConnectedComponent.removeAll(nonConnectedBuses); - setPredefinedResults(lfFactors, connectivity, mainComponent); // check if factors are still in the main component + setPredefinedResults(lfFactors, slackConnectedComponent, connectivity); // check if factors are still in the main component rescaleGlsk(factorGroups, nonConnectedBuses); diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index d0e5823f70..1e831b208a 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -454,12 +454,11 @@ public Pair, Map>> analyse List contingencyList = entry.getValue(); lfFactors.forEach(factor -> factor.setPredefinedResult(null)); cutConnectivity(lfNetwork, connectivity, breakingConnectivityCandidates.stream().map(ComputedContingencyElement::getElement).map(ContingencyElement::getId).collect(Collectors.toSet())); - int mainComponent = connectivity.getComponentNumber(lfNetwork.getSlackBus()); Set nonConnectedBuses = connectivity.getNonConnectedVertices(lfNetwork.getSlackBus()); - Collection slackConnectedComponent = new ArrayList<>(lfNetwork.getBuses()); + Set slackConnectedComponent = new HashSet<>(lfNetwork.getBuses()); slackConnectedComponent.removeAll(nonConnectedBuses); - setPredefinedResults(lfFactors, connectivity, mainComponent); // check if factors are still in the main component + setPredefinedResults(lfFactors, slackConnectedComponent, connectivity); // check if factors are still in the main component // some elements of the GLSK may not be in the connected component anymore, we recompute the injections rescaleGlsk(factorGroups, nonConnectedBuses); From baf69a992d74c94084b74e9c5368349a6202ce60 Mon Sep 17 00:00:00 2001 From: Gael Macherel Date: Thu, 4 Mar 2021 17:08:40 +0100 Subject: [PATCH 08/10] merge fix Signed-off-by: Gael Macherel --- .../com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index 1e831b208a..a8cd356a4f 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -357,7 +357,7 @@ public Pair, Map>> analyse // create dc load flow engine for setting reference DcLoadFlowParameters dcLoadFlowParameters = new DcLoadFlowParameters(lfParametersExt.getSlackBusSelector(), matrixFactory, true, lfParametersExt.isDcUseTransformerRatio(), lfParameters.isDistributedSlack(), lfParameters.getBalanceType(), true, - lfParametersExt.getPlausibleActivePowerLimit()); + lfParametersExt.getPlausibleActivePowerLimit(), lfParametersExt.isAddRatioToLinesWithDifferentNominalVoltageAtBothEnds()); DcLoadFlowEngine dcLoadFlowEngine = new DcLoadFlowEngine(lfNetworks, dcLoadFlowParameters); // create DC equation system for sensitivity analysis From bf7a16e20b26fe4eb767db1ce0b1465d3e165dff Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Fri, 5 Mar 2021 11:46:29 +0100 Subject: [PATCH 09/10] Adding connectivity unit tests Signed-off-by: Florian Dupuy --- ...nShiloachGraphDecrementalConnectivity.java | 17 ++-- ...nningTreeGraphDecrementalConnectivity.java | 35 ++++--- .../NaiveGraphDecrementalConnectivity.java | 9 ++ .../openloadflow/graph/ConnectivityTest.java | 93 +++++++++++-------- 4 files changed, 92 insertions(+), 62 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/graph/EvenShiloachGraphDecrementalConnectivity.java b/src/main/java/com/powsybl/openloadflow/graph/EvenShiloachGraphDecrementalConnectivity.java index ee077d43f6..3b2ed1abd7 100644 --- a/src/main/java/com/powsybl/openloadflow/graph/EvenShiloachGraphDecrementalConnectivity.java +++ b/src/main/java/com/powsybl/openloadflow/graph/EvenShiloachGraphDecrementalConnectivity.java @@ -132,6 +132,7 @@ public void reset() { @Override public int getComponentNumber(V vertex) { + checkVertex(vertex); lazyComputeConnectivity(); updateVertexMapCache(); return vertexToConnectedComponent.get(vertex); @@ -145,13 +146,11 @@ public List> getSmallComponents() { @Override public Set getConnectedComponent(V vertex) { + checkVertex(vertex); lazyComputeConnectivity(); updateVertexMapCache(); int cn = vertexToConnectedComponent.get(vertex); - if (cn >= 0) { - return cn == 0 ? getMainConnectedComponent() : newConnectedComponents.get(cn - 1); - } - return Collections.emptySet(); + return cn == 0 ? getMainConnectedComponent() : newConnectedComponents.get(cn - 1); } private Set getMainConnectedComponent() { @@ -160,10 +159,8 @@ private Set getMainConnectedComponent() { @Override public Set getNonConnectedVertices(V vertex) { + checkVertex(vertex); lazyComputeConnectivity(); - if (!vertices.contains(vertex)) { - throw new AssertionError("given vertex is not in the graph"); - } List> nonConnectedComponents = new ArrayList<>(newConnectedComponents); newConnectedComponents.stream().filter(c -> c.contains(vertex)).findFirst().ifPresent(c -> { nonConnectedComponents.remove(c); @@ -248,6 +245,12 @@ private void updateVertexMapCache() { } } + private void checkVertex(V vertex) { + if (!graph.containsVertex(vertex)) { + throw new AssertionError("given vertex " + vertex + " is not in the graph"); + } + } + private interface GraphProcess { void next(); diff --git a/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphDecrementalConnectivity.java b/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphDecrementalConnectivity.java index 6cb658bdc2..229bdd68f2 100644 --- a/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphDecrementalConnectivity.java +++ b/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphDecrementalConnectivity.java @@ -91,30 +91,19 @@ private void invalidateMst() { @Override public int getComponentNumber(V vertex) { - if (this.mst == null) { - this.mst = new KruskalMinimumSpanningTrees().getSpanningTree(); - } - if (this.parentMap == null) { - this.parentMap = mst.forest.getParentMap(); - this.sortedRoots = mst.forest.getSortedRoots(); - } + checkVertex(vertex); + lazyCompute(); return sortedRoots.indexOf(parentMap.get(vertex)); } @Override public List> getSmallComponents() { - if (this.mst == null) { - this.mst = new KruskalMinimumSpanningTrees().getSpanningTree(); - } - if (this.parentMap == null) { - this.parentMap = mst.forest.getParentMap(); - this.sortedRoots = mst.forest.getSortedRoots(); - } List> components = getConnectedComponents(); return components.subList(1, components.size()); } private List> getConnectedComponents() { + lazyCompute(); List> components = new ArrayList<>(); for (V root : sortedRoots) { Set set = parentMap.entrySet().stream() @@ -127,15 +116,33 @@ private List> getConnectedComponents() { @Override public Set getConnectedComponent(V vertex) { + checkVertex(vertex); return getConnectedComponents().get(getComponentNumber(vertex)); } @Override public Set getNonConnectedVertices(V vertex) { + checkVertex(vertex); return getConnectedComponents().stream().filter(component -> !component.contains(vertex)) .flatMap(Collection::stream).collect(Collectors.toSet()); } + private void lazyCompute() { + if (this.mst == null) { + this.mst = new KruskalMinimumSpanningTrees().getSpanningTree(); + } + if (this.parentMap == null) { + this.parentMap = mst.forest.getParentMap(); + this.sortedRoots = mst.forest.getSortedRoots(); + } + } + + private void checkVertex(V vertex) { + if (!graph.containsVertex(vertex)) { + throw new AssertionError("given vertex " + vertex + " is not in the graph"); + } + } + class KruskalMinimumSpanningTrees implements SpanningTreeAlgorithm { @Override diff --git a/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphDecrementalConnectivity.java b/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphDecrementalConnectivity.java index b51f0c3ed9..964daedf58 100644 --- a/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphDecrementalConnectivity.java +++ b/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphDecrementalConnectivity.java @@ -92,6 +92,7 @@ public void reset() { @Override public int getComponentNumber(V vertex) { + checkVertex(vertex); updateComponents(); return components[numGetter.applyAsInt(vertex)]; } @@ -104,14 +105,22 @@ public Collection> getSmallComponents() { @Override public Set getConnectedComponent(V vertex) { + checkVertex(vertex); updateComponents(); return componentSets.get(components[numGetter.applyAsInt(vertex)]); } @Override public Set getNonConnectedVertices(V vertex) { + checkVertex(vertex); updateComponents(); return componentSets.stream().filter(component -> !component.contains(vertex)) .flatMap(Collection::stream).collect(Collectors.toSet()); } + + private void checkVertex(V vertex) { + if (!graph.containsVertex(vertex)) { + throw new AssertionError("given vertex " + vertex + " is not in the graph"); + } + } } diff --git a/src/test/java/com/powsybl/openloadflow/graph/ConnectivityTest.java b/src/test/java/com/powsybl/openloadflow/graph/ConnectivityTest.java index 3d548023d0..a6f4a62bcf 100644 --- a/src/test/java/com/powsybl/openloadflow/graph/ConnectivityTest.java +++ b/src/test/java/com/powsybl/openloadflow/graph/ConnectivityTest.java @@ -7,7 +7,6 @@ package com.powsybl.openloadflow.graph; import com.powsybl.commons.PowsyblException; -import com.powsybl.iidm.network.Bus; import com.powsybl.iidm.network.Network; import com.powsybl.openloadflow.network.*; import org.junit.jupiter.api.BeforeEach; @@ -15,6 +14,8 @@ import java.util.Arrays; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -29,7 +30,7 @@ class ConnectivityTest { @BeforeEach void setup() { - Network network = new ConnectedFactory().createThreeCcLinkedByASingleBus(); + Network network = ConnectedComponentNetworkFactory.createThreeCcLinkedByASingleBus(); List lfNetworks = LfNetwork.load(network, new FirstSlackBusSelector()); lfNetwork = lfNetworks.get(0); } @@ -71,6 +72,20 @@ void testNonConnected() { assertEquals("Algorithm not implemented for a network with several connected components at start", e.getMessage()); } + @Test + void testNonConnectedComponents() { + testNonConnectedComponents(new NaiveGraphDecrementalConnectivity<>(LfBus::getNum)); + testNonConnectedComponents(new EvenShiloachGraphDecrementalConnectivity<>()); + testNonConnectedComponents(new MinimumSpanningTreeGraphDecrementalConnectivity<>()); + } + + @Test + void testConnectedComponents() { + testConnectedComponents(new NaiveGraphDecrementalConnectivity<>(LfBus::getNum)); + testConnectedComponents(new EvenShiloachGraphDecrementalConnectivity<>()); + testConnectedComponents(new MinimumSpanningTreeGraphDecrementalConnectivity<>()); + } + private void testConnectivity(GraphDecrementalConnectivity connectivity) { updateConnectivity(connectivity); cutBranches(connectivity, "l34", "l48"); @@ -79,6 +94,9 @@ private void testConnectivity(GraphDecrementalConnectivity connectivity) assertEquals(0, connectivity.getComponentNumber(lfNetwork.getBusById("b4_vl_0"))); assertEquals(2, connectivity.getComponentNumber(lfNetwork.getBusById("b8_vl_0"))); assertEquals(2, connectivity.getSmallComponents().size()); + + AssertionError e = assertThrows(AssertionError.class, () -> connectivity.getComponentNumber(null)); + assertEquals("given vertex null is not in the graph", e.getMessage()); } private void testReducedMainComponent(GraphDecrementalConnectivity connectivity) { @@ -113,6 +131,36 @@ private void testReaddEdge(GraphDecrementalConnectivity connectivity) { assertEquals(1, connectivity.getComponentNumber(lfNetwork.getBusById("b8_vl_0"))); } + private void testNonConnectedComponents(GraphDecrementalConnectivity connectivity) { + updateConnectivity(connectivity); + cutBranches(connectivity, "l34", "l48"); + + assertEquals(createVerticesSet("b4_vl_0", "b5_vl_0", "b6_vl_0", "b7_vl_0", "b8_vl_0", "b9_vl_0", "b10_vl_0"), + connectivity.getNonConnectedVertices(lfNetwork.getBusById("b3_vl_0"))); + assertEquals(createVerticesSet("b1_vl_0", "b2_vl_0", "b3_vl_0", "b8_vl_0", "b9_vl_0", "b10_vl_0"), + connectivity.getNonConnectedVertices(lfNetwork.getBusById("b6_vl_0"))); + assertEquals(createVerticesSet("b4_vl_0", "b5_vl_0", "b6_vl_0", "b7_vl_0", "b1_vl_0", "b2_vl_0", "b3_vl_0"), + connectivity.getNonConnectedVertices(lfNetwork.getBusById("b10_vl_0"))); + + AssertionError e = assertThrows(AssertionError.class, () -> connectivity.getNonConnectedVertices(null)); + assertEquals("given vertex null is not in the graph", e.getMessage()); + } + + private void testConnectedComponents(GraphDecrementalConnectivity connectivity) { + updateConnectivity(connectivity); + cutBranches(connectivity, "l34", "l56", "l57"); + + assertEquals(createVerticesSet("b1_vl_0", "b2_vl_0", "b3_vl_0"), + connectivity.getConnectedComponent(lfNetwork.getBusById("b3_vl_0"))); + assertEquals(createVerticesSet("b6_vl_0", "b7_vl_0"), + connectivity.getConnectedComponent(lfNetwork.getBusById("b6_vl_0"))); + assertEquals(createVerticesSet("b4_vl_0", "b5_vl_0", "b8_vl_0", "b9_vl_0", "b10_vl_0"), + connectivity.getConnectedComponent(lfNetwork.getBusById("b10_vl_0"))); + + AssertionError e = assertThrows(AssertionError.class, () -> connectivity.getConnectedComponent(null)); + assertEquals("given vertex null is not in the graph", e.getMessage()); + } + private void cutBranches(GraphDecrementalConnectivity connectivity, String... branches) { Arrays.stream(branches).map(lfNetwork::getBranchById).forEach(lfBranch -> connectivity.cut(lfBranch.getBus2(), lfBranch.getBus1())); } @@ -126,44 +174,7 @@ private void updateConnectivity(GraphDecrementalConnectivity connectivity } } - public static class ConnectedFactory extends AbstractLoadFlowNetworkFactory { - public Network createThreeCcLinkedByASingleBus() { - Network network = Network.create("test", "code"); - Bus b1 = createBus(network, "b1"); - Bus b2 = createBus(network, "b2"); - Bus b3 = createBus(network, "b3"); - Bus b4 = createBus(network, "b4"); - Bus b5 = createBus(network, "b5"); - Bus b6 = createBus(network, "b6"); - Bus b7 = createBus(network, "b7"); - Bus b8 = createBus(network, "b8"); - Bus b9 = createBus(network, "b9"); - Bus b10 = createBus(network, "b10"); - createLine(network, b1, b2, "l12", 0.1f); - createLine(network, b1, b3, "l13", 0.1f); - createLine(network, b2, b3, "l23", 0.1f); - createLine(network, b3, b4, "l34", 0.1f); - createLine(network, b4, b5, "l45", 0.1f); - createLine(network, b5, b6, "l56", 0.1f); - createLine(network, b5, b7, "l57", 0.1f); - createLine(network, b6, b7, "l67", 0.1f); - createLine(network, b4, b8, "l48", 0.1f); - createLine(network, b8, b9, "l89", 0.1f); - createLine(network, b8, b10, "l810", 0.1f); - createLine(network, b9, b10, "l910", 0.1f); - - createGenerator(b2, "g2", 3); - createGenerator(b6, "g6", 2); - createGenerator(b10, "g10", 4); - createLoad(b1, "d1", 1); - createLoad(b3, "d3", 1); - createLoad(b4, "d4", 1); - createLoad(b5, "d5", 2); - createLoad(b7, "d7", 2); - createLoad(b8, "d8", 1); - createLoad(b9, "d9", 1); - - return network; - } + private Set createVerticesSet(String... busIds) { + return Arrays.stream(busIds).map(lfNetwork::getBusById).collect(Collectors.toSet()); } } From e3f7ae1fb404ab5e764acc75e9ba927b4b31a144 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Mon, 8 Mar 2021 09:44:01 +0100 Subject: [PATCH 10/10] Small clarification about bus disabled status. Signed-off-by: Anne Tilloy --- .../powsybl/openloadflow/dc/DcLoadFlowEngine.java | 8 ++++---- .../openloadflow/sensi/DcSensitivityAnalysis.java | 14 +++++++------- .../com/powsybl/openloadflow/util/BusState.java | 10 +++++----- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java b/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java index c2be1ed38e..240c2893b2 100644 --- a/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java +++ b/src/main/java/com/powsybl/openloadflow/dc/DcLoadFlowEngine.java @@ -81,7 +81,7 @@ public DcLoadFlowResult run() { return new DcLoadFlowResult(network, getActivePowerMismatch(network.getBuses()), status); } - public LoadFlowResult.ComponentResult.Status run(EquationSystem equationSystem, JacobianMatrix j, Collection removedBuses) { + public LoadFlowResult.ComponentResult.Status run(EquationSystem equationSystem, JacobianMatrix j, Collection disabledBuses) { double[] x = equationSystem.createStateVector(new UniformValueVoltageInitializer()); @@ -89,7 +89,7 @@ public LoadFlowResult.ComponentResult.Status run(EquationSystem equationSystem, LfNetwork network = networks.get(0); Collection remainingBuses = new HashSet<>(network.getBuses()); - remainingBuses.removeAll(removedBuses); + remainingBuses.removeAll(disabledBuses); if (parameters.isDistributedSlack()) { distributeSlack(remainingBuses); @@ -99,9 +99,9 @@ public LoadFlowResult.ComponentResult.Status run(EquationSystem equationSystem, this.targetVector = equationSystem.createTargetVector(); - if (!removedBuses.isEmpty()) { + if (!disabledBuses.isEmpty()) { // set buses injections and transformers to 0 - removedBuses.stream() + disabledBuses.stream() .map(lfBus -> equationSystem.getEquation(lfBus.getNum(), EquationType.BUS_P)) .filter(Optional::isPresent) .map(Optional::get) diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index e086d390b1..6e2b86ef2c 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -124,7 +124,7 @@ public DcSensitivityAnalysis(MatrixFactory matrixFactory) { protected DenseMatrix setReferenceActivePowerFlows(DcLoadFlowEngine dcLoadFlowEngine, EquationSystem equationSystem, JacobianMatrix j, List> factors, LoadFlowParameters lfParameters, - List participatingElements, Collection removedBuses) { + List participatingElements, Collection disabledBuses) { Map busStates = new HashMap<>(); if (lfParameters.isDistributedSlack()) { @@ -133,14 +133,14 @@ protected DenseMatrix setReferenceActivePowerFlows(DcLoadFlowEngine dcLoadFlowEn .collect(Collectors.toSet())); } - dcLoadFlowEngine.run(equationSystem, j, removedBuses); + dcLoadFlowEngine.run(equationSystem, j, disabledBuses); for (LfSensitivityFactor factor : factors) { factor.setFunctionReference(factor.getFunctionLfBranch().getP1()); } if (lfParameters.isDistributedSlack()) { - BusState.restoreDcBusStates(busStates); + BusState.restoreBusActiveStates(busStates); } double[] dx = dcLoadFlowEngine.getTargetVector(); @@ -459,13 +459,13 @@ public Pair, Map>> analyse lfFactors.forEach(factor -> factor.setPredefinedResult(null)); cutConnectivity(lfNetwork, connectivity, breakingConnectivityCandidates.stream().map(ComputedContingencyElement::getElement).map(ContingencyElement::getId).collect(Collectors.toSet())); - Set nonConnectedBuses = connectivity.getNonConnectedVertices(lfNetwork.getSlackBus()); + Set disabledBuses = connectivity.getNonConnectedVertices(lfNetwork.getSlackBus()); Set slackConnectedComponent = new HashSet<>(lfNetwork.getBuses()); - slackConnectedComponent.removeAll(nonConnectedBuses); + slackConnectedComponent.removeAll(disabledBuses); setPredefinedResults(lfFactors, slackConnectedComponent, connectivity); // check if factors are still in the main component // some elements of the GLSK may not be in the connected component anymore, we recompute the injections - rescaleGlsk(factorGroups, nonConnectedBuses); + rescaleGlsk(factorGroups, disabledBuses); // null and unused if slack is not distributed List participatingElementsForThisConnectivity = participatingElements; @@ -493,7 +493,7 @@ public Pair, Map>> analyse } flowStates = setReferenceActivePowerFlows(dcLoadFlowEngine, equationSystem, j, lfFactors, lfParameters, - participatingElementsForThisConnectivity, nonConnectedBuses); + participatingElementsForThisConnectivity, disabledBuses); Set elementsToReconnect = getElementsToReconnect(connectivity, breakingConnectivityCandidates); diff --git a/src/main/java/com/powsybl/openloadflow/util/BusState.java b/src/main/java/com/powsybl/openloadflow/util/BusState.java index edf3305c6d..59fff3ec54 100644 --- a/src/main/java/com/powsybl/openloadflow/util/BusState.java +++ b/src/main/java/com/powsybl/openloadflow/util/BusState.java @@ -39,21 +39,21 @@ public BusState(LfBus b) { } public void restoreBusState(LfBus bus) { - restoreDcBusState(bus); + restoreBusActiveState(bus); bus.setV(v); bus.setLoadTargetQ(loadTargetQ); bus.setGenerationTargetQ(generationTargetQ); + bus.setDisabled(disabled); bus.setVoltageControllerEnabled(isVoltageControllerEnabled); bus.setVoltageControlSwitchOffCount(0); } - public void restoreDcBusState(LfBus bus) { + public void restoreBusActiveState(LfBus bus) { bus.setAngle(angle); bus.setLoadTargetP(loadTargetP); bus.getGenerators().forEach(g -> { g.setTargetP(generatorsTargetP.get(g.getId())); }); - bus.setDisabled(disabled); } /** @@ -77,8 +77,8 @@ public static void restoreBusStates(Map busStates) { * Set the bus states based on the given map of states * @param busStates the map containing the bus states, indexed by buses */ - public static void restoreDcBusStates(Map busStates) { - busStates.forEach((b, state) -> state.restoreDcBusState(b)); + public static void restoreBusActiveStates(Map busStates) { + busStates.forEach((b, state) -> state.restoreBusActiveState(b)); } }