Skip to content

Commit 3c49e59

Browse files
authored
Bug fix: support of factors with SKIP status after contingencies (#476)
Signed-off-by: Anne Tilloy <anne.tilloy@rte-france.com> Signed-off-by: Geoffroy Jamgotchian <geoffroy.jamgotchian@rte-france.com>
1 parent 055b406 commit 3c49e59

File tree

5 files changed

+95
-73
lines changed

5 files changed

+95
-73
lines changed

src/main/java/com/powsybl/openloadflow/sensi/AbstractSensitivityAnalysis.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -556,9 +556,6 @@ protected List<SensitivityFactorGroup<V, E>> createFactorGroups(List<LfSensitivi
556556
Map<Pair<SensitivityVariableType, String>, SensitivityFactorGroup<V, E>> groupIndexedById = new LinkedHashMap<>(factors.size());
557557
// index factors by variable config
558558
for (LfSensitivityFactor<V, E> factor : factors) {
559-
if (factor.getStatus() == LfSensitivityFactor.Status.SKIP) {
560-
continue;
561-
}
562559
Pair<SensitivityVariableType, String> id = Pair.of(factor.getVariableType(), factor.getVariableId());
563560
if (factor instanceof SingleVariableLfSensitivityFactor) {
564561
SingleVariableLfSensitivityFactor<V, E> singleVarFactor = (SingleVariableLfSensitivityFactor<V, E>) factor;
@@ -635,6 +632,8 @@ protected void setPredefinedResults(Collection<LfSensitivityFactor<V, E>> lfFact
635632
if (!factor.isFunctionConnectedToSlackComponent(connectedComponent)) {
636633
factor.setFunctionPredefinedResult(Double.NaN);
637634
}
635+
} else {
636+
throw new IllegalStateException("Unexpected factor status: " + factor.getStatus());
638637
}
639638
}
640639
}
@@ -651,18 +650,32 @@ protected boolean rescaleGlsk(List<SensitivityFactorGroup<V, E>> factorGroups, S
651650
return rescaled;
652651
}
653652

654-
protected void writeSkippedFactors(Collection<LfSensitivityFactor<V, E>> lfFactors, SensitivityValueWriter valueWriter) {
655-
List<LfSensitivityFactor<V, E>> skippedFactors = lfFactors.stream().filter(factor -> factor.getStatus() == LfSensitivityFactor.Status.SKIP).collect(Collectors.toList());
656-
657-
// SKIP factors are for factors where both variable and function elements are not in the main connected componant.
658-
// Therefore, their sensitivity and reference values are set to NaN.
659-
skippedFactors.forEach(factor -> valueWriter.write(factor.getIndex(), -1, Double.NaN, Double.NaN));
660-
661-
Set<String> skippedVariables = skippedFactors.stream().map(LfSensitivityFactor::getVariableId).collect(Collectors.toSet());
653+
/**
654+
* Write zero or skip factors to output and send a new factor holder containing only other valid ones.
655+
* IMPORTANT: this is only a base case test (factor status only deal with base case). We do not output anything
656+
* on post contingency if factor is already invalid (skip o zero) on base case.
657+
*/
658+
protected SensitivityFactorHolder<V, E> writeInvalidFactors(SensitivityFactorHolder<V, E> factorHolder, SensitivityValueWriter valueWriter) {
659+
Set<String> skippedVariables = new LinkedHashSet<>();
660+
SensitivityFactorHolder<V, E> validFactorHolder = new SensitivityFactorHolder<>();
661+
for (var factor : factorHolder.getAllFactors()) {
662+
// directly write output for zero and invalid factors
663+
if (factor.getStatus() == LfSensitivityFactor.Status.ZERO) {
664+
// ZERO status is for factors where variable element is in the main connected component and reference element is not.
665+
// Therefore, the sensitivity is known to value 0, but the reference cannot be known and is set to NaN.
666+
valueWriter.write(factor.getIndex(), -1, 0, Double.NaN);
667+
} else if (factor.getStatus() == LfSensitivityFactor.Status.SKIP) {
668+
valueWriter.write(factor.getIndex(), -1, Double.NaN, Double.NaN);
669+
skippedVariables.add(factor.getVariableId());
670+
} else {
671+
validFactorHolder.addFactor(factor);
672+
}
673+
}
662674
if (!skippedVariables.isEmpty() && LOGGER.isWarnEnabled()) {
663675
LOGGER.warn("Skipping all factors with variables: '{}', as they cannot be found in the network",
664676
String.join(", ", skippedVariables));
665677
}
678+
return validFactorHolder;
666679
}
667680

668681
public void checkContingencies(LfNetwork lfNetwork, List<PropagatedContingency> contingencies) {

src/main/java/com/powsybl/openloadflow/sensi/AcSensitivityAnalysis.java

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,7 @@ public AcSensitivityAnalysis(MatrixFactory matrixFactory, GraphDecrementalConnec
4949
private void calculateSensitivityValues(List<LfSensitivityFactor<AcVariableType, AcEquationType>> lfFactors, List<SensitivityFactorGroup<AcVariableType, AcEquationType>> factorGroups, DenseMatrix factorsState,
5050
int contingencyIndex, SensitivityValueWriter valueWriter) {
5151
Set<LfSensitivityFactor<AcVariableType, AcEquationType>> lfFactorsSet = new HashSet<>(lfFactors);
52-
// ZERO status is for factors where variable element is in the main connected component and reference element is not.
53-
// Therefore, the sensitivity is known to value 0, but the reference cannot be known and is set to NaN.
54-
lfFactors.stream().filter(factor -> factor.getStatus() == LfSensitivityFactor.Status.ZERO)
55-
.forEach(factor -> valueWriter.write(factor.getIndex(), contingencyIndex, 0, Double.NaN));
52+
5653
// VALID_ONLY_FOR_FUNCTION status is for factors where variable element is not in the main connected component but reference element is.
5754
// Therefore, the sensitivity is known to value 0 and the reference value can be computed.
5855
lfFactors.stream().filter(factor -> factor.getStatus() == LfSensitivityFactor.Status.VALID_ONLY_FOR_FUNCTION)
@@ -208,16 +205,13 @@ public void analyse(Network network, List<PropagatedContingency> contingencies,
208205
);
209206

210207
Map<String, SensitivityVariableSet> variableSetsById = variableSets.stream().collect(Collectors.toMap(SensitivityVariableSet::getId, Function.identity()));
211-
SensitivityFactorHolder<AcVariableType, AcEquationType> factorHolder = readAndCheckFactors(network, variableSetsById, factorReader, lfNetwork);
212-
List<LfSensitivityFactor<AcVariableType, AcEquationType>> lfFactors = factorHolder.getAllFactors();
213-
LOGGER.info("Running AC sensitivity analysis with {} factors and {} contingencies", lfFactors.size(), contingencies.size());
208+
SensitivityFactorHolder<AcVariableType, AcEquationType> allFactorHolder = readAndCheckFactors(network, variableSetsById, factorReader, lfNetwork);
209+
List<LfSensitivityFactor<AcVariableType, AcEquationType>> allLfFactors = allFactorHolder.getAllFactors();
210+
LOGGER.info("Running AC sensitivity analysis with {} factors and {} contingencies", allLfFactors.size(), contingencies.size());
214211

215-
writeSkippedFactors(lfFactors, valueWriter);
216212
// next we only work with valid and valid only for function factors
217-
List<LfSensitivityFactor.Status> validFactors = new ArrayList<>();
218-
validFactors.add(LfSensitivityFactor.Status.VALID);
219-
validFactors.add(LfSensitivityFactor.Status.VALID_ONLY_FOR_FUNCTION);
220-
lfFactors = lfFactors.stream().filter(factor -> validFactors.contains(factor.getStatus())).collect(Collectors.toList());
213+
var validFactorHolder = writeInvalidFactors(allFactorHolder, valueWriter);
214+
var validLfFactors = validFactorHolder.getAllFactors();
221215

222216
// create AC engine
223217
AcLoadFlowParameters acParameters = OpenLoadFlowParameters.createAcParameters(network, lfParameters, lfParametersExt, matrixFactory, connectivityFactory, reporter, false, true);
@@ -228,7 +222,7 @@ public void analyse(Network network, List<PropagatedContingency> contingencies,
228222
.run(reporter);
229223

230224
// index factors by variable group to compute a minimal number of states
231-
List<SensitivityFactorGroup<AcVariableType, AcEquationType>> factorGroups = createFactorGroups(lfFactors.stream()
225+
List<SensitivityFactorGroup<AcVariableType, AcEquationType>> factorGroups = createFactorGroups(validLfFactors.stream()
232226
.filter(factor -> factor.getStatus() == LfSensitivityFactor.Status.VALID).collect(Collectors.toList()));
233227

234228
// compute the participation for each injection factor (+1 on the injection and then -participation factor on all
@@ -269,8 +263,8 @@ public void analyse(Network network, List<PropagatedContingency> contingencies,
269263
context.getJacobianMatrix().solveTransposed(factorsStates);
270264

271265
// calculate sensitivity values
272-
setFunctionReferences(lfFactors);
273-
calculateSensitivityValues(factorHolder.getFactorsForBaseNetwork(), factorGroups, factorsStates, -1, valueWriter);
266+
setFunctionReferences(validLfFactors);
267+
calculateSensitivityValues(validFactorHolder.getFactorsForBaseNetwork(), factorGroups, factorsStates, -1, valueWriter);
274268

275269
GraphDecrementalConnectivity<LfBus> connectivity = lfNetwork.getConnectivity();
276270

@@ -282,8 +276,7 @@ public void analyse(Network network, List<PropagatedContingency> contingencies,
282276

283277
// Contingency not breaking connectivity
284278
for (LfContingency lfContingency : lfContingencies.stream().filter(lfContingency -> lfContingency.getBuses().isEmpty()).collect(Collectors.toSet())) {
285-
List<LfSensitivityFactor<AcVariableType, AcEquationType>> contingencyFactors = factorHolder.getFactorsForContingency(lfContingency.getId());
286-
contingencyFactors = contingencyFactors.stream().filter(factor -> validFactors.contains(factor.getStatus())).collect(Collectors.toList());
279+
List<LfSensitivityFactor<AcVariableType, AcEquationType>> contingencyFactors = validFactorHolder.getFactorsForContingency(lfContingency.getId());
287280
contingencyFactors.forEach(lfFactor -> {
288281
lfFactor.setSensitivityValuePredefinedResult(null);
289282
lfFactor.setFunctionPredefinedResult(null);
@@ -303,8 +296,7 @@ public void analyse(Network network, List<PropagatedContingency> contingencies,
303296

304297
// Contingency breaking connectivity
305298
for (LfContingency lfContingency : lfContingencies.stream().filter(lfContingency -> !lfContingency.getBuses().isEmpty()).collect(Collectors.toSet())) {
306-
List<LfSensitivityFactor<AcVariableType, AcEquationType>> contingencyFactors = factorHolder.getFactorsForContingency(lfContingency.getId());
307-
contingencyFactors = contingencyFactors.stream().filter(factor -> validFactors.contains(factor.getStatus())).collect(Collectors.toList());
299+
List<LfSensitivityFactor<AcVariableType, AcEquationType>> contingencyFactors = validFactorHolder.getFactorsForContingency(lfContingency.getId());
308300
contingencyFactors.forEach(lfFactor -> {
309301
lfFactor.setSensitivityValuePredefinedResult(null);
310302
lfFactor.setFunctionPredefinedResult(null); });

0 commit comments

Comments
 (0)