Skip to content

Commit 7abede4

Browse files
Save and restore only active power changes in Fast DC Security Analysis (#1205)
Signed-off-by: p-arvy <pierre.arvy@artelys.com> Co-authored-by: Hadrien <hadrien.godard@artelys.com>
1 parent 814ae31 commit 7abede4

2 files changed

Lines changed: 43 additions & 5 deletions

File tree

src/main/java/com/powsybl/openloadflow/network/LfContingency.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,23 +147,50 @@ public void apply(LoadFlowParameters.BalanceType balanceType) {
147147
shunt.setG(shunt.getG() - e.getValue().getG());
148148
shunt.setB(shunt.getB() - e.getValue().getB());
149149
}
150+
processLostPowerChanges(balanceType, true);
151+
}
152+
153+
/**
154+
* Process the power shifts due to the loss of loads, generators, and HVDCs.
155+
* @param balanceType the property defining how to manage active distribution.
156+
* @param updateAcQuantities a boolean to indicate if voltage/reactive dependent quantities should be updated or not.
157+
*/
158+
public void processLostPowerChanges(LoadFlowParameters.BalanceType balanceType, boolean updateAcQuantities) {
159+
processLostLoads(balanceType, updateAcQuantities);
160+
processLostGenerators(updateAcQuantities);
161+
processHvdcsWithoutPower();
162+
}
163+
164+
private void processLostLoads(LoadFlowParameters.BalanceType balanceType, boolean updateAcQuantities) {
150165
for (var e : lostLoads.entrySet()) {
151166
LfLoad load = e.getKey();
152167
LfLostLoad lostLoad = e.getValue();
153168
PowerShift shift = lostLoad.getPowerShift();
154169
load.setTargetP(load.getTargetP() - getUpdatedLoadP0(load, balanceType, shift.getActive(), shift.getVariableActive(), lostLoad.getNotParticipatingLoadP0()));
155-
load.setTargetQ(load.getTargetQ() - shift.getReactive());
170+
if (updateAcQuantities) {
171+
load.setTargetQ(load.getTargetQ() - shift.getReactive());
172+
}
156173
load.setAbsVariableTargetP(load.getAbsVariableTargetP() - Math.abs(shift.getVariableActive()));
157174
lostLoad.getOriginalIds().forEach(loadId -> load.setOriginalLoadDisabled(loadId, true));
158175
}
176+
}
177+
178+
private void processLostGenerators(boolean updateAcQuantities) {
159179
Set<LfBus> generatorBuses = new HashSet<>();
160180
for (LfGenerator generator : lostGenerators) {
181+
// DC and AC quantities
161182
generator.setTargetP(0);
162183
generator.setInitialTargetP(0);
163184
LfBus bus = generator.getBus();
164185
generatorBuses.add(bus);
165186
generator.setParticipating(false);
166187
generator.setDisabled(true);
188+
189+
if (!updateAcQuantities) {
190+
continue;
191+
}
192+
193+
// Only AC quantities
167194
if (generator.getGeneratorControlType() != LfGenerator.GeneratorControlType.OFF) {
168195
generator.setGeneratorControlType(LfGenerator.GeneratorControlType.OFF);
169196
bus.getGeneratorVoltageControl().ifPresent(GeneratorVoltageControl::updateReactiveKeys);
@@ -179,6 +206,12 @@ public void apply(LoadFlowParameters.BalanceType balanceType) {
179206
});
180207
}
181208
}
209+
210+
if (!updateAcQuantities) {
211+
return;
212+
}
213+
214+
// Only AC quantities
182215
for (LfBus bus : generatorBuses) {
183216
if (bus.getGenerators().stream().noneMatch(gen -> gen.getGeneratorControlType() == LfGenerator.GeneratorControlType.VOLTAGE)) {
184217
bus.setGeneratorVoltageControlEnabled(false);
@@ -187,6 +220,9 @@ public void apply(LoadFlowParameters.BalanceType balanceType) {
187220
bus.setGeneratorReactivePowerControlEnabled(false);
188221
}
189222
}
223+
}
224+
225+
private void processHvdcsWithoutPower() {
190226
for (LfHvdc hvdc : hvdcsWithoutPower) {
191227
hvdc.getConverterStation1().setTargetP(0.0);
192228
hvdc.getConverterStation2().setTargetP(0.0);

src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,14 +167,16 @@ private double[] calculatePostContingencyAndOperatorStrategyStates(DcLoadFlowCon
167167
engine.toPostContingencyAndOperatorStrategyStates(newFlowStates);
168168
} else {
169169
// if we have a contingency including the loss of a DC line or a generator or a load
170-
// save base state for later restoration after each contingency
170+
// save dc buses' base state for later restoration after processing lost power changes
171171
DcLoadFlowParameters lfParameters = loadFlowContext.getParameters();
172-
NetworkState networkState = NetworkState.save(lfNetwork);
172+
List<BusDcState> busStates = ElementState.save(lfNetwork.getBuses(), BusDcState::save);
173173
connectivityAnalysisResult.toLfContingency()
174-
.ifPresent(lfContingency -> lfContingency.apply(lfParameters.getBalanceType()));
174+
// only process the power shifts due to the loss of loads, generators, and HVDCs
175+
// the loss of buses and phase shifts are taken into account in the override of the flow states
176+
.ifPresent(lfContingency -> lfContingency.processLostPowerChanges(lfParameters.getBalanceType(), false));
175177
newFlowStates = WoodburyEngine.runDcLoadFlowWithModifiedTargetVector(loadFlowContext, disabledNetwork, reportNode, operatorStrategyLfActions);
176178
engine.toPostContingencyAndOperatorStrategyStates(newFlowStates);
177-
networkState.restore();
179+
ElementState.restore(busStates);
178180
}
179181

180182
return newFlowStates;

0 commit comments

Comments
 (0)