Skip to content

Commit 95e5e82

Browse files
committed
Support component reconnection
Signed-off-by: Geoffroy Jamgotchian <geoffroy.jamgotchian@gmail.com>
1 parent 56f6044 commit 95e5e82

4 files changed

Lines changed: 124 additions & 46 deletions

File tree

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

Lines changed: 47 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ protected interface LfSensitivityFactor<V extends Enum<V> & Quantity, E extends
7575

7676
enum Status {
7777
VALID,
78-
SKIP,
79-
VALID_ONLY_FOR_FUNCTION,
80-
ZERO
78+
SKIP, // variable element and function element are not in the network
79+
VALID_ONLY_FOR_FUNCTION, // variable element is not in the network but function element is
80+
ZERO // variable element is in the network but function element is not
8181
}
8282

8383
int getIndex();
@@ -110,7 +110,9 @@ enum Status {
110110

111111
Status getStatus();
112112

113-
void setStatus(Status status);
113+
void updateStatus();
114+
115+
boolean couldBeValid();
114116

115117
boolean isVariableConnectedToSlackComponent(DisabledNetwork disabledNetwork);
116118

@@ -159,9 +161,6 @@ protected AbstractLfSensitivityFactor(int index, String variableId, String funct
159161
this.functionType = Objects.requireNonNull(functionType);
160162
this.variableType = Objects.requireNonNull(variableType);
161163
this.contingencyContext = Objects.requireNonNull(contingencyContext);
162-
if (functionElement == null) {
163-
status = Status.ZERO;
164-
}
165164
}
166165

167166
@Override
@@ -269,11 +268,6 @@ public Status getStatus() {
269268
return status;
270269
}
271270

272-
@Override
273-
public void setStatus(Status status) {
274-
this.status = status;
275-
}
276-
277271
protected boolean isElementConnectedToSlackComponent(LfElement element, DisabledNetwork disabledNetwork) {
278272
if (element instanceof LfBus) {
279273
return !disabledNetwork.getBuses().contains(element);
@@ -304,16 +298,31 @@ protected SingleVariableLfSensitivityFactor(int index, String variableId, String
304298
ContingencyContext contingencyContext) {
305299
super(index, variableId, functionId, functionElement, functionType, variableType, contingencyContext);
306300
this.variableElement = variableElement;
307-
if (variableElement == null) {
308-
status = functionElement == null ? Status.SKIP : Status.VALID_ONLY_FOR_FUNCTION;
301+
updateStatus();
302+
}
303+
304+
@Override
305+
public void updateStatus() {
306+
if (variableElement == null || variableElement.isDisabled()) {
307+
status = functionElement == null || functionElement.isDisabled() ? Status.SKIP : Status.VALID_ONLY_FOR_FUNCTION;
308+
} else {
309+
status = functionElement == null || functionElement.isDisabled() ? Status.ZERO : Status.VALID;
309310
}
310311
}
311312

313+
@Override
314+
public boolean couldBeValid() {
315+
return variableElement != null && functionElement != null;
316+
}
317+
312318
protected LfElement getVariableElement() {
313319
return variableElement;
314320
}
315321

316322
protected Equation<V, E> getVariableEquation() {
323+
if (variableElement == null) {
324+
return null;
325+
}
317326
switch (variableType) {
318327
case TRANSFORMER_PHASE, TRANSFORMER_PHASE_1, TRANSFORMER_PHASE_2, TRANSFORMER_PHASE_3:
319328
LfBranch lfBranch = (LfBranch) variableElement;
@@ -373,10 +382,22 @@ protected MultiVariablesLfSensitivityFactor(int index, String variableId, String
373382
ContingencyContext contingencyContext, Set<String> originalVariableSetIds) {
374383
super(index, variableId, functionId, functionElement, functionType, variableType, contingencyContext);
375384
this.weightedVariableElements = weightedVariableElements;
385+
this.originalVariableSetIds = originalVariableSetIds;
386+
updateStatus();
387+
}
388+
389+
@Override
390+
public void updateStatus() {
376391
if (weightedVariableElements.isEmpty()) {
377-
status = functionElement == null ? Status.SKIP : Status.VALID_ONLY_FOR_FUNCTION;
392+
status = functionElement == null || functionElement.isDisabled() ? Status.SKIP : Status.VALID_ONLY_FOR_FUNCTION;
393+
} else {
394+
status = functionElement == null || functionElement.isDisabled() ? Status.ZERO : Status.VALID;
378395
}
379-
this.originalVariableSetIds = originalVariableSetIds;
396+
}
397+
398+
@Override
399+
public boolean couldBeValid() {
400+
return functionElement != null && !weightedVariableElements.isEmpty();
380401
}
381402

382403
protected Map<LfElement, Double> getWeightedVariableElements() {
@@ -492,12 +513,15 @@ protected static class SingleVariableFactorGroup<V extends Enum<V> & Quantity, E
492513

493514
protected SingleVariableFactorGroup(LfElement variableElement, Equation<V, E> variableEquation, SensitivityVariableType variableType) {
494515
super(variableType);
495-
this.variableElement = Objects.requireNonNull(variableElement);
516+
this.variableElement = variableElement;
496517
this.variableEquation = variableEquation;
497518
}
498519

499520
@Override
500521
public void fillRhs(Matrix rhs, Map<LfBus, Double> participationByBus) {
522+
if (variableElement == null) {
523+
return;
524+
}
501525
switch (variableType) {
502526
case TRANSFORMER_PHASE, TRANSFORMER_PHASE_1, TRANSFORMER_PHASE_2, TRANSFORMER_PHASE_3:
503527
if (variableEquation.isActive()) {
@@ -699,6 +723,12 @@ protected Pair<Optional<Double>, Optional<Double>> getPredefinedResults(LfSensit
699723
if (!factor.isFunctionConnectedToSlackComponent(disabledNetwork)) {
700724
functionPredefinedResult = Double.NaN;
701725
}
726+
} else if (factor.getStatus() == LfSensitivityFactor.Status.ZERO) {
727+
sensitivityValuePredefinedResult = 0d;
728+
functionPredefinedResult = Double.NaN;
729+
} else if (factor.getStatus() == LfSensitivityFactor.Status.SKIP) {
730+
sensitivityValuePredefinedResult = Double.NaN;
731+
functionPredefinedResult = Double.NaN;
702732
} else {
703733
throw new IllegalStateException("Unexpected factor status: " + factor.getStatus());
704734
}

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

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -65,15 +65,6 @@ private void calculateSensitivityValues(List<LfSensitivityFactor<AcVariableType,
6565
int contingencyIndex, int operatorStrategyIndex, SensitivityResultWriter resultWriter) {
6666
Set<LfSensitivityFactor<AcVariableType, AcEquationType>> lfFactorsSet = new HashSet<>(lfFactors);
6767

68-
// VALID_ONLY_FOR_FUNCTION status is for factors where variable element is not in the main connected component but reference element is.
69-
// Therefore, the sensitivity is known to value 0 and the reference value can be computed.
70-
lfFactors.stream().filter(factor -> factor.getStatus() == LfSensitivityFactor.Status.VALID_ONLY_FOR_FUNCTION)
71-
.forEach(factor -> {
72-
if (!filterSensitivityValue(0, factor.getVariableType(), factor.getFunctionType(), parameters)) {
73-
resultWriter.writeSensitivityValue(factor.getIndex(), contingencyIndex, operatorStrategyIndex, 0, unscaleFunction(factor, factor.getFunctionReference()));
74-
}
75-
});
76-
7768
for (SensitivityFactorGroup<AcVariableType, AcEquationType> factorGroup : factorGroups.getList()) {
7869
for (LfSensitivityFactor<AcVariableType, AcEquationType> factor : factorGroup.getFactors()) {
7970
if (!lfFactorsSet.contains(factor)) {
@@ -87,16 +78,15 @@ private void calculateSensitivityValues(List<LfSensitivityFactor<AcVariableType,
8778
if (!factor.getFunctionEquationTerm().isActive()) {
8879
throw new PowsyblException("Found an inactive equation for a factor that has no predefined result");
8980
}
90-
sensi = factor.getFunctionEquationTerm().calculateSensi(factorsState, factorGroup.getIndex());
81+
sensi = unscaleSensitivity(factor, factor.getFunctionEquationTerm().calculateSensi(factorsState, factorGroup.getIndex()));
9182
}
9283
if (factor.getFunctionPredefinedResult() != null) {
9384
ref = factor.getFunctionPredefinedResult();
9485
} else {
95-
ref = factor.getFunctionReference();
86+
ref = unscaleFunction(factor, factor.getFunctionReference());
9687
}
97-
double unscaledSensi = unscaleSensitivity(factor, sensi);
98-
if (!filterSensitivityValue(unscaledSensi, factor.getVariableType(), factor.getFunctionType(), parameters)) {
99-
resultWriter.writeSensitivityValue(factor.getIndex(), contingencyIndex, operatorStrategyIndex, unscaledSensi, unscaleFunction(factor, ref));
88+
if (!filterSensitivityValue(sensi, factor.getVariableType(), factor.getFunctionType(), parameters)) {
89+
resultWriter.writeSensitivityValue(factor.getIndex(), contingencyIndex, operatorStrategyIndex, sensi, ref);
10090
}
10191
}
10292
}
@@ -344,19 +334,14 @@ private void analyzeContingencySet(Network network, LfNetworkList lfNetworks, Li
344334
LOGGER.info("Running AC sensitivity analysis with {} factors, {} contingencies and {} operator strategies",
345335
allLfFactors.size(), propagatedContingencies.size(), operatorStrategies.size());
346336

347-
// next we only work with valid and valid only for function factors
348-
var validFactorHolder = writeInvalidFactors(allFactorHolder, resultWriter, propagatedContingencies, new HashMap<>(), parameters);
349-
var validLfFactors = validFactorHolder.getAllFactors();
350-
351337
try (AcLoadFlowContext context = new AcLoadFlowContext(lfNetwork, acParameters)) {
352338

353339
runLoadFlow(context, true);
354340

355341
acParameters.setVoltageInitReport(false);
356342

357343
// index factors by variable group to compute a minimal number of states
358-
SensitivityFactorGroupList<AcVariableType, AcEquationType> factorGroups = createFactorGroups(validLfFactors.stream()
359-
.filter(factor -> factor.getStatus() == LfSensitivityFactor.Status.VALID).collect(Collectors.toList()));
344+
SensitivityFactorGroupList<AcVariableType, AcEquationType> factorGroups = createFactorGroups(allLfFactors);
360345

361346
// compute the participation for each injection factor (+1 on the injection and then -participation factor on all
362347
// buses that contain elements participating to slack distribution
@@ -395,10 +380,12 @@ private void analyzeContingencySet(Network network, LfNetworkList lfNetworks, Li
395380
OpenLoadFlowParameters contingencylfParametersExt = applyGenericContingencyParameters(context, lfParameters, lfParametersExt,
396381
sensitivityAnalysisParametersExt.isStartWithFrozenACEmulation());
397382

383+
setPredefinedResults(allLfFactors, new DisabledNetwork(), null);
384+
398385
// calculate sensitivity values
399-
setFunctionReferences(validLfFactors);
386+
setFunctionReferences(allLfFactors);
400387
if (parameters.getOperatorStrategiesCalculationMode() != SensitivityOperatorStrategiesCalculationMode.ONLY_OPERATOR_STRATEGIES) {
401-
calculateSensitivityValues(validFactorHolder.getFactorsForBaseNetwork(), factorGroups, factorsStates, -1, -1, resultWriter);
388+
calculateSensitivityValues(allFactorHolder.getFactorsForBaseNetwork(), factorGroups, factorsStates, -1, -1, resultWriter);
402389
}
403390

404391
NetworkState networkState = NetworkState.save(lfNetwork);
@@ -411,7 +398,7 @@ private void analyzeContingencySet(Network network, LfNetworkList lfNetworks, Li
411398
LfOperatorStrategy lfOperatorStrategy = LfOperatorStrategy.create(operatorStrategy, lfActionById);
412399
LfNetworkChange lfNetworkChange = new LfNetworkChange(lfNetwork, null, null, lfOperatorStrategy);
413400
processNetworkChange(lfParameters, resultWriter, variablesTargetVoltageInfo, null, lfNetworkChange, networkReportNode,
414-
lfNetwork, validFactorHolder, factorGroups, contingencylfParametersExt, context, networkState, factorsStates);
401+
lfNetwork, allFactorHolder, factorGroups, contingencylfParametersExt, context, networkState, factorsStates);
415402
}
416403
}
417404
}
@@ -428,7 +415,7 @@ private void analyzeContingencySet(Network network, LfNetworkList lfNetworks, Li
428415
LOGGER.info("Simulate contingency '{}'", propagatedContingency.getContingency().getId());
429416
LfNetworkChange lfNetworkChange = new LfNetworkChange(lfNetwork, propagatedContingency, lfContingency, null);
430417
processNetworkChange(lfParameters, resultWriter, variablesTargetVoltageInfo, propagatedContingency, lfNetworkChange, networkReportNode,
431-
lfNetwork, validFactorHolder, factorGroups, contingencylfParametersExt, context, networkState, factorsStates);
418+
lfNetwork, allFactorHolder, factorGroups, contingencylfParametersExt, context, networkState, factorsStates);
432419
}
433420

434421
if (parameters.getOperatorStrategiesCalculationMode() != SensitivityOperatorStrategiesCalculationMode.NONE) {
@@ -440,7 +427,7 @@ private void analyzeContingencySet(Network network, LfNetworkList lfNetworks, Li
440427
LfOperatorStrategy lfOperatorStrategy = LfOperatorStrategy.create(operatorStrategy, lfActionById);
441428
LfNetworkChange lfNetworkChange = new LfNetworkChange(lfNetwork, propagatedContingency, lfContingency, lfOperatorStrategy);
442429
processNetworkChange(lfParameters, resultWriter, variablesTargetVoltageInfo, propagatedContingency, lfNetworkChange, networkReportNode,
443-
lfNetwork, validFactorHolder, factorGroups, contingencylfParametersExt, context, networkState, factorsStates);
430+
lfNetwork, allFactorHolder, factorGroups, contingencylfParametersExt, context, networkState, factorsStates);
444431
}
445432
}
446433
});
@@ -455,14 +442,15 @@ private void processNetworkChange(LoadFlowParameters lfParameters, SensitivityRe
455442
ReportNode postContSimReportNode = Reports.createPostContingencySimulation(networkReportNode, lfNetworkChange.getContingencyId());
456443
lfNetwork.setReportNode(postContSimReportNode);
457444

445+
lfNetworkChange.apply(lfParameters.getBalanceType());
446+
458447
List<LfSensitivityFactor<AcVariableType, AcEquationType>> contingencyFactors = validFactorHolder.getFactorsForContingency(lfNetworkChange.getContingencyId());
459448
contingencyFactors.forEach(lfFactor -> {
460449
lfFactor.setSensitivityValuePredefinedResult(null);
461450
lfFactor.setFunctionPredefinedResult(null);
451+
lfFactor.updateStatus();
462452
});
463453

464-
lfNetworkChange.apply(lfParameters.getBalanceType());
465-
466454
setPredefinedResults(contingencyFactors, lfNetworkChange.getDisabledNetwork(), propagatedContingency);
467455

468456
Map<LfBus, Double> postContingencySlackParticipationByBus;

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

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public class LfNetworkChange {
2828
private final LfContingency lfContingency;
2929
private final LfOperatorStrategy lfOperatorStrategy;
3030
private final DisabledNetwork disabledNetwork;
31+
private final EnabledNetwork enabledNetwork;
3132

3233
public LfNetworkChange(LfNetwork lfNetwork, PropagatedContingency propagatedContingency, LfContingency lfContingency, LfOperatorStrategy lfOperatorStrategy) {
3334
Objects.requireNonNull(lfNetwork);
@@ -37,6 +38,8 @@ public LfNetworkChange(LfNetwork lfNetwork, PropagatedContingency propagatedCont
3738
Set<LfBus> disabledBuses = new HashSet<>();
3839
Map<LfBranch, DisabledBranchStatus> branchesStatus = new HashMap<>();
3940
Set<LfHvdc> disabledHvdcs = new HashSet<>();
41+
Set<LfBus> enabledBuses = new HashSet<>();
42+
Set<LfBranch> enabledBranches = new HashSet<>();
4043
if (lfContingency != null) {
4144
disabledBuses.addAll(lfContingency.getDisabledNetwork().getBuses());
4245
branchesStatus.putAll(lfContingency.getDisabledNetwork().getBranchesStatus());
@@ -49,11 +52,23 @@ public LfNetworkChange(LfNetwork lfNetwork, PropagatedContingency propagatedCont
4952
NetworkActivations networkActivations = AbstractLfBranchAction.getNetworkActivations(lfNetwork, lfContingency, branchActions);
5053
disabledBuses.addAll(networkActivations.getDisabledNetwork().getBuses());
5154
branchesStatus.putAll(networkActivations.getDisabledNetwork().getBranchesStatus());
52-
if (!networkActivations.getEnabledNetwork().getBuses().isEmpty()) {
53-
throw new PowsyblException("Network change should not add new buses");
55+
// check we don't re-enable a bus or a branch disabled by the contingency
56+
// TODO to support later
57+
for (LfBus bus : networkActivations.getEnabledNetwork().getBuses()) {
58+
if (disabledBuses.contains(bus)) {
59+
throw new PowsyblException("Network change should not enable a bus already disabled by the contingency");
60+
}
5461
}
62+
for (LfBranch branch : networkActivations.getEnabledNetwork().getBranches()) {
63+
if (branchesStatus.containsKey(branch)) {
64+
throw new PowsyblException("Network change should not enable a branch already disabled by the contingency");
65+
}
66+
}
67+
enabledBuses.addAll(networkActivations.getEnabledNetwork().getBuses());
68+
enabledBranches.addAll(networkActivations.getEnabledNetwork().getBranches());
5569
}
5670
disabledNetwork = new DisabledNetwork(disabledBuses, branchesStatus, disabledHvdcs);
71+
enabledNetwork = new EnabledNetwork(enabledBuses, enabledBranches);
5772
}
5873

5974
public String getContingencyId() {
@@ -72,8 +87,13 @@ public DisabledNetwork getDisabledNetwork() {
7287
return disabledNetwork;
7388
}
7489

90+
public EnabledNetwork getEnabledNetwork() {
91+
return enabledNetwork;
92+
}
93+
7594
public void apply(LoadFlowParameters.BalanceType balanceType) {
7695
disabledNetwork.apply();
96+
enabledNetwork.apply();
7797
if (lfContingency != null) {
7898
lfContingency.processLostPowerChanges(balanceType, true);
7999
}

0 commit comments

Comments
 (0)