Skip to content

Commit

Permalink
Fix already converged case in fast restart mode (#802)
Browse files Browse the repository at this point in the history
Signed-off-by: Geoffroy Jamgotchian <geoffroy.jamgotchian@rte-france.com>
(cherry picked from commit fbc684f)
  • Loading branch information
geofjamg authored and jeandemanged committed Jul 18, 2023
1 parent 22da556 commit ec5111e
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import com.powsybl.openloadflow.ac.AcLoadFlowParameters;
import com.powsybl.openloadflow.ac.AcLoadFlowResult;
import com.powsybl.openloadflow.ac.AcloadFlowEngine;
import com.powsybl.openloadflow.ac.nr.NewtonRaphsonStatus;
import com.powsybl.openloadflow.lf.outerloop.OuterLoopStatus;
import com.powsybl.openloadflow.network.impl.LfNetworkList;
import com.powsybl.openloadflow.network.impl.Networks;
import org.slf4j.Logger;
Expand Down Expand Up @@ -93,13 +95,16 @@ private List<AcLoadFlowContext> initContexts(NetworkCache.Entry entry) {
}

private static AcLoadFlowResult run(AcLoadFlowContext context) {
if (context.getNetwork().isValid() && context.isNetworkUpdated()) {
if (!context.getNetwork().isValid()) {
return AcLoadFlowResult.createNoCalculationResult(context.getNetwork());
}
if (context.isNetworkUpdated()) {
AcLoadFlowResult result = new AcloadFlowEngine(context)
.run();
context.setNetworkUpdated(false);
return result;
}
return AcLoadFlowResult.createNoCalculationResult(context.getNetwork());
return new AcLoadFlowResult(context.getNetwork(), 0, 0, NewtonRaphsonStatus.CONVERGED, OuterLoopStatus.STABLE, 0d, 0d);
}

public List<AcLoadFlowResult> run() {
Expand Down
15 changes: 13 additions & 2 deletions src/main/java/com/powsybl/openloadflow/NetworkCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import com.powsybl.openloadflow.network.LfShunt;
import com.powsybl.openloadflow.network.GeneratorVoltageControl;
import com.powsybl.openloadflow.network.*;
import com.powsybl.openloadflow.network.impl.AbstractLfGenerator;
import com.powsybl.openloadflow.network.util.PreviousValueVoltageInitializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -134,8 +135,18 @@ private boolean onGeneratorUpdate(Generator generator, String attribute, Object
if (attribute.equals("targetV")) {
double valueShift = (double) newValue - (double) oldValue;
GeneratorVoltageControl voltageControl = lfBus.getGeneratorVoltageControl().orElseThrow();
double newTargetV = voltageControl.getTargetValue() + valueShift / lfBus.getNominalV();
voltageControl.setTargetValue(newTargetV);
double nominalV = voltageControl.getControlledBus().getNominalV();
double newTargetV = voltageControl.getTargetValue() + valueShift / nominalV;
LfNetworkParameters networkParameters = context.getParameters().getNetworkParameters();
if (AbstractLfGenerator.checkTargetV(generator.getId(), newTargetV, nominalV, networkParameters, null)) {
voltageControl.setTargetValue(newTargetV);
} else {
context.getNetwork().getGeneratorById(generator.getId()).setGeneratorControlType(LfGenerator.GeneratorControlType.OFF);
if (lfBus.getGenerators().stream().noneMatch(gen -> gen.getGeneratorControlType() == LfGenerator.GeneratorControlType.VOLTAGE)) {
lfBus.setGeneratorVoltageControlEnabled(false);
}
}
context.getNetwork().validate(LoadFlowModel.AC, null);
return true;
}
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ private LoadFlowResult runAc(Network network, LoadFlowParameters parameters, Ope
List<LoadFlowResult.ComponentResult> componentResults = new ArrayList<>(results.size());
for (AcLoadFlowResult result : results) {
// update network state
if (result.getNewtonRaphsonStatus() == NewtonRaphsonStatus.CONVERGED || parametersExt.isAlwaysUpdateNetwork()) {
if ((result.getNewtonRaphsonStatus() == NewtonRaphsonStatus.CONVERGED && result.getNewtonRaphsonIterations() > 0) || parametersExt.isAlwaysUpdateNetwork()) {
var updateParameters = new LfNetworkStateUpdateParameters(parameters.isUseReactiveLimits(),
parameters.isWriteSlackBus(),
parameters.isPhaseShifterRegulationOn(),
Expand Down
14 changes: 8 additions & 6 deletions src/main/java/com/powsybl/openloadflow/network/LfNetwork.java
Original file line number Diff line number Diff line change
Expand Up @@ -490,16 +490,18 @@ public void fix(boolean minImpedance, double lowImpedanceThreshold) {

private void validateBuses(LoadFlowModel loadFlowModel, Reporter reporter) {
if (loadFlowModel == LoadFlowModel.AC) {
boolean hasAtLeastOneBusVoltageControlled = false;
boolean hasAtLeastOneBusGeneratorVoltageControlEnabled = false;
for (LfBus bus : busesByIndex) {
if (bus.isGeneratorVoltageControlled()) {
hasAtLeastOneBusVoltageControlled = true;
if (bus.isGeneratorVoltageControlEnabled()) {
hasAtLeastOneBusGeneratorVoltageControlEnabled = true;
break;
}
}
if (!hasAtLeastOneBusVoltageControlled) {
LOGGER.error("Network {} must have at least one bus voltage controlled", this);
Reports.reportNetworkMustHaveAtLeastOneBusVoltageControlled(reporter);
if (!hasAtLeastOneBusGeneratorVoltageControlEnabled) {
LOGGER.error("Network {} must have at least one bus with generator voltage control enabled", this);
if (reporter != null) {
Reports.reportNetworkMustHaveAtLeastOneBusGeneratorVoltageControlEnabled(reporter);
}
valid = false;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ protected void setVoltageControl(double targetV, Terminal terminal, Terminal reg
LOGGER.warn("Regulating terminal of LfGenerator {} is not in the same synchronous component: voltage control discarded", getId());
return;
}
if (!checkTargetV(targetV / regulatingTerminal.getVoltageLevel().getNominalV(), regulatingTerminal.getVoltageLevel().getNominalV(), parameters, report)) {
if (!checkTargetV(getId(), targetV / regulatingTerminal.getVoltageLevel().getNominalV(), regulatingTerminal.getVoltageLevel().getNominalV(), parameters, report)) {
return;
}
this.controlledBusId = controlledBus.getId();
Expand Down Expand Up @@ -262,13 +262,15 @@ protected boolean checkVoltageControlConsistency(LfNetworkParameters parameters,
return consistency;
}

protected boolean checkTargetV(double targetV, double nominalV, LfNetworkParameters parameters, LfNetworkLoadingReport report) {
public static boolean checkTargetV(String generatorId, double targetV, double nominalV, LfNetworkParameters parameters, LfNetworkLoadingReport report) {
// check that targetV has a plausible value (wrong nominal voltage issue)
if (nominalV > parameters.getMinNominalVoltageTargetVoltageCheck() &&
(targetV < parameters.getMinPlausibleTargetVoltage() || targetV > parameters.getMaxPlausibleTargetVoltage())) {
LOGGER.trace("Generator '{}' has an inconsistent target voltage: {} pu: generator voltage control discarded",
getId(), targetV);
report.generatorsWithInconsistentTargetVoltage++;
generatorId, targetV);
if (report != null) {
report.generatorsWithInconsistentTargetVoltage++;
}
return false;
}
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ private LfDanglingLineGenerator(DanglingLine danglingLine, LfNetwork network, St
// local control only
if (danglingLine.getGeneration().isVoltageRegulationOn() && checkVoltageControlConsistency(parameters, report)) {
// The controlled bus cannot be reached from the DanglingLine parameters (there is no terminal in DanglingLine.Generation)
if (checkTargetV(danglingLine.getGeneration().getTargetV() / danglingLine.getTerminal().getVoltageLevel().getNominalV(),
if (checkTargetV(getId(), danglingLine.getGeneration().getTargetV() / danglingLine.getTerminal().getVoltageLevel().getNominalV(),
danglingLine.getTerminal().getVoltageLevel().getNominalV(), parameters, report)) {
this.controlledBusId = Objects.requireNonNull(controlledLfBusId);
this.targetV = danglingLine.getGeneration().getTargetV() / danglingLine.getTerminal().getVoltageLevel().getNominalV();
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/com/powsybl/openloadflow/util/Reports.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ public static void reportNetworkBalance(Reporter reporter, double activeGenerati
.build());
}

public static void reportNetworkMustHaveAtLeastOneBusVoltageControlled(Reporter reporter) {
public static void reportNetworkMustHaveAtLeastOneBusGeneratorVoltageControlEnabled(Reporter reporter) {
reporter.report(Report.builder()
.withKey("networkMustHaveAtLeastOneBusVoltageControlled")
.withDefaultMessage("Network must have at least one bus voltage controlled")
.withKey("networkMustHaveAtLeastOneBusGeneratorVoltageControlEnabled")
.withDefaultMessage("Network must have at least one bus with generator voltage control enabled")
.build());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ void noGeneratorTest() {
ReporterModel postLoadingReporter = createNetworkReporter.getSubReporters().get(0);
assertEquals("postLoadingProcessing", postLoadingReporter.getTaskKey());
assertEquals(1, postLoadingReporter.getReports().size());
assertEquals("Network must have at least one bus voltage controlled",
assertEquals("Network must have at least one bus with generator voltage control enabled",
postLoadingReporter.getReports().iterator().next().getDefaultMessage());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ void testTargetV() {

result = loadFlowRunner.run(network, parameters);
assertEquals(1, NetworkCache.INSTANCE.getEntryCount());
// FIXME NO_CALCULATION should be added to API
assertEquals(LoadFlowResult.ComponentResult.Status.FAILED, result.getComponentResults().get(0).getStatus());
assertEquals(LoadFlowResult.ComponentResult.Status.CONVERGED, result.getComponentResults().get(0).getStatus());
assertEquals(0, result.getComponentResults().get(0).getIterationCount());
}

Expand Down Expand Up @@ -333,4 +332,33 @@ void testSwitchClose() {
assertActivePowerEquals(301.884, l1.getTerminal1());
assertActivePowerEquals(301.884, l2.getTerminal1());
}

@Test
void testInvalidNetwork() {
var network = EurostagFactory.fix(EurostagTutorialExample1Factory.create());
var result = loadFlowRunner.run(network, parameters);

assertNotNull(NetworkCache.INSTANCE.findEntry(network).orElseThrow().getContexts());

var gen = network.getGenerator("GEN");
gen.setTargetV(1000);
result = loadFlowRunner.run(network, parameters);
assertEquals(LoadFlowResult.ComponentResult.Status.FAILED, result.getComponentResults().get(0).getStatus());
}

@Test
@Disabled("To support later")
void testInitiallyInvalidNetwork() {
var network = EurostagFactory.fix(EurostagTutorialExample1Factory.create());
var gen = network.getGenerator("GEN");
gen.setTargetV(1000);
var result = loadFlowRunner.run(network, parameters);
assertEquals(LoadFlowResult.ComponentResult.Status.FAILED, result.getComponentResults().get(0).getStatus());

assertNotNull(NetworkCache.INSTANCE.findEntry(network).orElseThrow().getContexts());

gen.setTargetV(24);
result = loadFlowRunner.run(network, parameters);
assertEquals(LoadFlowResult.ComponentResult.Status.CONVERGED, result.getComponentResults().get(0).getStatus());
}
}

0 comments on commit ec5111e

Please sign in to comment.