From 3a731b2063e4dc8feb1c976892c56caa1ae988fd Mon Sep 17 00:00:00 2001 From: p-arvy Date: Fri, 5 Jul 2024 12:09:18 +0200 Subject: [PATCH 01/16] Remove map on pst lost in DC sensis Signed-off-by: p-arvy --- .../sensi/DcSensitivityAnalysis.java | 101 ++++++------------ 1 file changed, 32 insertions(+), 69 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index 4679be4fb4..c2312c92b9 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -48,38 +48,6 @@ public class DcSensitivityAnalysis extends AbstractSensitivityAnalysis { private static final double FUNCTION_REFERENCE_ZER0_THRESHOLD = 1e-13; - private static final class PhaseTapChangerContingenciesIndexing { - - private final List contingenciesWithoutTransformers = new ArrayList<>(); - private final Map, Collection> contingenciesIndexedByPhaseTapChangers = new LinkedHashMap<>(); - - private PhaseTapChangerContingenciesIndexing(Collection contingencies, - Map contingencyElementByBranch, - Collection elementIdsToSkip) { - for (PropagatedContingency contingency : contingencies) { - Set lostTransformers = contingency.getBranchIdsToOpen().keySet().stream() - .filter(element -> !elementIdsToSkip.contains(element)) - .map(contingencyElementByBranch::get) - .map(ComputedContingencyElement::getLfBranch) - .filter(LfBranch::hasPhaseControllerCapability) - .collect(Collectors.toSet()); - if (lostTransformers.isEmpty()) { - contingenciesWithoutTransformers.add(contingency); - } else { - contingenciesIndexedByPhaseTapChangers.computeIfAbsent(lostTransformers, key -> new ArrayList<>()).add(contingency); - } - } - } - - private Collection getContingenciesWithoutPhaseTapChangerLoss() { - return contingenciesWithoutTransformers; - } - - private Map, Collection> getContingenciesIndexedByPhaseTapChangers() { - return contingenciesIndexedByPhaseTapChangers; - } - } - public DcSensitivityAnalysis(MatrixFactory matrixFactory, GraphConnectivityFactory connectivityFactory, SensitivityAnalysisParameters parameters) { super(matrixFactory, connectivityFactory, parameters); } @@ -413,20 +381,23 @@ private void calculateContingencySensitivityValues(PropagatedContingency conting } } - private void calculateSensitivityValuesForContingencyList(DcLoadFlowContext loadFlowContext, OpenLoadFlowParameters lfParametersExt, SensitivityFactorHolder validFactorHolder, + private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlowContext, OpenLoadFlowParameters lfParametersExt, SensitivityFactorHolder validFactorHolder, SensitivityFactorGroupList factorGroups, DenseMatrix factorState, DenseMatrix contingenciesStates, DenseMatrix flowStates, - Collection contingencies, Map contingencyElementByBranch, + PropagatedContingency contingency, Map contingencyElementByBranch, Set disabledBuses, List participatingElements, Set elementsToReconnect, SensitivityResultWriter resultWriter, ReportNode reportNode, Set partialDisabledBranches) { DenseMatrix modifiedFlowStates = flowStates; - - PhaseTapChangerContingenciesIndexing phaseTapChangerContingenciesIndexing = new PhaseTapChangerContingenciesIndexing(contingencies, contingencyElementByBranch, elementsToReconnect); - var lfNetwork = loadFlowContext.getNetwork(); - // compute contingencies without loss of phase tap changer - // first we compute the ones without loss of phase tap changers (because we reuse the load flows from the pre contingency network for all of them) - for (PropagatedContingency contingency : phaseTapChangerContingenciesIndexing.getContingenciesWithoutPhaseTapChangerLoss()) { + Set lostTransformers = contingency.getBranchIdsToOpen().keySet().stream() + .filter(element -> !elementsToReconnect.contains(element)) + .map(contingencyElementByBranch::get) + .map(ComputedContingencyElement::getLfBranch) + .filter(LfBranch::hasPhaseControllerCapability) + .collect(Collectors.toSet()); + + // no pst is lost + if (lostTransformers.isEmpty()) { Collection contingencyElements = contingency.getBranchIdsToOpen().keySet().stream() .filter(element -> !elementsToReconnect.contains(element)) .map(contingencyElementByBranch::get) @@ -438,32 +409,22 @@ private void calculateSensitivityValuesForContingencyList(DcLoadFlowContext load calculateContingencySensitivityValues(contingency, factorGroups, factorState, contingenciesStates, modifiedFlowStates, contingencyElements, resultWriter, loadFlowContext, lfParametersExt, validFactorHolder, participatingElements, new DisabledNetwork(disabledBuses, disabledBranches), reportNode); - } - - // then we compute the ones involving the loss of a phase tap changer (because we need to recompute the load flows) - for (Map.Entry, Collection> e : phaseTapChangerContingenciesIndexing.getContingenciesIndexedByPhaseTapChangers().entrySet()) { - Set disabledPhaseTapChangers = e.getKey(); - Collection propagatedContingencies = e.getValue(); - List contingenciesIds = propagatedContingencies.stream() - .map(c -> c.getContingency().getId()) - .collect(Collectors.toList()); - List> lfFactors = validFactorHolder.getFactorsForContingencies(contingenciesIds); + } else { + List> lfFactors = validFactorHolder.getFactorsForContingencies(List.of(contingency.getContingency().getId())); if (!lfFactors.isEmpty()) { - modifiedFlowStates = calculateActivePowerFlows(loadFlowContext, lfFactors, participatingElements, new DisabledNetwork(disabledBuses, disabledPhaseTapChangers), reportNode); - } - for (PropagatedContingency contingency : propagatedContingencies) { - Collection contingencyElements = contingency.getBranchIdsToOpen().keySet().stream() - .filter(element -> !elementsToReconnect.contains(element)) - .map(contingencyElementByBranch::get) - .collect(Collectors.toList()); - - Set disabledBranches = contingency.getBranchIdsToOpen().keySet().stream().map(lfNetwork::getBranchById).collect(Collectors.toSet()); - disabledBranches.addAll(partialDisabledBranches); - - calculateContingencySensitivityValues(contingency, factorGroups, factorState, contingenciesStates, modifiedFlowStates, contingencyElements, resultWriter, - loadFlowContext, lfParametersExt, validFactorHolder, participatingElements, - new DisabledNetwork(disabledBuses, disabledBranches), reportNode); + modifiedFlowStates = calculateActivePowerFlows(loadFlowContext, lfFactors, participatingElements, new DisabledNetwork(disabledBuses, lostTransformers), reportNode); } + Collection contingencyElements = contingency.getBranchIdsToOpen().keySet().stream() + .filter(element -> !elementsToReconnect.contains(element)) + .map(contingencyElementByBranch::get) + .collect(Collectors.toList()); + + Set disabledBranches = contingency.getBranchIdsToOpen().keySet().stream().map(lfNetwork::getBranchById).collect(Collectors.toSet()); + disabledBranches.addAll(partialDisabledBranches); + + calculateContingencySensitivityValues(contingency, factorGroups, factorState, contingenciesStates, modifiedFlowStates, contingencyElements, resultWriter, + loadFlowContext, lfParametersExt, validFactorHolder, participatingElements, + new DisabledNetwork(disabledBuses, disabledBranches), reportNode); } } @@ -521,9 +482,9 @@ participatingElementsForThisConnectivity, new DisabledNetwork(disabledBuses, Col reportNode); } - calculateSensitivityValuesForContingencyList(loadFlowContext, lfParametersExt, + calculateSensitivityValuesForAContingency(loadFlowContext, lfParametersExt, validFactorHolder, factorGroups, factorStateForThisConnectivity, contingenciesStates, modifiedFlowStates, - List.of(contingency), contingencyElementByBranch, disabledBuses, participatingElementsForThisConnectivity, + contingency, contingencyElementByBranch, disabledBuses, participatingElementsForThisConnectivity, connectivityAnalysisResult.getElementsToReconnect(), resultWriter, reportNode, partialDisabledBranches); if (rhsChanged) { @@ -689,9 +650,11 @@ public void analyse(Network network, List contingencies, LOGGER.info("Processing contingencies with no connectivity break"); // process contingencies with no connectivity break - calculateSensitivityValuesForContingencyList(loadFlowContext, lfParametersExt, validFactorHolder, factorGroups, - factorsStates, connectivityBreakAnalysisResults.contingenciesStates(), flowStates, connectivityBreakAnalysisResults.nonBreakingConnectivityContingencies(), - connectivityBreakAnalysisResults.contingencyElementByBranch(), Collections.emptySet(), participatingElements, Collections.emptySet(), resultWriter, reportNode, Collections.emptySet()); + for (PropagatedContingency contingency : connectivityBreakAnalysisResults.nonBreakingConnectivityContingencies()) { + calculateSensitivityValuesForAContingency(loadFlowContext, lfParametersExt, validFactorHolder, factorGroups, + factorsStates, connectivityBreakAnalysisResults.contingenciesStates(), flowStates, contingency, + connectivityBreakAnalysisResults.contingencyElementByBranch(), Collections.emptySet(), participatingElements, Collections.emptySet(), resultWriter, reportNode, Collections.emptySet()); + } LOGGER.info("Processing contingencies with connectivity break"); From b1642fc5a403d0200ede1b7a9a1dc527c1cbbedd Mon Sep 17 00:00:00 2001 From: p-arvy Date: Fri, 5 Jul 2024 12:41:16 +0200 Subject: [PATCH 02/16] Refactor method recomputing load flows if a pst is lost Signed-off-by: p-arvy --- .../sensi/DcSensitivityAnalysis.java | 44 ++++++------------- 1 file changed, 14 insertions(+), 30 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index c2312c92b9..a3a7ccb833 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -389,43 +389,27 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo DenseMatrix modifiedFlowStates = flowStates; var lfNetwork = loadFlowContext.getNetwork(); + // if needed, recompute load flows due to loss of a phase ap changer Set lostTransformers = contingency.getBranchIdsToOpen().keySet().stream() .filter(element -> !elementsToReconnect.contains(element)) .map(contingencyElementByBranch::get) .map(ComputedContingencyElement::getLfBranch) .filter(LfBranch::hasPhaseControllerCapability) .collect(Collectors.toSet()); - - // no pst is lost - if (lostTransformers.isEmpty()) { - Collection contingencyElements = contingency.getBranchIdsToOpen().keySet().stream() - .filter(element -> !elementsToReconnect.contains(element)) - .map(contingencyElementByBranch::get) - .collect(Collectors.toList()); - - Set disabledBranches = contingency.getBranchIdsToOpen().keySet().stream().map(lfNetwork::getBranchById).collect(Collectors.toSet()); - disabledBranches.addAll(partialDisabledBranches); - - calculateContingencySensitivityValues(contingency, factorGroups, factorState, contingenciesStates, modifiedFlowStates, contingencyElements, resultWriter, - loadFlowContext, lfParametersExt, validFactorHolder, participatingElements, - new DisabledNetwork(disabledBuses, disabledBranches), reportNode); - } else { - List> lfFactors = validFactorHolder.getFactorsForContingencies(List.of(contingency.getContingency().getId())); - if (!lfFactors.isEmpty()) { - modifiedFlowStates = calculateActivePowerFlows(loadFlowContext, lfFactors, participatingElements, new DisabledNetwork(disabledBuses, lostTransformers), reportNode); - } - Collection contingencyElements = contingency.getBranchIdsToOpen().keySet().stream() - .filter(element -> !elementsToReconnect.contains(element)) - .map(contingencyElementByBranch::get) - .collect(Collectors.toList()); - - Set disabledBranches = contingency.getBranchIdsToOpen().keySet().stream().map(lfNetwork::getBranchById).collect(Collectors.toSet()); - disabledBranches.addAll(partialDisabledBranches); - - calculateContingencySensitivityValues(contingency, factorGroups, factorState, contingenciesStates, modifiedFlowStates, contingencyElements, resultWriter, - loadFlowContext, lfParametersExt, validFactorHolder, participatingElements, - new DisabledNetwork(disabledBuses, disabledBranches), reportNode); + List> lfFactors = validFactorHolder.getFactorsForContingencies(List.of(contingency.getContingency().getId())); + if (!lostTransformers.isEmpty() && !lfFactors.isEmpty()) { + modifiedFlowStates = calculateActivePowerFlows(loadFlowContext, lfFactors, participatingElements, new DisabledNetwork(disabledBuses, lostTransformers), reportNode); } + + Collection contingencyElements = contingency.getBranchIdsToOpen().keySet().stream() + .filter(element -> !elementsToReconnect.contains(element)) + .map(contingencyElementByBranch::get) + .collect(Collectors.toList()); + Set disabledBranches = contingency.getBranchIdsToOpen().keySet().stream().map(lfNetwork::getBranchById).collect(Collectors.toSet()); + disabledBranches.addAll(partialDisabledBranches); + calculateContingencySensitivityValues(contingency, factorGroups, factorState, contingenciesStates, modifiedFlowStates, contingencyElements, resultWriter, + loadFlowContext, lfParametersExt, validFactorHolder, participatingElements, + new DisabledNetwork(disabledBuses, disabledBranches), reportNode); } private void processContingenciesBreakingConnectivity(ConnectivityBreakAnalysis.ConnectivityAnalysisResult connectivityAnalysisResult, DcLoadFlowContext loadFlowContext, From ddad6d36aa39ae79e3a2467ba26efabe5f380103 Mon Sep 17 00:00:00 2001 From: p-arvy Date: Fri, 5 Jul 2024 12:49:43 +0200 Subject: [PATCH 03/16] Case with pst or glsk/slack lost in same method Signed-off-by: p-arvy --- .../sensi/DcSensitivityAnalysis.java | 74 +++++++++---------- 1 file changed, 33 insertions(+), 41 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index a3a7ccb833..3b668697c9 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -311,14 +311,38 @@ private static double calculatePower(DcLoadFlowContext loadFlowContext, LfBranch * When a contingency involves the loss of a load or a generator, the slack distribution could be changed * or the sensitivity factors in case of GLSK. */ - private void calculateContingencySensitivityValues(PropagatedContingency contingency, SensitivityFactorGroupList factorGroups, DenseMatrix factorStates, DenseMatrix contingenciesStates, - DenseMatrix flowStates, Collection contingencyElements, SensitivityResultWriter resultWriter, - DcLoadFlowContext loadFlowContext, OpenLoadFlowParameters lfParametersExt, - SensitivityFactorHolder factorHolder, List participatingElements, - DisabledNetwork disabledNetwork, ReportNode reportNode) { - List> factors = factorHolder.getFactorsForContingency(contingency.getContingency().getId()); + private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlowContext, OpenLoadFlowParameters lfParametersExt, SensitivityFactorHolder validFactorHolder, + SensitivityFactorGroupList factorGroups, DenseMatrix factorState, DenseMatrix contingenciesStates, DenseMatrix flowStates, + PropagatedContingency contingency, Map contingencyElementByBranch, + Set disabledBuses, List participatingElements, Set elementsToReconnect, + SensitivityResultWriter resultWriter, ReportNode reportNode, Set partialDisabledBranches) { + List> factors = validFactorHolder.getFactorsForContingency(contingency.getContingency().getId()); + + var lfNetwork = loadFlowContext.getNetwork(); + Collection contingencyElements = contingency.getBranchIdsToOpen().keySet().stream() + .filter(element -> !elementsToReconnect.contains(element)) + .map(contingencyElementByBranch::get) + .collect(Collectors.toList()); + Set disabledBranches = contingency.getBranchIdsToOpen().keySet().stream().map(lfNetwork::getBranchById).collect(Collectors.toSet()); + disabledBranches.addAll(partialDisabledBranches); + DisabledNetwork disabledNetwork = new DisabledNetwork(disabledBuses, disabledBranches); + if (contingency.getGeneratorIdsToLose().isEmpty() && contingency.getLoadIdsToLoose().isEmpty()) { - calculateSensitivityValues(loadFlowContext, factors, factorStates, contingenciesStates, flowStates, contingencyElements, + DenseMatrix modifiedFlowStates = flowStates; + + // if needed, recompute load flows due to loss of a phase ap changer + Set lostTransformers = contingency.getBranchIdsToOpen().keySet().stream() + .filter(element -> !elementsToReconnect.contains(element)) + .map(contingencyElementByBranch::get) + .map(ComputedContingencyElement::getLfBranch) + .filter(LfBranch::hasPhaseControllerCapability) + .collect(Collectors.toSet()); + List> lfFactors = validFactorHolder.getFactorsForContingencies(List.of(contingency.getContingency().getId())); + if (!lostTransformers.isEmpty() && !lfFactors.isEmpty()) { + modifiedFlowStates = calculateActivePowerFlows(loadFlowContext, lfFactors, participatingElements, new DisabledNetwork(disabledBuses, lostTransformers), reportNode); + } + + calculateSensitivityValues(loadFlowContext, factors, factorState, contingenciesStates, modifiedFlowStates, contingencyElements, contingency, resultWriter, disabledNetwork); // write contingency status if (contingency.hasNoImpact()) { @@ -329,11 +353,10 @@ private void calculateContingencySensitivityValues(PropagatedContingency conting } else { // if we have a contingency including the loss of a DC line or a generator or a load // save base state for later restoration after each contingency - LfNetwork lfNetwork = loadFlowContext.getNetwork(); DcLoadFlowParameters lfParameters = loadFlowContext.getParameters(); NetworkState networkState = NetworkState.save(lfNetwork); LfContingency lfContingency = contingency.toLfContingency(lfNetwork).orElse(null); - DenseMatrix newFactorStates = factorStates; + DenseMatrix newFactorStates = factorState; List newParticipatingElements = participatingElements; boolean participatingElementsChanged = false; boolean rhsChanged = false; @@ -376,42 +399,11 @@ private void calculateContingencySensitivityValues(PropagatedContingency conting networkState.restore(); if (participatingElementsChanged || rhsChanged) { - setBaseCaseSensitivityValues(factorGroups, factorStates); + setBaseCaseSensitivityValues(factorGroups, factorState); } } } - private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlowContext, OpenLoadFlowParameters lfParametersExt, SensitivityFactorHolder validFactorHolder, - SensitivityFactorGroupList factorGroups, DenseMatrix factorState, DenseMatrix contingenciesStates, DenseMatrix flowStates, - PropagatedContingency contingency, Map contingencyElementByBranch, - Set disabledBuses, List participatingElements, Set elementsToReconnect, - SensitivityResultWriter resultWriter, ReportNode reportNode, Set partialDisabledBranches) { - DenseMatrix modifiedFlowStates = flowStates; - var lfNetwork = loadFlowContext.getNetwork(); - - // if needed, recompute load flows due to loss of a phase ap changer - Set lostTransformers = contingency.getBranchIdsToOpen().keySet().stream() - .filter(element -> !elementsToReconnect.contains(element)) - .map(contingencyElementByBranch::get) - .map(ComputedContingencyElement::getLfBranch) - .filter(LfBranch::hasPhaseControllerCapability) - .collect(Collectors.toSet()); - List> lfFactors = validFactorHolder.getFactorsForContingencies(List.of(contingency.getContingency().getId())); - if (!lostTransformers.isEmpty() && !lfFactors.isEmpty()) { - modifiedFlowStates = calculateActivePowerFlows(loadFlowContext, lfFactors, participatingElements, new DisabledNetwork(disabledBuses, lostTransformers), reportNode); - } - - Collection contingencyElements = contingency.getBranchIdsToOpen().keySet().stream() - .filter(element -> !elementsToReconnect.contains(element)) - .map(contingencyElementByBranch::get) - .collect(Collectors.toList()); - Set disabledBranches = contingency.getBranchIdsToOpen().keySet().stream().map(lfNetwork::getBranchById).collect(Collectors.toSet()); - disabledBranches.addAll(partialDisabledBranches); - calculateContingencySensitivityValues(contingency, factorGroups, factorState, contingenciesStates, modifiedFlowStates, contingencyElements, resultWriter, - loadFlowContext, lfParametersExt, validFactorHolder, participatingElements, - new DisabledNetwork(disabledBuses, disabledBranches), reportNode); - } - private void processContingenciesBreakingConnectivity(ConnectivityBreakAnalysis.ConnectivityAnalysisResult connectivityAnalysisResult, DcLoadFlowContext loadFlowContext, LoadFlowParameters lfParameters, OpenLoadFlowParameters lfParametersExt, SensitivityFactorHolder validFactorHolder, From 5eba925d047f502dfd1de95fd28ac8120a3c4437 Mon Sep 17 00:00:00 2001 From: p-arvy Date: Mon, 8 Jul 2024 12:31:11 +0200 Subject: [PATCH 04/16] At most 1 override of flow/sensi Signed-off-by: p-arvy --- .../sensi/DcSensitivityAnalysis.java | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index 3b668697c9..a68a564063 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -16,7 +16,9 @@ import com.powsybl.math.matrix.LUDecomposition; import com.powsybl.math.matrix.MatrixFactory; import com.powsybl.openloadflow.OpenLoadFlowParameters; -import com.powsybl.openloadflow.dc.*; +import com.powsybl.openloadflow.dc.DcLoadFlowContext; +import com.powsybl.openloadflow.dc.DcLoadFlowEngine; +import com.powsybl.openloadflow.dc.DcLoadFlowParameters; import com.powsybl.openloadflow.dc.equations.*; import com.powsybl.openloadflow.equations.Equation; import com.powsybl.openloadflow.equations.StateVector; @@ -315,34 +317,43 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo SensitivityFactorGroupList factorGroups, DenseMatrix factorState, DenseMatrix contingenciesStates, DenseMatrix flowStates, PropagatedContingency contingency, Map contingencyElementByBranch, Set disabledBuses, List participatingElements, Set elementsToReconnect, - SensitivityResultWriter resultWriter, ReportNode reportNode, Set partialDisabledBranches) { + SensitivityResultWriter resultWriter, ReportNode reportNode, Set partialDisabledBranches, boolean hasRhsChangedDueToConnectivityBreak) { List> factors = validFactorHolder.getFactorsForContingency(contingency.getContingency().getId()); - - var lfNetwork = loadFlowContext.getNetwork(); Collection contingencyElements = contingency.getBranchIdsToOpen().keySet().stream() .filter(element -> !elementsToReconnect.contains(element)) .map(contingencyElementByBranch::get) .collect(Collectors.toList()); + + var lfNetwork = loadFlowContext.getNetwork(); Set disabledBranches = contingency.getBranchIdsToOpen().keySet().stream().map(lfNetwork::getBranchById).collect(Collectors.toSet()); disabledBranches.addAll(partialDisabledBranches); DisabledNetwork disabledNetwork = new DisabledNetwork(disabledBuses, disabledBranches); if (contingency.getGeneratorIdsToLose().isEmpty() && contingency.getLoadIdsToLoose().isEmpty()) { - DenseMatrix modifiedFlowStates = flowStates; - - // if needed, recompute load flows due to loss of a phase ap changer - Set lostTransformers = contingency.getBranchIdsToOpen().keySet().stream() - .filter(element -> !elementsToReconnect.contains(element)) - .map(contingencyElementByBranch::get) - .map(ComputedContingencyElement::getLfBranch) - .filter(LfBranch::hasPhaseControllerCapability) - .collect(Collectors.toSet()); - List> lfFactors = validFactorHolder.getFactorsForContingencies(List.of(contingency.getContingency().getId())); - if (!lostTransformers.isEmpty() && !lfFactors.isEmpty()) { - modifiedFlowStates = calculateActivePowerFlows(loadFlowContext, lfFactors, participatingElements, new DisabledNetwork(disabledBuses, lostTransformers), reportNode); + DenseMatrix newFlowStates = flowStates; + DenseMatrix newFactorStates = factorState; + + if (!factors.isEmpty()) { + Set lostTransformers = contingency.getBranchIdsToOpen().keySet().stream() + .filter(element -> !elementsToReconnect.contains(element)) + .map(contingencyElementByBranch::get) + .map(ComputedContingencyElement::getLfBranch) + .filter(LfBranch::hasPhaseControllerCapability) + .collect(Collectors.toSet()); + + // if a phase tap changer is lost or if connectivity changed, recompute load flows + if (!disabledBuses.isEmpty() || !lostTransformers.isEmpty()) { + DisabledNetwork disabledNetworkWithPstLost = new DisabledNetwork(disabledBuses, lostTransformers); + newFlowStates = calculateActivePowerFlows(loadFlowContext, factors, participatingElements, disabledNetworkWithPstLost, reportNode); + } + } + + // we need to recompute the factor states because the connectivity changed + if (hasRhsChangedDueToConnectivityBreak) { + newFactorStates = calculateFactorStates(loadFlowContext, factorGroups, participatingElements); } - calculateSensitivityValues(loadFlowContext, factors, factorState, contingenciesStates, modifiedFlowStates, contingencyElements, + calculateSensitivityValues(loadFlowContext, factors, newFactorStates, contingenciesStates, newFlowStates, contingencyElements, contingency, resultWriter, disabledNetwork); // write contingency status if (contingency.hasNoImpact()) { @@ -381,9 +392,6 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo newParticipatingElements = getParticipatingElements(lfNetwork.getBuses(), lfParameters.getBalanceType(), lfParametersExt); } } - if (participatingElementsChanged || rhsChanged) { - newFactorStates = calculateFactorStates(loadFlowContext, factorGroups, newParticipatingElements); - } // write contingency status resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.SUCCESS); } else { @@ -391,6 +399,11 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.NO_IMPACT); } + // we need to recompute the factor states because the rhs has changed or + if (participatingElementsChanged || rhsChanged || hasRhsChangedDueToConnectivityBreak) { + newFactorStates = calculateFactorStates(loadFlowContext, factorGroups, newParticipatingElements); + } + DenseMatrix newFlowStates = calculateActivePowerFlows(loadFlowContext, factors, newParticipatingElements, disabledNetwork, reportNode); @@ -413,12 +426,8 @@ private void processContingenciesBreakingConnectivity(ConnectivityBreakAnalysis. DenseMatrix flowStates, DenseMatrix factorsStates, DenseMatrix contingenciesStates, SensitivityResultWriter resultWriter, ReportNode reportNode) { - DenseMatrix modifiedFlowStates = flowStates; PropagatedContingency contingency = connectivityAnalysisResult.getPropagatedContingency(); - List contingencyId = List.of(contingency.getContingency().getId()); - List> lfFactorsForContingencies = validFactorHolder.getFactorsForContingencies(contingencyId); - Set disabledBuses = connectivityAnalysisResult.getDisabledBuses(); Set partialDisabledBranches = connectivityAnalysisResult.getPartialDisabledBranches(); @@ -434,7 +443,6 @@ private void processContingenciesBreakingConnectivity(ConnectivityBreakAnalysis. // null and unused if slack bus is not distributed List participatingElementsForThisConnectivity = participatingElements; boolean rhsChanged = false; // true if the disabled buses change the slack distribution, or the GLSK - DenseMatrix factorStateForThisConnectivity = factorsStates; if (lfParameters.isDistributedSlack()) { rhsChanged = participatingElements.stream().anyMatch(element -> disabledBuses.contains(element.getLfBus())); } @@ -443,25 +451,17 @@ private void processContingenciesBreakingConnectivity(ConnectivityBreakAnalysis. rhsChanged |= rescaleGlsk(factorGroups, disabledBuses); } - // we need to recompute the factor states because the connectivity changed + // we need to recompute the participating elements because the connectivity changed if (rhsChanged) { participatingElementsForThisConnectivity = lfParameters.isDistributedSlack() ? getParticipatingElements(connectivityAnalysisResult.getSlackConnectedComponent(), lfParameters.getBalanceType(), lfParametersExt) // will also be used to recompute the loadflow : Collections.emptyList(); - - factorStateForThisConnectivity = calculateFactorStates(loadFlowContext, factorGroups, participatingElementsForThisConnectivity); - } - - if (!lfFactorsForContingencies.isEmpty()) { - modifiedFlowStates = calculateActivePowerFlows(loadFlowContext, lfFactorsForContingencies, - participatingElementsForThisConnectivity, new DisabledNetwork(disabledBuses, Collections.emptySet()), - reportNode); } calculateSensitivityValuesForAContingency(loadFlowContext, lfParametersExt, - validFactorHolder, factorGroups, factorStateForThisConnectivity, contingenciesStates, modifiedFlowStates, + validFactorHolder, factorGroups, factorsStates, contingenciesStates, flowStates, contingency, contingencyElementByBranch, disabledBuses, participatingElementsForThisConnectivity, - connectivityAnalysisResult.getElementsToReconnect(), resultWriter, reportNode, partialDisabledBranches); + connectivityAnalysisResult.getElementsToReconnect(), resultWriter, reportNode, partialDisabledBranches, rhsChanged); if (rhsChanged) { setBaseCaseSensitivityValues(factorGroups, factorsStates); // we modified the rhs, we need to restore previous state @@ -629,7 +629,7 @@ public void analyse(Network network, List contingencies, for (PropagatedContingency contingency : connectivityBreakAnalysisResults.nonBreakingConnectivityContingencies()) { calculateSensitivityValuesForAContingency(loadFlowContext, lfParametersExt, validFactorHolder, factorGroups, factorsStates, connectivityBreakAnalysisResults.contingenciesStates(), flowStates, contingency, - connectivityBreakAnalysisResults.contingencyElementByBranch(), Collections.emptySet(), participatingElements, Collections.emptySet(), resultWriter, reportNode, Collections.emptySet()); + connectivityBreakAnalysisResults.contingencyElementByBranch(), Collections.emptySet(), participatingElements, Collections.emptySet(), resultWriter, reportNode, Collections.emptySet(), false); } LOGGER.info("Processing contingencies with connectivity break"); From 321045f1138b08ec60f65c60ebc6a0961d298711 Mon Sep 17 00:00:00 2001 From: p-arvy Date: Mon, 8 Jul 2024 12:34:29 +0200 Subject: [PATCH 05/16] Small clean Signed-off-by: p-arvy --- .../openloadflow/sensi/DcSensitivityAnalysis.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index a68a564063..a3dbac63a2 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -16,9 +16,7 @@ import com.powsybl.math.matrix.LUDecomposition; import com.powsybl.math.matrix.MatrixFactory; import com.powsybl.openloadflow.OpenLoadFlowParameters; -import com.powsybl.openloadflow.dc.DcLoadFlowContext; -import com.powsybl.openloadflow.dc.DcLoadFlowEngine; -import com.powsybl.openloadflow.dc.DcLoadFlowParameters; +import com.powsybl.openloadflow.dc.*; import com.powsybl.openloadflow.dc.equations.*; import com.powsybl.openloadflow.equations.Equation; import com.powsybl.openloadflow.equations.StateVector; @@ -314,7 +312,7 @@ private static double calculatePower(DcLoadFlowContext loadFlowContext, LfBranch * or the sensitivity factors in case of GLSK. */ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlowContext, OpenLoadFlowParameters lfParametersExt, SensitivityFactorHolder validFactorHolder, - SensitivityFactorGroupList factorGroups, DenseMatrix factorState, DenseMatrix contingenciesStates, DenseMatrix flowStates, + SensitivityFactorGroupList factorGroups, DenseMatrix factorStates, DenseMatrix contingenciesStates, DenseMatrix flowStates, PropagatedContingency contingency, Map contingencyElementByBranch, Set disabledBuses, List participatingElements, Set elementsToReconnect, SensitivityResultWriter resultWriter, ReportNode reportNode, Set partialDisabledBranches, boolean hasRhsChangedDueToConnectivityBreak) { @@ -331,7 +329,7 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo if (contingency.getGeneratorIdsToLose().isEmpty() && contingency.getLoadIdsToLoose().isEmpty()) { DenseMatrix newFlowStates = flowStates; - DenseMatrix newFactorStates = factorState; + DenseMatrix newFactorStates = factorStates; if (!factors.isEmpty()) { Set lostTransformers = contingency.getBranchIdsToOpen().keySet().stream() @@ -367,7 +365,7 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo DcLoadFlowParameters lfParameters = loadFlowContext.getParameters(); NetworkState networkState = NetworkState.save(lfNetwork); LfContingency lfContingency = contingency.toLfContingency(lfNetwork).orElse(null); - DenseMatrix newFactorStates = factorState; + DenseMatrix newFactorStates = factorStates; List newParticipatingElements = participatingElements; boolean participatingElementsChanged = false; boolean rhsChanged = false; @@ -412,7 +410,7 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo networkState.restore(); if (participatingElementsChanged || rhsChanged) { - setBaseCaseSensitivityValues(factorGroups, factorState); + setBaseCaseSensitivityValues(factorGroups, factorStates); } } } From 1e68ead316442cf6ca0f4e6d3558e665c08668d1 Mon Sep 17 00:00:00 2001 From: p-arvy Date: Mon, 8 Jul 2024 12:50:28 +0200 Subject: [PATCH 06/16] Small clean Signed-off-by: p-arvy --- .../sensi/DcSensitivityAnalysis.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index a3dbac63a2..4e220bab3b 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -328,8 +328,13 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo DisabledNetwork disabledNetwork = new DisabledNetwork(disabledBuses, disabledBranches); if (contingency.getGeneratorIdsToLose().isEmpty() && contingency.getLoadIdsToLoose().isEmpty()) { - DenseMatrix newFlowStates = flowStates; DenseMatrix newFactorStates = factorStates; + DenseMatrix newFlowStates = flowStates; + + // we need to recompute the factor states because the connectivity changed + if (hasRhsChangedDueToConnectivityBreak) { + newFactorStates = calculateFactorStates(loadFlowContext, factorGroups, participatingElements); + } if (!factors.isEmpty()) { Set lostTransformers = contingency.getBranchIdsToOpen().keySet().stream() @@ -346,13 +351,13 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo } } - // we need to recompute the factor states because the connectivity changed + calculateSensitivityValues(loadFlowContext, factors, newFactorStates, contingenciesStates, newFlowStates, contingencyElements, + contingency, resultWriter, disabledNetwork); + if (hasRhsChangedDueToConnectivityBreak) { - newFactorStates = calculateFactorStates(loadFlowContext, factorGroups, participatingElements); + setBaseCaseSensitivityValues(factorGroups, factorStates); // we modified the rhs, we need to restore previous state } - calculateSensitivityValues(loadFlowContext, factors, newFactorStates, contingenciesStates, newFlowStates, contingencyElements, - contingency, resultWriter, disabledNetwork); // write contingency status if (contingency.hasNoImpact()) { resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.NO_IMPACT); @@ -409,8 +414,8 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo contingency, resultWriter, disabledNetwork); networkState.restore(); - if (participatingElementsChanged || rhsChanged) { - setBaseCaseSensitivityValues(factorGroups, factorStates); + if (participatingElementsChanged || rhsChanged || hasRhsChangedDueToConnectivityBreak) { + setBaseCaseSensitivityValues(factorGroups, factorStates); // we modified the rhs, we need to restore previous state } } } @@ -460,10 +465,6 @@ private void processContingenciesBreakingConnectivity(ConnectivityBreakAnalysis. validFactorHolder, factorGroups, factorsStates, contingenciesStates, flowStates, contingency, contingencyElementByBranch, disabledBuses, participatingElementsForThisConnectivity, connectivityAnalysisResult.getElementsToReconnect(), resultWriter, reportNode, partialDisabledBranches, rhsChanged); - - if (rhsChanged) { - setBaseCaseSensitivityValues(factorGroups, factorsStates); // we modified the rhs, we need to restore previous state - } } protected void cleanContingencies(LfNetwork lfNetwork, List contingencies) { From 516cf2989146caf86d8f012866d91d91a9ad5eaa Mon Sep 17 00:00:00 2001 From: p-arvy Date: Mon, 8 Jul 2024 18:28:33 +0200 Subject: [PATCH 07/16] Remove distinction of cases with/without generator or load lost Signed-off-by: p-arvy --- .../sensi/DcSensitivityAnalysis.java | 136 +++++++----------- 1 file changed, 55 insertions(+), 81 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index 4e220bab3b..2bdbcac76b 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -327,97 +327,67 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo disabledBranches.addAll(partialDisabledBranches); DisabledNetwork disabledNetwork = new DisabledNetwork(disabledBuses, disabledBranches); - if (contingency.getGeneratorIdsToLose().isEmpty() && contingency.getLoadIdsToLoose().isEmpty()) { - DenseMatrix newFactorStates = factorStates; - DenseMatrix newFlowStates = flowStates; - - // we need to recompute the factor states because the connectivity changed - if (hasRhsChangedDueToConnectivityBreak) { - newFactorStates = calculateFactorStates(loadFlowContext, factorGroups, participatingElements); + DcLoadFlowParameters lfParameters = loadFlowContext.getParameters(); + NetworkState networkState = NetworkState.save(lfNetwork); + LfContingency lfContingency = contingency.toLfContingency(lfNetwork).orElse(null); + DenseMatrix newFactorStates = factorStates; + List newParticipatingElements = participatingElements; + boolean participatingElementsChanged = false; + boolean rhsChanged = false; + if (lfContingency != null) { + lfContingency.apply(lfParameters.getBalanceType()); + participatingElementsChanged = isDistributedSlackOnGenerators(lfParameters) && !contingency.getGeneratorIdsToLose().isEmpty() + || isDistributedSlackOnLoads(lfParameters) && !contingency.getLoadIdsToLoose().isEmpty(); + if (factorGroups.hasMultiVariables()) { + Set impactedBuses = lfContingency.getLoadAndGeneratorBuses(); + impactedBuses.addAll(disabledBuses); + rhsChanged = rescaleGlsk(factorGroups, impactedBuses); } - - if (!factors.isEmpty()) { - Set lostTransformers = contingency.getBranchIdsToOpen().keySet().stream() - .filter(element -> !elementsToReconnect.contains(element)) - .map(contingencyElementByBranch::get) - .map(ComputedContingencyElement::getLfBranch) - .filter(LfBranch::hasPhaseControllerCapability) - .collect(Collectors.toSet()); - - // if a phase tap changer is lost or if connectivity changed, recompute load flows - if (!disabledBuses.isEmpty() || !lostTransformers.isEmpty()) { - DisabledNetwork disabledNetworkWithPstLost = new DisabledNetwork(disabledBuses, lostTransformers); - newFlowStates = calculateActivePowerFlows(loadFlowContext, factors, participatingElements, disabledNetworkWithPstLost, reportNode); + if (participatingElementsChanged) { + if (isDistributedSlackOnGenerators(lfParameters)) { + // deep copy of participatingElements, removing the participating LfGeneratorImpl whose targetP has been set to 0 + Set participatingGeneratorsToRemove = lfContingency.getLostGenerators(); + newParticipatingElements = participatingElements.stream() + .filter(participatingElement -> !participatingGeneratorsToRemove.contains(participatingElement.getElement())) + .map(participatingElement -> new ParticipatingElement(participatingElement.getElement(), participatingElement.getFactor())) + .collect(Collectors.toList()); + normalizeParticipationFactors(newParticipatingElements); + } else { // slack distribution on loads + newParticipatingElements = getParticipatingElements(lfNetwork.getBuses(), lfParameters.getBalanceType(), lfParametersExt); } } - - calculateSensitivityValues(loadFlowContext, factors, newFactorStates, contingenciesStates, newFlowStates, contingencyElements, - contingency, resultWriter, disabledNetwork); - - if (hasRhsChangedDueToConnectivityBreak) { - setBaseCaseSensitivityValues(factorGroups, factorStates); // we modified the rhs, we need to restore previous state - } - // write contingency status - if (contingency.hasNoImpact()) { - resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.NO_IMPACT); - } else { - resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.SUCCESS); - } + resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.SUCCESS); } else { - // if we have a contingency including the loss of a DC line or a generator or a load - // save base state for later restoration after each contingency - DcLoadFlowParameters lfParameters = loadFlowContext.getParameters(); - NetworkState networkState = NetworkState.save(lfNetwork); - LfContingency lfContingency = contingency.toLfContingency(lfNetwork).orElse(null); - DenseMatrix newFactorStates = factorStates; - List newParticipatingElements = participatingElements; - boolean participatingElementsChanged = false; - boolean rhsChanged = false; - if (lfContingency != null) { - lfContingency.apply(lfParameters.getBalanceType()); - participatingElementsChanged = isDistributedSlackOnGenerators(lfParameters) && !contingency.getGeneratorIdsToLose().isEmpty() - || isDistributedSlackOnLoads(lfParameters) && !contingency.getLoadIdsToLoose().isEmpty(); - if (factorGroups.hasMultiVariables()) { - Set impactedBuses = lfContingency.getLoadAndGeneratorBuses(); - rhsChanged = rescaleGlsk(factorGroups, impactedBuses); - } - if (participatingElementsChanged) { - if (isDistributedSlackOnGenerators(lfParameters)) { - // deep copy of participatingElements, removing the participating LfGeneratorImpl whose targetP has been set to 0 - Set participatingGeneratorsToRemove = lfContingency.getLostGenerators(); - newParticipatingElements = participatingElements.stream() - .filter(participatingElement -> !participatingGeneratorsToRemove.contains(participatingElement.getElement())) - .map(participatingElement -> new ParticipatingElement(participatingElement.getElement(), participatingElement.getFactor())) - .collect(Collectors.toList()); - normalizeParticipationFactors(newParticipatingElements); - } else { // slack distribution on loads - newParticipatingElements = getParticipatingElements(lfNetwork.getBuses(), lfParameters.getBalanceType(), lfParametersExt); - } - } - // write contingency status - resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.SUCCESS); - } else { - // write contingency status - resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.NO_IMPACT); - } + // write contingency status + resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.NO_IMPACT); + } - // we need to recompute the factor states because the rhs has changed or - if (participatingElementsChanged || rhsChanged || hasRhsChangedDueToConnectivityBreak) { - newFactorStates = calculateFactorStates(loadFlowContext, factorGroups, newParticipatingElements); - } + // we need to recompute the factor states because the rhs has changed or + if (participatingElementsChanged || rhsChanged || hasRhsChangedDueToConnectivityBreak) { + newFactorStates = calculateFactorStates(loadFlowContext, factorGroups, newParticipatingElements); + } - DenseMatrix newFlowStates = calculateActivePowerFlows(loadFlowContext, factors, - newParticipatingElements, disabledNetwork, reportNode); + Set lostTransformers = contingency.getBranchIdsToOpen().keySet().stream() + .filter(element -> !elementsToReconnect.contains(element)) + .map(contingencyElementByBranch::get) + .map(ComputedContingencyElement::getLfBranch) + .filter(LfBranch::hasPhaseControllerCapability) + .collect(Collectors.toSet()); + DenseMatrix newFlowStates = flowStates; + if (!contingency.getLoadIdsToLoose().isEmpty() || !contingency.getGeneratorIdsToLose().isEmpty() || + !disabledBuses.isEmpty() || !lostTransformers.isEmpty()) { + newFlowStates = calculateActivePowerFlows(loadFlowContext, factors, newParticipatingElements, disabledNetwork, reportNode); + } - calculateSensitivityValues(loadFlowContext, factors, newFactorStates, contingenciesStates, newFlowStates, contingencyElements, - contingency, resultWriter, disabledNetwork); + calculateSensitivityValues(loadFlowContext, factors, newFactorStates, contingenciesStates, newFlowStates, contingencyElements, + contingency, resultWriter, disabledNetwork); - networkState.restore(); - if (participatingElementsChanged || rhsChanged || hasRhsChangedDueToConnectivityBreak) { - setBaseCaseSensitivityValues(factorGroups, factorStates); // we modified the rhs, we need to restore previous state - } + networkState.restore(); + if (participatingElementsChanged || rhsChanged || hasRhsChangedDueToConnectivityBreak) { + setBaseCaseSensitivityValues(factorGroups, factorStates); // we modified the rhs, we need to restore previous state } +// } } private void processContingenciesBreakingConnectivity(ConnectivityBreakAnalysis.ConnectivityAnalysisResult connectivityAnalysisResult, DcLoadFlowContext loadFlowContext, @@ -459,8 +429,12 @@ private void processContingenciesBreakingConnectivity(ConnectivityBreakAnalysis. participatingElementsForThisConnectivity = lfParameters.isDistributedSlack() ? getParticipatingElements(connectivityAnalysisResult.getSlackConnectedComponent(), lfParameters.getBalanceType(), lfParametersExt) // will also be used to recompute the loadflow : Collections.emptyList(); + + // calcul de l'injection } + // calcul du flow + calculateSensitivityValuesForAContingency(loadFlowContext, lfParametersExt, validFactorHolder, factorGroups, factorsStates, contingenciesStates, flowStates, contingency, contingencyElementByBranch, disabledBuses, participatingElementsForThisConnectivity, From 05ddbc1f074bfec02709853d1a6e779ad0fcd6b6 Mon Sep 17 00:00:00 2001 From: p-arvy Date: Mon, 8 Jul 2024 19:03:10 +0200 Subject: [PATCH 08/16] Merge treatment of override for contingency breaking connectivity or not Signed-off-by: p-arvy --- .../sensi/DcSensitivityAnalysis.java | 96 +++++++------------ 1 file changed, 33 insertions(+), 63 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index 2bdbcac76b..112ea64977 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -315,7 +315,7 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo SensitivityFactorGroupList factorGroups, DenseMatrix factorStates, DenseMatrix contingenciesStates, DenseMatrix flowStates, PropagatedContingency contingency, Map contingencyElementByBranch, Set disabledBuses, List participatingElements, Set elementsToReconnect, - SensitivityResultWriter resultWriter, ReportNode reportNode, Set partialDisabledBranches, boolean hasRhsChangedDueToConnectivityBreak) { + SensitivityResultWriter resultWriter, ReportNode reportNode, Set partialDisabledBranches, Collection slackConnectedComponent) { List> factors = validFactorHolder.getFactorsForContingency(contingency.getContingency().getId()); Collection contingencyElements = contingency.getBranchIdsToOpen().keySet().stream() .filter(element -> !elementsToReconnect.contains(element)) @@ -332,17 +332,27 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo LfContingency lfContingency = contingency.toLfContingency(lfNetwork).orElse(null); DenseMatrix newFactorStates = factorStates; List newParticipatingElements = participatingElements; - boolean participatingElementsChanged = false; - boolean rhsChanged = false; + boolean participatingElementsChanged = false; // true if participating elements are changed due to contingency + boolean rhsChanged = false; // true if the disabled buses or the contingency change the slack distribution, or the GLSK if (lfContingency != null) { lfContingency.apply(lfParameters.getBalanceType()); - participatingElementsChanged = isDistributedSlackOnGenerators(lfParameters) && !contingency.getGeneratorIdsToLose().isEmpty() - || isDistributedSlackOnLoads(lfParameters) && !contingency.getLoadIdsToLoose().isEmpty(); + // TODO : verify if we need rhsChanged AND participatingElementsChanged + if (lfParameters.isDistributedSlack()) { + rhsChanged = participatingElements.stream().anyMatch(element -> disabledBuses.contains(element.getLfBus())); + } if (factorGroups.hasMultiVariables()) { Set impactedBuses = lfContingency.getLoadAndGeneratorBuses(); impactedBuses.addAll(disabledBuses); rhsChanged = rescaleGlsk(factorGroups, impactedBuses); } + if (rhsChanged) { + newParticipatingElements = lfParameters.isDistributedSlack() + ? getParticipatingElements(slackConnectedComponent, lfParameters.getBalanceType(), lfParametersExt) // will also be used to recompute the loadflow + : Collections.emptyList(); + } + + participatingElementsChanged = isDistributedSlackOnGenerators(lfParameters) && !contingency.getGeneratorIdsToLose().isEmpty() + || isDistributedSlackOnLoads(lfParameters) && !contingency.getLoadIdsToLoose().isEmpty(); if (participatingElementsChanged) { if (isDistributedSlackOnGenerators(lfParameters)) { // deep copy of participatingElements, removing the participating LfGeneratorImpl whose targetP has been set to 0 @@ -364,7 +374,7 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo } // we need to recompute the factor states because the rhs has changed or - if (participatingElementsChanged || rhsChanged || hasRhsChangedDueToConnectivityBreak) { + if (participatingElementsChanged || rhsChanged) { newFactorStates = calculateFactorStates(loadFlowContext, factorGroups, newParticipatingElements); } @@ -384,61 +394,9 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo contingency, resultWriter, disabledNetwork); networkState.restore(); - if (participatingElementsChanged || rhsChanged || hasRhsChangedDueToConnectivityBreak) { + if (participatingElementsChanged || rhsChanged) { setBaseCaseSensitivityValues(factorGroups, factorStates); // we modified the rhs, we need to restore previous state } -// } - } - - private void processContingenciesBreakingConnectivity(ConnectivityBreakAnalysis.ConnectivityAnalysisResult connectivityAnalysisResult, DcLoadFlowContext loadFlowContext, - LoadFlowParameters lfParameters, OpenLoadFlowParameters lfParametersExt, - SensitivityFactorHolder validFactorHolder, - SensitivityFactorGroupList factorGroups, - List participatingElements, - Map contingencyElementByBranch, - DenseMatrix flowStates, DenseMatrix factorsStates, DenseMatrix contingenciesStates, - SensitivityResultWriter resultWriter, - ReportNode reportNode) { - - PropagatedContingency contingency = connectivityAnalysisResult.getPropagatedContingency(); - Set disabledBuses = connectivityAnalysisResult.getDisabledBuses(); - Set partialDisabledBranches = connectivityAnalysisResult.getPartialDisabledBranches(); - - // as we are processing a contingency with connectivity break, we have to reset active power flow of a hvdc line - // if one bus of the line is lost. - for (LfHvdc hvdc : loadFlowContext.getNetwork().getHvdcs()) { - if (Networks.isIsolatedBusForHvdc(hvdc.getBus1(), disabledBuses) ^ Networks.isIsolatedBusForHvdc(hvdc.getBus2(), disabledBuses)) { - contingency.getGeneratorIdsToLose().add(hvdc.getConverterStation1().getId()); - contingency.getGeneratorIdsToLose().add(hvdc.getConverterStation2().getId()); - } - } - - // null and unused if slack bus is not distributed - List participatingElementsForThisConnectivity = participatingElements; - boolean rhsChanged = false; // true if the disabled buses change the slack distribution, or the GLSK - if (lfParameters.isDistributedSlack()) { - rhsChanged = participatingElements.stream().anyMatch(element -> disabledBuses.contains(element.getLfBus())); - } - if (factorGroups.hasMultiVariables()) { - // some elements of the GLSK may not be in the connected component anymore, we recompute the injections - rhsChanged |= rescaleGlsk(factorGroups, disabledBuses); - } - - // we need to recompute the participating elements because the connectivity changed - if (rhsChanged) { - participatingElementsForThisConnectivity = lfParameters.isDistributedSlack() - ? getParticipatingElements(connectivityAnalysisResult.getSlackConnectedComponent(), lfParameters.getBalanceType(), lfParametersExt) // will also be used to recompute the loadflow - : Collections.emptyList(); - - // calcul de l'injection - } - - // calcul du flow - - calculateSensitivityValuesForAContingency(loadFlowContext, lfParametersExt, - validFactorHolder, factorGroups, factorsStates, contingenciesStates, flowStates, - contingency, contingencyElementByBranch, disabledBuses, participatingElementsForThisConnectivity, - connectivityAnalysisResult.getElementsToReconnect(), resultWriter, reportNode, partialDisabledBranches, rhsChanged); } protected void cleanContingencies(LfNetwork lfNetwork, List contingencies) { @@ -602,16 +560,28 @@ public void analyse(Network network, List contingencies, for (PropagatedContingency contingency : connectivityBreakAnalysisResults.nonBreakingConnectivityContingencies()) { calculateSensitivityValuesForAContingency(loadFlowContext, lfParametersExt, validFactorHolder, factorGroups, factorsStates, connectivityBreakAnalysisResults.contingenciesStates(), flowStates, contingency, - connectivityBreakAnalysisResults.contingencyElementByBranch(), Collections.emptySet(), participatingElements, Collections.emptySet(), resultWriter, reportNode, Collections.emptySet(), false); + connectivityBreakAnalysisResults.contingencyElementByBranch(), Collections.emptySet(), participatingElements, Collections.emptySet(), resultWriter, reportNode, Collections.emptySet(), + lfNetwork.getBuses()); } LOGGER.info("Processing contingencies with connectivity break"); // process contingencies with connectivity break for (ConnectivityBreakAnalysis.ConnectivityAnalysisResult connectivityAnalysisResult : connectivityBreakAnalysisResults.connectivityAnalysisResults()) { - processContingenciesBreakingConnectivity(connectivityAnalysisResult, loadFlowContext, lfParameters, lfParametersExt, - validFactorHolder, factorGroups, participatingElements, connectivityBreakAnalysisResults.contingencyElementByBranch(), - flowStates, factorsStates, connectivityBreakAnalysisResults.contingenciesStates(), resultWriter, reportNode); + Set disabledBuses = connectivityAnalysisResult.getDisabledBuses(); + PropagatedContingency contingency = connectivityAnalysisResult.getPropagatedContingency(); + + for (LfHvdc hvdc : loadFlowContext.getNetwork().getHvdcs()) { + if (Networks.isIsolatedBusForHvdc(hvdc.getBus1(), disabledBuses) ^ Networks.isIsolatedBusForHvdc(hvdc.getBus2(), disabledBuses)) { + contingency.getGeneratorIdsToLose().add(hvdc.getConverterStation1().getId()); + contingency.getGeneratorIdsToLose().add(hvdc.getConverterStation2().getId()); + } + } + + calculateSensitivityValuesForAContingency(loadFlowContext, lfParametersExt, + validFactorHolder, factorGroups, factorsStates, connectivityBreakAnalysisResults.contingenciesStates(), flowStates, + contingency, connectivityBreakAnalysisResults.contingencyElementByBranch(), disabledBuses, participatingElements, + connectivityAnalysisResult.getElementsToReconnect(), resultWriter, reportNode, connectivityAnalysisResult.getPartialDisabledBranches(), connectivityAnalysisResult.getSlackConnectedComponent()); } } From 4ea0b54894d7b0c8369dd4df8e1e23089a29ab63 Mon Sep 17 00:00:00 2001 From: p-arvy Date: Mon, 8 Jul 2024 19:05:33 +0200 Subject: [PATCH 09/16] Modify commentary Signed-off-by: p-arvy --- .../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 112ea64977..431346df66 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -373,7 +373,7 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.NO_IMPACT); } - // we need to recompute the factor states because the rhs has changed or + // we need to recompute the factor states because the rhs or the participating elements have changed if (participatingElementsChanged || rhsChanged) { newFactorStates = calculateFactorStates(loadFlowContext, factorGroups, newParticipatingElements); } From 5c41a7d8d9c8019b037f8baf5add3ba5b52f6fac Mon Sep 17 00:00:00 2001 From: p-arvy Date: Tue, 9 Jul 2024 14:23:43 +0200 Subject: [PATCH 10/16] Revert "Modify commentary" This reverts commit 4f5fbe335fb6386de234c7897591fcf060d64351. --- .../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 431346df66..112ea64977 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -373,7 +373,7 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.NO_IMPACT); } - // we need to recompute the factor states because the rhs or the participating elements have changed + // we need to recompute the factor states because the rhs has changed or if (participatingElementsChanged || rhsChanged) { newFactorStates = calculateFactorStates(loadFlowContext, factorGroups, newParticipatingElements); } From 3bf641ef997fba69cfa4fd4842234c07d23dd041 Mon Sep 17 00:00:00 2001 From: p-arvy Date: Tue, 9 Jul 2024 14:23:43 +0200 Subject: [PATCH 11/16] Revert "Merge treatment of override for contingency breaking connectivity or not" This reverts commit 307cc690971b7c4a7f5f0474fc1c859804692fa6. --- .../sensi/DcSensitivityAnalysis.java | 96 ++++++++++++------- 1 file changed, 63 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index 112ea64977..2bdbcac76b 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -315,7 +315,7 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo SensitivityFactorGroupList factorGroups, DenseMatrix factorStates, DenseMatrix contingenciesStates, DenseMatrix flowStates, PropagatedContingency contingency, Map contingencyElementByBranch, Set disabledBuses, List participatingElements, Set elementsToReconnect, - SensitivityResultWriter resultWriter, ReportNode reportNode, Set partialDisabledBranches, Collection slackConnectedComponent) { + SensitivityResultWriter resultWriter, ReportNode reportNode, Set partialDisabledBranches, boolean hasRhsChangedDueToConnectivityBreak) { List> factors = validFactorHolder.getFactorsForContingency(contingency.getContingency().getId()); Collection contingencyElements = contingency.getBranchIdsToOpen().keySet().stream() .filter(element -> !elementsToReconnect.contains(element)) @@ -332,27 +332,17 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo LfContingency lfContingency = contingency.toLfContingency(lfNetwork).orElse(null); DenseMatrix newFactorStates = factorStates; List newParticipatingElements = participatingElements; - boolean participatingElementsChanged = false; // true if participating elements are changed due to contingency - boolean rhsChanged = false; // true if the disabled buses or the contingency change the slack distribution, or the GLSK + boolean participatingElementsChanged = false; + boolean rhsChanged = false; if (lfContingency != null) { lfContingency.apply(lfParameters.getBalanceType()); - // TODO : verify if we need rhsChanged AND participatingElementsChanged - if (lfParameters.isDistributedSlack()) { - rhsChanged = participatingElements.stream().anyMatch(element -> disabledBuses.contains(element.getLfBus())); - } + participatingElementsChanged = isDistributedSlackOnGenerators(lfParameters) && !contingency.getGeneratorIdsToLose().isEmpty() + || isDistributedSlackOnLoads(lfParameters) && !contingency.getLoadIdsToLoose().isEmpty(); if (factorGroups.hasMultiVariables()) { Set impactedBuses = lfContingency.getLoadAndGeneratorBuses(); impactedBuses.addAll(disabledBuses); rhsChanged = rescaleGlsk(factorGroups, impactedBuses); } - if (rhsChanged) { - newParticipatingElements = lfParameters.isDistributedSlack() - ? getParticipatingElements(slackConnectedComponent, lfParameters.getBalanceType(), lfParametersExt) // will also be used to recompute the loadflow - : Collections.emptyList(); - } - - participatingElementsChanged = isDistributedSlackOnGenerators(lfParameters) && !contingency.getGeneratorIdsToLose().isEmpty() - || isDistributedSlackOnLoads(lfParameters) && !contingency.getLoadIdsToLoose().isEmpty(); if (participatingElementsChanged) { if (isDistributedSlackOnGenerators(lfParameters)) { // deep copy of participatingElements, removing the participating LfGeneratorImpl whose targetP has been set to 0 @@ -374,7 +364,7 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo } // we need to recompute the factor states because the rhs has changed or - if (participatingElementsChanged || rhsChanged) { + if (participatingElementsChanged || rhsChanged || hasRhsChangedDueToConnectivityBreak) { newFactorStates = calculateFactorStates(loadFlowContext, factorGroups, newParticipatingElements); } @@ -394,9 +384,61 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo contingency, resultWriter, disabledNetwork); networkState.restore(); - if (participatingElementsChanged || rhsChanged) { + if (participatingElementsChanged || rhsChanged || hasRhsChangedDueToConnectivityBreak) { setBaseCaseSensitivityValues(factorGroups, factorStates); // we modified the rhs, we need to restore previous state } +// } + } + + private void processContingenciesBreakingConnectivity(ConnectivityBreakAnalysis.ConnectivityAnalysisResult connectivityAnalysisResult, DcLoadFlowContext loadFlowContext, + LoadFlowParameters lfParameters, OpenLoadFlowParameters lfParametersExt, + SensitivityFactorHolder validFactorHolder, + SensitivityFactorGroupList factorGroups, + List participatingElements, + Map contingencyElementByBranch, + DenseMatrix flowStates, DenseMatrix factorsStates, DenseMatrix contingenciesStates, + SensitivityResultWriter resultWriter, + ReportNode reportNode) { + + PropagatedContingency contingency = connectivityAnalysisResult.getPropagatedContingency(); + Set disabledBuses = connectivityAnalysisResult.getDisabledBuses(); + Set partialDisabledBranches = connectivityAnalysisResult.getPartialDisabledBranches(); + + // as we are processing a contingency with connectivity break, we have to reset active power flow of a hvdc line + // if one bus of the line is lost. + for (LfHvdc hvdc : loadFlowContext.getNetwork().getHvdcs()) { + if (Networks.isIsolatedBusForHvdc(hvdc.getBus1(), disabledBuses) ^ Networks.isIsolatedBusForHvdc(hvdc.getBus2(), disabledBuses)) { + contingency.getGeneratorIdsToLose().add(hvdc.getConverterStation1().getId()); + contingency.getGeneratorIdsToLose().add(hvdc.getConverterStation2().getId()); + } + } + + // null and unused if slack bus is not distributed + List participatingElementsForThisConnectivity = participatingElements; + boolean rhsChanged = false; // true if the disabled buses change the slack distribution, or the GLSK + if (lfParameters.isDistributedSlack()) { + rhsChanged = participatingElements.stream().anyMatch(element -> disabledBuses.contains(element.getLfBus())); + } + if (factorGroups.hasMultiVariables()) { + // some elements of the GLSK may not be in the connected component anymore, we recompute the injections + rhsChanged |= rescaleGlsk(factorGroups, disabledBuses); + } + + // we need to recompute the participating elements because the connectivity changed + if (rhsChanged) { + participatingElementsForThisConnectivity = lfParameters.isDistributedSlack() + ? getParticipatingElements(connectivityAnalysisResult.getSlackConnectedComponent(), lfParameters.getBalanceType(), lfParametersExt) // will also be used to recompute the loadflow + : Collections.emptyList(); + + // calcul de l'injection + } + + // calcul du flow + + calculateSensitivityValuesForAContingency(loadFlowContext, lfParametersExt, + validFactorHolder, factorGroups, factorsStates, contingenciesStates, flowStates, + contingency, contingencyElementByBranch, disabledBuses, participatingElementsForThisConnectivity, + connectivityAnalysisResult.getElementsToReconnect(), resultWriter, reportNode, partialDisabledBranches, rhsChanged); } protected void cleanContingencies(LfNetwork lfNetwork, List contingencies) { @@ -560,28 +602,16 @@ public void analyse(Network network, List contingencies, for (PropagatedContingency contingency : connectivityBreakAnalysisResults.nonBreakingConnectivityContingencies()) { calculateSensitivityValuesForAContingency(loadFlowContext, lfParametersExt, validFactorHolder, factorGroups, factorsStates, connectivityBreakAnalysisResults.contingenciesStates(), flowStates, contingency, - connectivityBreakAnalysisResults.contingencyElementByBranch(), Collections.emptySet(), participatingElements, Collections.emptySet(), resultWriter, reportNode, Collections.emptySet(), - lfNetwork.getBuses()); + connectivityBreakAnalysisResults.contingencyElementByBranch(), Collections.emptySet(), participatingElements, Collections.emptySet(), resultWriter, reportNode, Collections.emptySet(), false); } LOGGER.info("Processing contingencies with connectivity break"); // process contingencies with connectivity break for (ConnectivityBreakAnalysis.ConnectivityAnalysisResult connectivityAnalysisResult : connectivityBreakAnalysisResults.connectivityAnalysisResults()) { - Set disabledBuses = connectivityAnalysisResult.getDisabledBuses(); - PropagatedContingency contingency = connectivityAnalysisResult.getPropagatedContingency(); - - for (LfHvdc hvdc : loadFlowContext.getNetwork().getHvdcs()) { - if (Networks.isIsolatedBusForHvdc(hvdc.getBus1(), disabledBuses) ^ Networks.isIsolatedBusForHvdc(hvdc.getBus2(), disabledBuses)) { - contingency.getGeneratorIdsToLose().add(hvdc.getConverterStation1().getId()); - contingency.getGeneratorIdsToLose().add(hvdc.getConverterStation2().getId()); - } - } - - calculateSensitivityValuesForAContingency(loadFlowContext, lfParametersExt, - validFactorHolder, factorGroups, factorsStates, connectivityBreakAnalysisResults.contingenciesStates(), flowStates, - contingency, connectivityBreakAnalysisResults.contingencyElementByBranch(), disabledBuses, participatingElements, - connectivityAnalysisResult.getElementsToReconnect(), resultWriter, reportNode, connectivityAnalysisResult.getPartialDisabledBranches(), connectivityAnalysisResult.getSlackConnectedComponent()); + processContingenciesBreakingConnectivity(connectivityAnalysisResult, loadFlowContext, lfParameters, lfParametersExt, + validFactorHolder, factorGroups, participatingElements, connectivityBreakAnalysisResults.contingencyElementByBranch(), + flowStates, factorsStates, connectivityBreakAnalysisResults.contingenciesStates(), resultWriter, reportNode); } } From d819cfb54965a3547d83d30d3d443078b9434977 Mon Sep 17 00:00:00 2001 From: p-arvy Date: Tue, 9 Jul 2024 14:23:43 +0200 Subject: [PATCH 12/16] Revert "Remove distinction of cases with/without generator or load lost" This reverts commit 1d3eaad3f8077c9ca7ab61877eb8ce3095b0969a. --- .../sensi/DcSensitivityAnalysis.java | 136 +++++++++++------- 1 file changed, 81 insertions(+), 55 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index 2bdbcac76b..4e220bab3b 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -327,67 +327,97 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo disabledBranches.addAll(partialDisabledBranches); DisabledNetwork disabledNetwork = new DisabledNetwork(disabledBuses, disabledBranches); - DcLoadFlowParameters lfParameters = loadFlowContext.getParameters(); - NetworkState networkState = NetworkState.save(lfNetwork); - LfContingency lfContingency = contingency.toLfContingency(lfNetwork).orElse(null); - DenseMatrix newFactorStates = factorStates; - List newParticipatingElements = participatingElements; - boolean participatingElementsChanged = false; - boolean rhsChanged = false; - if (lfContingency != null) { - lfContingency.apply(lfParameters.getBalanceType()); - participatingElementsChanged = isDistributedSlackOnGenerators(lfParameters) && !contingency.getGeneratorIdsToLose().isEmpty() - || isDistributedSlackOnLoads(lfParameters) && !contingency.getLoadIdsToLoose().isEmpty(); - if (factorGroups.hasMultiVariables()) { - Set impactedBuses = lfContingency.getLoadAndGeneratorBuses(); - impactedBuses.addAll(disabledBuses); - rhsChanged = rescaleGlsk(factorGroups, impactedBuses); + if (contingency.getGeneratorIdsToLose().isEmpty() && contingency.getLoadIdsToLoose().isEmpty()) { + DenseMatrix newFactorStates = factorStates; + DenseMatrix newFlowStates = flowStates; + + // we need to recompute the factor states because the connectivity changed + if (hasRhsChangedDueToConnectivityBreak) { + newFactorStates = calculateFactorStates(loadFlowContext, factorGroups, participatingElements); } - if (participatingElementsChanged) { - if (isDistributedSlackOnGenerators(lfParameters)) { - // deep copy of participatingElements, removing the participating LfGeneratorImpl whose targetP has been set to 0 - Set participatingGeneratorsToRemove = lfContingency.getLostGenerators(); - newParticipatingElements = participatingElements.stream() - .filter(participatingElement -> !participatingGeneratorsToRemove.contains(participatingElement.getElement())) - .map(participatingElement -> new ParticipatingElement(participatingElement.getElement(), participatingElement.getFactor())) - .collect(Collectors.toList()); - normalizeParticipationFactors(newParticipatingElements); - } else { // slack distribution on loads - newParticipatingElements = getParticipatingElements(lfNetwork.getBuses(), lfParameters.getBalanceType(), lfParametersExt); + + if (!factors.isEmpty()) { + Set lostTransformers = contingency.getBranchIdsToOpen().keySet().stream() + .filter(element -> !elementsToReconnect.contains(element)) + .map(contingencyElementByBranch::get) + .map(ComputedContingencyElement::getLfBranch) + .filter(LfBranch::hasPhaseControllerCapability) + .collect(Collectors.toSet()); + + // if a phase tap changer is lost or if connectivity changed, recompute load flows + if (!disabledBuses.isEmpty() || !lostTransformers.isEmpty()) { + DisabledNetwork disabledNetworkWithPstLost = new DisabledNetwork(disabledBuses, lostTransformers); + newFlowStates = calculateActivePowerFlows(loadFlowContext, factors, participatingElements, disabledNetworkWithPstLost, reportNode); } } + + calculateSensitivityValues(loadFlowContext, factors, newFactorStates, contingenciesStates, newFlowStates, contingencyElements, + contingency, resultWriter, disabledNetwork); + + if (hasRhsChangedDueToConnectivityBreak) { + setBaseCaseSensitivityValues(factorGroups, factorStates); // we modified the rhs, we need to restore previous state + } + // write contingency status - resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.SUCCESS); + if (contingency.hasNoImpact()) { + resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.NO_IMPACT); + } else { + resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.SUCCESS); + } } else { - // write contingency status - resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.NO_IMPACT); - } + // if we have a contingency including the loss of a DC line or a generator or a load + // save base state for later restoration after each contingency + DcLoadFlowParameters lfParameters = loadFlowContext.getParameters(); + NetworkState networkState = NetworkState.save(lfNetwork); + LfContingency lfContingency = contingency.toLfContingency(lfNetwork).orElse(null); + DenseMatrix newFactorStates = factorStates; + List newParticipatingElements = participatingElements; + boolean participatingElementsChanged = false; + boolean rhsChanged = false; + if (lfContingency != null) { + lfContingency.apply(lfParameters.getBalanceType()); + participatingElementsChanged = isDistributedSlackOnGenerators(lfParameters) && !contingency.getGeneratorIdsToLose().isEmpty() + || isDistributedSlackOnLoads(lfParameters) && !contingency.getLoadIdsToLoose().isEmpty(); + if (factorGroups.hasMultiVariables()) { + Set impactedBuses = lfContingency.getLoadAndGeneratorBuses(); + rhsChanged = rescaleGlsk(factorGroups, impactedBuses); + } + if (participatingElementsChanged) { + if (isDistributedSlackOnGenerators(lfParameters)) { + // deep copy of participatingElements, removing the participating LfGeneratorImpl whose targetP has been set to 0 + Set participatingGeneratorsToRemove = lfContingency.getLostGenerators(); + newParticipatingElements = participatingElements.stream() + .filter(participatingElement -> !participatingGeneratorsToRemove.contains(participatingElement.getElement())) + .map(participatingElement -> new ParticipatingElement(participatingElement.getElement(), participatingElement.getFactor())) + .collect(Collectors.toList()); + normalizeParticipationFactors(newParticipatingElements); + } else { // slack distribution on loads + newParticipatingElements = getParticipatingElements(lfNetwork.getBuses(), lfParameters.getBalanceType(), lfParametersExt); + } + } + // write contingency status + resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.SUCCESS); + } else { + // write contingency status + resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.NO_IMPACT); + } - // we need to recompute the factor states because the rhs has changed or - if (participatingElementsChanged || rhsChanged || hasRhsChangedDueToConnectivityBreak) { - newFactorStates = calculateFactorStates(loadFlowContext, factorGroups, newParticipatingElements); - } + // we need to recompute the factor states because the rhs has changed or + if (participatingElementsChanged || rhsChanged || hasRhsChangedDueToConnectivityBreak) { + newFactorStates = calculateFactorStates(loadFlowContext, factorGroups, newParticipatingElements); + } - Set lostTransformers = contingency.getBranchIdsToOpen().keySet().stream() - .filter(element -> !elementsToReconnect.contains(element)) - .map(contingencyElementByBranch::get) - .map(ComputedContingencyElement::getLfBranch) - .filter(LfBranch::hasPhaseControllerCapability) - .collect(Collectors.toSet()); - DenseMatrix newFlowStates = flowStates; - if (!contingency.getLoadIdsToLoose().isEmpty() || !contingency.getGeneratorIdsToLose().isEmpty() || - !disabledBuses.isEmpty() || !lostTransformers.isEmpty()) { - newFlowStates = calculateActivePowerFlows(loadFlowContext, factors, newParticipatingElements, disabledNetwork, reportNode); - } + DenseMatrix newFlowStates = calculateActivePowerFlows(loadFlowContext, factors, + newParticipatingElements, disabledNetwork, reportNode); - calculateSensitivityValues(loadFlowContext, factors, newFactorStates, contingenciesStates, newFlowStates, contingencyElements, - contingency, resultWriter, disabledNetwork); + calculateSensitivityValues(loadFlowContext, factors, newFactorStates, contingenciesStates, newFlowStates, contingencyElements, + contingency, resultWriter, disabledNetwork); - networkState.restore(); - if (participatingElementsChanged || rhsChanged || hasRhsChangedDueToConnectivityBreak) { - setBaseCaseSensitivityValues(factorGroups, factorStates); // we modified the rhs, we need to restore previous state + networkState.restore(); + if (participatingElementsChanged || rhsChanged || hasRhsChangedDueToConnectivityBreak) { + setBaseCaseSensitivityValues(factorGroups, factorStates); // we modified the rhs, we need to restore previous state + } } -// } } private void processContingenciesBreakingConnectivity(ConnectivityBreakAnalysis.ConnectivityAnalysisResult connectivityAnalysisResult, DcLoadFlowContext loadFlowContext, @@ -429,12 +459,8 @@ private void processContingenciesBreakingConnectivity(ConnectivityBreakAnalysis. participatingElementsForThisConnectivity = lfParameters.isDistributedSlack() ? getParticipatingElements(connectivityAnalysisResult.getSlackConnectedComponent(), lfParameters.getBalanceType(), lfParametersExt) // will also be used to recompute the loadflow : Collections.emptyList(); - - // calcul de l'injection } - // calcul du flow - calculateSensitivityValuesForAContingency(loadFlowContext, lfParametersExt, validFactorHolder, factorGroups, factorsStates, contingenciesStates, flowStates, contingency, contingencyElementByBranch, disabledBuses, participatingElementsForThisConnectivity, From f9f7f5ae50ab54307254a131d57d5d659bf996ba Mon Sep 17 00:00:00 2001 From: p-arvy Date: Tue, 9 Jul 2024 16:47:33 +0200 Subject: [PATCH 13/16] Fix comment. Signed-off-by: p-arvy --- .../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 4e220bab3b..bcc724536e 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -402,7 +402,7 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.NO_IMPACT); } - // we need to recompute the factor states because the rhs has changed or + // we need to recompute the factor states because the rhs or the participating elements have changed if (participatingElementsChanged || rhsChanged || hasRhsChangedDueToConnectivityBreak) { newFactorStates = calculateFactorStates(loadFlowContext, factorGroups, newParticipatingElements); } From dbda9e5a2cfd0e0529f01637d4541017c6f82aad Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Wed, 10 Jul 2024 09:38:03 +0200 Subject: [PATCH 14/16] Small clean. Signed-off-by: Anne Tilloy --- .../sensi/DcSensitivityAnalysis.java | 74 ++++++++++--------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index bcc724536e..004c735658 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -308,15 +308,22 @@ private static double calculatePower(DcLoadFlowContext loadFlowContext, LfBranch /** * Calculate sensitivity values for a post-contingency state. - * When a contingency involves the loss of a load or a generator, the slack distribution could be changed - * or the sensitivity factors in case of GLSK. + * In case of connectivity break, a pre-computation has been done to get a first version of the new participating + * elements, that can be overridden in this method. + * TODO Pierre: better description here */ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlowContext, OpenLoadFlowParameters lfParametersExt, SensitivityFactorHolder validFactorHolder, - SensitivityFactorGroupList factorGroups, DenseMatrix factorStates, DenseMatrix contingenciesStates, DenseMatrix flowStates, - PropagatedContingency contingency, Map contingencyElementByBranch, - Set disabledBuses, List participatingElements, Set elementsToReconnect, - SensitivityResultWriter resultWriter, ReportNode reportNode, Set partialDisabledBranches, boolean hasRhsChangedDueToConnectivityBreak) { + SensitivityFactorGroupList factorGroups, DenseMatrix factorStates, DenseMatrix contingenciesStates, DenseMatrix flowStates, + PropagatedContingency contingency, Map contingencyElementByBranch, + Set disabledBuses, List participatingElements, Set elementsToReconnect, + SensitivityResultWriter resultWriter, ReportNode reportNode, Set partialDisabledBranches, boolean rhsChangedAfterConnectivityBreak) { List> factors = validFactorHolder.getFactorsForContingency(contingency.getContingency().getId()); + if (factors.isEmpty()) { + // no factor no more computation + resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.FAILURE); + return; + } + Collection contingencyElements = contingency.getBranchIdsToOpen().keySet().stream() .filter(element -> !elementsToReconnect.contains(element)) .map(contingencyElementByBranch::get) @@ -326,36 +333,34 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo Set disabledBranches = contingency.getBranchIdsToOpen().keySet().stream().map(lfNetwork::getBranchById).collect(Collectors.toSet()); disabledBranches.addAll(partialDisabledBranches); DisabledNetwork disabledNetwork = new DisabledNetwork(disabledBuses, disabledBranches); + DenseMatrix newFactorStates = factorStates; if (contingency.getGeneratorIdsToLose().isEmpty() && contingency.getLoadIdsToLoose().isEmpty()) { - DenseMatrix newFactorStates = factorStates; DenseMatrix newFlowStates = flowStates; - // we need to recompute the factor states because the connectivity changed - if (hasRhsChangedDueToConnectivityBreak) { + if (rhsChangedAfterConnectivityBreak) { newFactorStates = calculateFactorStates(loadFlowContext, factorGroups, participatingElements); } - if (!factors.isEmpty()) { - Set lostTransformers = contingency.getBranchIdsToOpen().keySet().stream() - .filter(element -> !elementsToReconnect.contains(element)) - .map(contingencyElementByBranch::get) - .map(ComputedContingencyElement::getLfBranch) - .filter(LfBranch::hasPhaseControllerCapability) - .collect(Collectors.toSet()); - - // if a phase tap changer is lost or if connectivity changed, recompute load flows - if (!disabledBuses.isEmpty() || !lostTransformers.isEmpty()) { - DisabledNetwork disabledNetworkWithPstLost = new DisabledNetwork(disabledBuses, lostTransformers); - newFlowStates = calculateActivePowerFlows(loadFlowContext, factors, participatingElements, disabledNetworkWithPstLost, reportNode); - } + // get the lost phase tap changers for this contingency + Set lostPhaseControllers = contingency.getBranchIdsToOpen().keySet().stream() + .filter(element -> !elementsToReconnect.contains(element)) + .map(contingencyElementByBranch::get) + .map(ComputedContingencyElement::getLfBranch) + .filter(LfBranch::hasPhaseControllerCapability) + .collect(Collectors.toSet()); + + // if a phase tap changer is lost or if the connectivity have changed, we must recompute load flows + if (!disabledBuses.isEmpty() || !lostPhaseControllers.isEmpty()) { + newFlowStates = calculateActivePowerFlows(loadFlowContext, factors, participatingElements, disabledNetwork, reportNode); } calculateSensitivityValues(loadFlowContext, factors, newFactorStates, contingenciesStates, newFlowStates, contingencyElements, contingency, resultWriter, disabledNetwork); - if (hasRhsChangedDueToConnectivityBreak) { - setBaseCaseSensitivityValues(factorGroups, factorStates); // we modified the rhs, we need to restore previous state + if (rhsChangedAfterConnectivityBreak) { + // we modified the rhs, we need to restore previous state + setBaseCaseSensitivityValues(factorGroups, factorStates); } // write contingency status @@ -369,18 +374,17 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo // save base state for later restoration after each contingency DcLoadFlowParameters lfParameters = loadFlowContext.getParameters(); NetworkState networkState = NetworkState.save(lfNetwork); - LfContingency lfContingency = contingency.toLfContingency(lfNetwork).orElse(null); - DenseMatrix newFactorStates = factorStates; List newParticipatingElements = participatingElements; boolean participatingElementsChanged = false; - boolean rhsChanged = false; + boolean rhsChangedAfterGlskRescaling = false; + LfContingency lfContingency = contingency.toLfContingency(lfNetwork).orElse(null); if (lfContingency != null) { lfContingency.apply(lfParameters.getBalanceType()); participatingElementsChanged = isDistributedSlackOnGenerators(lfParameters) && !contingency.getGeneratorIdsToLose().isEmpty() || isDistributedSlackOnLoads(lfParameters) && !contingency.getLoadIdsToLoose().isEmpty(); if (factorGroups.hasMultiVariables()) { Set impactedBuses = lfContingency.getLoadAndGeneratorBuses(); - rhsChanged = rescaleGlsk(factorGroups, impactedBuses); + rhsChangedAfterGlskRescaling = rescaleGlsk(factorGroups, impactedBuses); } if (participatingElementsChanged) { if (isDistributedSlackOnGenerators(lfParameters)) { @@ -403,23 +407,26 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo } // we need to recompute the factor states because the rhs or the participating elements have changed - if (participatingElementsChanged || rhsChanged || hasRhsChangedDueToConnectivityBreak) { + if (participatingElementsChanged || rhsChangedAfterGlskRescaling || rhsChangedAfterConnectivityBreak) { newFactorStates = calculateFactorStates(loadFlowContext, factorGroups, newParticipatingElements); } - DenseMatrix newFlowStates = calculateActivePowerFlows(loadFlowContext, factors, - newParticipatingElements, disabledNetwork, reportNode); + DenseMatrix newFlowStates = calculateActivePowerFlows(loadFlowContext, factors, newParticipatingElements, disabledNetwork, reportNode); calculateSensitivityValues(loadFlowContext, factors, newFactorStates, contingenciesStates, newFlowStates, contingencyElements, contingency, resultWriter, disabledNetwork); networkState.restore(); - if (participatingElementsChanged || rhsChanged || hasRhsChangedDueToConnectivityBreak) { - setBaseCaseSensitivityValues(factorGroups, factorStates); // we modified the rhs, we need to restore previous state + if (participatingElementsChanged || rhsChangedAfterGlskRescaling || rhsChangedAfterConnectivityBreak) { + // we modified the rhs, we need to restore previous state + setBaseCaseSensitivityValues(factorGroups, factorStates); } } } + /** + * TODO Pierre: add a description here + */ private void processContingenciesBreakingConnectivity(ConnectivityBreakAnalysis.ConnectivityAnalysisResult connectivityAnalysisResult, DcLoadFlowContext loadFlowContext, LoadFlowParameters lfParameters, OpenLoadFlowParameters lfParametersExt, SensitivityFactorHolder validFactorHolder, @@ -443,7 +450,6 @@ private void processContingenciesBreakingConnectivity(ConnectivityBreakAnalysis. } } - // null and unused if slack bus is not distributed List participatingElementsForThisConnectivity = participatingElements; boolean rhsChanged = false; // true if the disabled buses change the slack distribution, or the GLSK if (lfParameters.isDistributedSlack()) { From 63c3c650a84745fde759c60e62d690079fbdb1a7 Mon Sep 17 00:00:00 2001 From: p-arvy Date: Wed, 10 Jul 2024 12:34:58 +0200 Subject: [PATCH 15/16] Add comments. Signed-off-by: p-arvy --- .../openloadflow/sensi/DcSensitivityAnalysis.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index 004c735658..21727bf915 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -307,10 +307,12 @@ private static double calculatePower(DcLoadFlowContext loadFlowContext, LfBranch } /** - * Calculate sensitivity values for a post-contingency state. - * In case of connectivity break, a pre-computation has been done to get a first version of the new participating - * elements, that can be overridden in this method. - * TODO Pierre: better description here + * Calculate sensitivity values for a contingency. + * In case of connectivity break, a pre-computation has been done in {@link #processContingenciesBreakingConnectivity} + * to get a first version of the new participating elements, that can be overridden in this method, and to indicate + * if the factorsStates should be overridden or not in this method. + * If connectivity, a generator, a load or a phase tap changer is lost due to the contingency, + * the flowStates are overridden. */ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlowContext, OpenLoadFlowParameters lfParametersExt, SensitivityFactorHolder validFactorHolder, SensitivityFactorGroupList factorGroups, DenseMatrix factorStates, DenseMatrix contingenciesStates, DenseMatrix flowStates, @@ -425,7 +427,9 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo } /** - * TODO Pierre: add a description here + * Calculate sensitivity values for a contingency breaking connectivity. + * It determines if the right hand side has been changed due to the contingency, e.g. when the slack distribution is + * impacted by the disabled buses. If so, factorsStates will be overridden in {@link #calculateSensitivityValuesForAContingency}. */ private void processContingenciesBreakingConnectivity(ConnectivityBreakAnalysis.ConnectivityAnalysisResult connectivityAnalysisResult, DcLoadFlowContext loadFlowContext, LoadFlowParameters lfParameters, OpenLoadFlowParameters lfParametersExt, From 8b27b1f7e6c774b50e1b714c1865815964658c83 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Fri, 12 Jul 2024 13:53:03 +0200 Subject: [PATCH 16/16] Fix. Signed-off-by: Anne Tilloy --- .../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 004c735658..12103b9223 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -320,7 +320,7 @@ private void calculateSensitivityValuesForAContingency(DcLoadFlowContext loadFlo List> factors = validFactorHolder.getFactorsForContingency(contingency.getContingency().getId()); if (factors.isEmpty()) { // no factor no more computation - resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.FAILURE); + resultWriter.writeContingencyStatus(contingency.getIndex(), SensitivityAnalysisResult.Status.SUCCESS); return; }