Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check target voltage plausibility on Transformers and Shunt Compensators #1030

Merged
merged 13 commits into from
May 17, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ private Optional<List<String>> processSecondaryVoltageControl(List<LfSecondaryVo
.stream()
.filter(e -> {
double newTargetV = e.getValue();
return LfGenerator.isTargetVoltageNotPlausible(newTargetV, minPlausibleTargetVoltage, maxPlausibleTargetVoltage);
return !VoltageControl.isTargetVoltagePlausible(newTargetV, minPlausibleTargetVoltage, maxPlausibleTargetVoltage);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@annetill just a note, no check on minNominalVoltageTargetVoltageCheck here, I have no idea if this is deliberate (I lack knowledge about this outerloop).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we are going to wait for the issue @geofjamg . At RTE, we are using this outer loop on network without any generator connected to low nominal voltages, but it could arrived soon.

})
.map(e -> {
// convert target to Kv for better display
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,6 @@ static double qToK(LfGenerator generator, double q) {
return (2 * q - maxQ - minQ) / (maxQ - minQ);
}

static boolean isTargetVoltageNotPlausible(double targetV, double minPlausibleTargetVoltage, double maxPlausibleTargetVoltage) {
return targetV < minPlausibleTargetVoltage || targetV > maxPlausibleTargetVoltage;
}

String getId();

String getOriginalId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,14 @@ public Optional<LfBus> findMainVisibleControlledBus() {
}
}

public static boolean checkTargetV(double targetV, double nominalV, LfNetworkParameters parameters) {
return nominalV <= parameters.getMinNominalVoltageTargetVoltageCheck() || isTargetVoltagePlausible(targetV, parameters.getMinPlausibleTargetVoltage(), parameters.getMaxPlausibleTargetVoltage());
}

public static boolean isTargetVoltagePlausible(double targetV, double minPlausibleTargetVoltage, double maxPlausibleTargetVoltage) {
return targetV >= minPlausibleTargetVoltage && targetV <= maxPlausibleTargetVoltage;
}

@Override
public String toString() {
return "VoltageControl(type=" + type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -327,25 +327,45 @@ void addBattery(Battery generator, LfNetworkParameters parameters, LfNetworkLoad
add(LfBatteryImpl.create(generator, network, parameters, report));
}

void setShuntCompensators(List<ShuntCompensator> shuntCompensators, LfNetworkParameters parameters, LfTopoConfig topoConfig) {
void setShuntCompensators(List<ShuntCompensator> shuntCompensators, LfNetworkParameters parameters, LfTopoConfig topoConfig, LfNetworkLoadingReport report) {
if (!parameters.isShuntVoltageControl() && !shuntCompensators.isEmpty()) {
shunt = new LfShuntImpl(shuntCompensators, network, this, false, parameters, topoConfig);
} else {
List<ShuntCompensator> controllerShuntCompensators = shuntCompensators.stream()
.filter(ShuntCompensator::isVoltageRegulatorOn)
.toList();
List<ShuntCompensator> controllerShuntCompensators = new ArrayList<>();
List<ShuntCompensator> fixedShuntCompensators = new ArrayList<>();
shuntCompensators.forEach(sc -> {
if (checkVoltageControl(sc, parameters, report)) {
controllerShuntCompensators.add(sc);
} else {
fixedShuntCompensators.add(sc);
}
});

if (!controllerShuntCompensators.isEmpty()) {
controllerShunt = new LfShuntImpl(controllerShuntCompensators, network, this, true, parameters, topoConfig);
}
List<ShuntCompensator> fixedShuntCompensators = shuntCompensators.stream()
.filter(sc -> !sc.isVoltageRegulatorOn())
.toList();
if (!fixedShuntCompensators.isEmpty()) {
shunt = new LfShuntImpl(fixedShuntCompensators, network, this, false, parameters, topoConfig);
}
}
}

static boolean checkVoltageControl(ShuntCompensator shuntCompensator, LfNetworkParameters parameters, LfNetworkLoadingReport report) {
double nominalV = shuntCompensator.getRegulatingTerminal().getVoltageLevel().getNominalV();
double targetV = shuntCompensator.getTargetV();
if (!shuntCompensator.isVoltageRegulatorOn()) {
return false;
}
if (!VoltageControl.checkTargetV(targetV / nominalV, nominalV, parameters)) {
LOGGER.trace("Shunt compensator '{}' has an inconsistent target voltage: {} pu: Shunt voltage control discarded", shuntCompensator.getId(), targetV);
if (report != null) {
report.shuntsWithInconsistentTargetVoltage++;
}
return false;
}
return true;
}

@Override
public void invalidateGenerationTargetP() {
generationTargetP = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,7 @@ protected boolean checkIfGeneratorIsInsideActivePowerLimitsForVoltageControl(LfN

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() &&
LfGenerator.isTargetVoltageNotPlausible(targetV, parameters.getMinPlausibleTargetVoltage(), parameters.getMaxPlausibleTargetVoltage())) {
if (!VoltageControl.checkTargetV(targetV, nominalV, parameters)) {
LOGGER.trace("Generator '{}' has an inconsistent target voltage: {} pu: generator voltage control discarded",
generatorId, targetV);
if (report != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ public void visitHvdcConverterStation(HvdcConverterStation<?> converterStation)
});

if (!shuntCompensators.isEmpty()) {
lfBus.setShuntCompensators(shuntCompensators, parameters, topoConfig);
lfBus.setShuntCompensators(shuntCompensators, parameters, topoConfig, report);
}

return lfBus;
Expand Down Expand Up @@ -627,6 +627,14 @@ private static void createTransformerVoltageControl(LfNetwork lfNetwork, RatioTa
double targetValue = rtc.getTargetV() / regulatingTerminalNominalV;
Double targetDeadband = rtc.getTargetDeadband() > 0 ? rtc.getTargetDeadband() / regulatingTerminalNominalV : null;

if (!VoltageControl.checkTargetV(targetValue, controlledBus.getNominalV(), parameters)) {
LOGGER.trace("RatioTapChanger on transformer '{}' has an inconsistent target voltage: {} pu: Rtc voltage control discarded", controllerBranchId, targetValue);
if (report != null) {
report.ratioTapChangersWithInconsistentTargetVoltage++;
}
return;
}

controlledBus.getTransformerVoltageControl().ifPresentOrElse(vc -> {
LOGGER.trace("Controlled bus '{}' already has a transformer voltage control: a shared control is created", controlledBus.getId());
if (FastMath.abs(vc.getTargetValue() - targetValue) > TARGET_V_EPSILON) {
Expand Down Expand Up @@ -705,7 +713,12 @@ private static void createShuntVoltageControl(LfNetwork lfNetwork, ShuntCompensa
LOGGER.warn("Voltage controller shunt {} is out of voltage: no voltage control created", shuntCompensator.getId());
return;
}
LfShunt controllerShunt = controllerBus.getControllerShunt().orElseThrow();
Optional<LfShunt> controllerShuntOpt = controllerBus.getControllerShunt();
if (controllerShuntOpt.isEmpty()) {
// The shunt voltage control has been discarded
return;
}
LfShunt controllerShunt = controllerShuntOpt.get();
LfBus controlledBus = getLfBus(shuntCompensator.getRegulatingTerminal(), lfNetwork, parameters.isBreakers());
if (controlledBus == null) {
LOGGER.warn("Regulating terminal of voltage controller shunt {} is out of voltage: no voltage control created", shuntCompensator.getId());
Expand Down Expand Up @@ -843,15 +856,12 @@ private LfNetwork create(int numCC, int numSC, Network network, List<Bus> buses,
LOGGER.warn("Network {}: {} branches have been discarded because connected to same bus at both ends",
lfNetwork, report.branchesDiscardedBecauseConnectedToSameBusAtBothEnds);
}
if (report.linesWithDifferentNominalVoltageAtBothEnds > 0) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why it is removed?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is dead code ... See #1030 (comment)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is a mistake @geofjamg what's happen here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LOGGER.warn("Network {}: {} lines have a different nominal voltage at both ends: a ratio has been added",
lfNetwork, report.linesWithDifferentNominalVoltageAtBothEnds);
}
if (report.nonImpedantBranches > 0) {
LOGGER.warn("Network {}: {} branches are non impedant", lfNetwork, report.nonImpedantBranches);
}

if (report.generatorsWithInconsistentTargetVoltage > 0) {
Reports.reportGeneratorsDiscardedFromVoltageControlBecauseTargetVIsInconsistent(reportNode, report.generatorsWithInconsistentTargetVoltage);
LOGGER.warn("Network {}: {} generators have an inconsistent target voltage and have been discarded from voltage control",
lfNetwork, report.generatorsWithInconsistentTargetVoltage);
}
Expand All @@ -871,6 +881,18 @@ private LfNetwork create(int numCC, int numSC, Network network, List<Bus> buses,
lfNetwork, report.transformerReactivePowerControlDiscardedBecauseControllerBranchIsOpen);
}

if (report.ratioTapChangersWithInconsistentTargetVoltage > 0) {
Reports.reportRatioTapChangersDiscardedFromVoltageControlBecauseTargetVIsInconsistent(reportNode, report.ratioTapChangersWithInconsistentTargetVoltage);
LOGGER.warn("Network {}: {} ratio tap changers have an inconsistent target voltage and have been discarded from voltage control",
lfNetwork, report.ratioTapChangersWithInconsistentTargetVoltage);
}

if (report.shuntsWithInconsistentTargetVoltage > 0) {
Reports.reportShuntsDiscardedFromVoltageControlBecauseTargetVIsInconsistent(reportNode, report.shuntsWithInconsistentTargetVoltage);
LOGGER.warn("Network {}: {} shunts have an inconsistent target voltage and have been discarded from voltage control",
lfNetwork, report.shuntsWithInconsistentTargetVoltage);
}

if (parameters.getDebugDir() != null) {
Path debugDir = DebugUtil.getDebugDir(parameters.getDebugDir());
String dateStr = ZonedDateTime.now().format(DATE_TIME_FORMAT);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ public class LfNetworkLoadingReport {

int branchesDiscardedBecauseConnectedToSameBusAtBothEnds = 0;

int linesWithDifferentNominalVoltageAtBothEnds = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question.


int nonImpedantBranches = 0;

int generatorsWithInconsistentTargetVoltage = 0;
Expand All @@ -41,4 +39,8 @@ public class LfNetworkLoadingReport {
int transformerVoltageControlDiscardedBecauseControllerBranchIsOpen = 0;

int transformerReactivePowerControlDiscardedBecauseControllerBranchIsOpen = 0;

int ratioTapChangersWithInconsistentTargetVoltage = 0;

int shuntsWithInconsistentTargetVoltage = 0;
}
28 changes: 28 additions & 0 deletions src/main/java/com/powsybl/openloadflow/util/Reports.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ public final class Reports {
private static final String ITERATION = "iteration";
private static final String NETWORK_ID = "networkId";
private static final String IMPACTED_GENERATOR_COUNT = "impactedGeneratorCount";

private static final String IMPACTED_RTC_COUNT = "impactedRatioTapChangerCount";

private static final String IMPACTED_SHUNT_COUNT = "impactedShuntCount";
private static final String BUS_ID = "busId";
private static final String CONTROLLER_BUS_ID = "controllerBusId";
private static final String CONTROLLED_BUS_ID = "controlledBusId";
Expand Down Expand Up @@ -294,6 +298,30 @@ public static void reportGeneratorsDiscardedFromVoltageControlBecauseTargetPIsOu
.add();
}

public static void reportGeneratorsDiscardedFromVoltageControlBecauseTargetVIsInconsistent(ReportNode reportNode, int impactedGeneratorCount) {
reportNode.newReportNode()
.withMessageTemplate("generatorsDiscardedFromVoltageControlBecauseTargetVIsInconsistent", "${impactedGeneratorCount} generators have been discarded from voltage control because targetV is inconsistent")
.withUntypedValue(IMPACTED_GENERATOR_COUNT, impactedGeneratorCount)
.withSeverity(TypedValue.WARN_SEVERITY)
.add();
}

public static void reportRatioTapChangersDiscardedFromVoltageControlBecauseTargetVIsInconsistent(ReportNode reportNode, int impactedRatioTapChangerCount) {
reportNode.newReportNode()
.withMessageTemplate("ratioTapChangersDiscardedFromVoltageControlBecauseTargetVIsInconsistent", "${impactedRatioTapChangerCount} ratio tap changers have been discarded from voltage control because targetV is inconsistent")
.withUntypedValue(IMPACTED_RTC_COUNT, impactedRatioTapChangerCount)
.withSeverity(TypedValue.WARN_SEVERITY)
.add();
}

public static void reportShuntsDiscardedFromVoltageControlBecauseTargetVIsInconsistent(ReportNode reportNode, int impactedShuntCount) {
reportNode.newReportNode()
.withMessageTemplate("shuntsDiscardedFromVoltageControlBecauseTargetVIsInconsistent", "${impactedShuntCount} shunts have been discarded from voltage control because targetV is inconsistent")
.withUntypedValue(IMPACTED_SHUNT_COUNT, impactedShuntCount)
.withSeverity(TypedValue.WARN_SEVERITY)
.add();
}

public static void reportAcLfComplete(ReportNode reportNode, boolean success, String solverStatus, String outerloopStatus) {
TypedValue severity = success ? TypedValue.INFO_SEVERITY : TypedValue.ERROR_SEVERITY;
String successText = success ? "successfully" : "with error";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ void testEsgTutoDetailedNrLogsLf() throws IOException {
@Test
void testShuntVoltageControlOuterLoopReport() throws IOException {
Network network = ShuntNetworkFactory.createWithTwoShuntCompensators();
network.getShuntCompensator("SHUNT2").setVoltageRegulatorOn(true).setTargetV(600); // not plausible targetV, will be discarded and reported
ReportNode reportNode = ReportNode.newRootReportNode()
.withMessageTemplate("testReport", "Test Report")
.build();
Expand Down Expand Up @@ -110,7 +111,7 @@ void testTransformerReactivePowerControlOuterLoopReport() throws IOException {

@Test
void testMultipleComponents() throws IOException {
Network network = ConnectedComponentNetworkFactory.createThreeCcLinkedByASingleBus();
Network network = ConnectedComponentNetworkFactory.createThreeCcLinkedByASingleBusWithInconsistentVoltages();
// open everything at bus b4 to create 3 components
network.getBusBreakerView().getBus("b4").getConnectedTerminalStream().forEach(Terminal::disconnect);

Expand All @@ -119,7 +120,9 @@ void testMultipleComponents() throws IOException {
// CC2 SC2 has no generator connected. Ignored in for DC and AC.
network.getGenerator("g10").disconnect();

var lfParameters = new LoadFlowParameters().setConnectedComponentMode(LoadFlowParameters.ConnectedComponentMode.ALL);
var lfParameters = new LoadFlowParameters().setConnectedComponentMode(LoadFlowParameters.ConnectedComponentMode.ALL)
.setTransformerVoltageControlOn(true);
OpenLoadFlowParameters.create(lfParameters).setMinNominalVoltageTargetVoltageCheck(0.5);

LoadFlowProvider provider = new OpenLoadFlowProvider(new DenseMatrixFactory(), new NaiveGraphConnectivityFactory<>(LfBus::getNum));
LoadFlow.Runner runner = new LoadFlow.Runner(provider);
Expand Down
12 changes: 12 additions & 0 deletions src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowShuntTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,18 @@ void testIncrementalVoltageControl() {
assertEquals(0, shunt.getSectionCount());
}

@Test
void testNotPlausibleTargetV() {
parameters.setShuntCompensatorVoltageControlOn(true);
shunt.setSectionCount(0);
shunt.setVoltageRegulatorOn(true);
shunt.setTargetV(600);
LoadFlowResult result2 = loadFlowRunner.run(network, parameters);
assertTrue(result2.isFullyConverged());
assertVoltageEquals(388.581, bus3);
assertEquals(0, shunt.getSectionCount());
}

@Test
void testIncrementalVoltageRemote() {
Network network = VoltageControlNetworkFactory.createWithShuntSharedRemoteControl();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,38 @@ void voltageControlT2wtTest8() {
assertEquals(4, t2wt.getRatioTapChanger().getTapPosition());
}

@Test
void voltageControlT2wtNonPlausibleTargetV() {
selectNetwork(VoltageControlNetworkFactory.createNetworkWithT2wt2());
parameters.setTransformerVoltageControlOn(true);
parametersExt.setTransformerVoltageControlMode(OpenLoadFlowParameters.TransformerVoltageControlMode.INCREMENTAL_VOLTAGE_CONTROL);

t2wt.getRatioTapChanger()
.setTargetDeadband(0)
.setRegulating(false)
.setTapPosition(7)
.setRegulationTerminal(t2wt.getTerminal2())
.setTargetV(34.0);
LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
assertFalse(t2wt.getRatioTapChanger().isRegulating());
assertVoltageEquals(134.281, bus2);
assertVoltageEquals(27.0, t2wt.getTerminal2().getBusView().getBus());
assertEquals(7, t2wt.getRatioTapChanger().getTapPosition());

t2wt.getRatioTapChanger()
.setTargetDeadband(0)
.setRegulating(true)
.setTapPosition(7)
.setRegulationTerminal(t2wt.getTerminal2())
.setTargetV(60);
result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
assertVoltageEquals(134.281, bus2);
assertVoltageEquals(27.0, t2wt.getTerminal2().getBusView().getBus());
assertEquals(7, t2wt.getRatioTapChanger().getTapPosition());
}

@Test
void remoteVoltageControlT2wtTest() {
selectNetwork(VoltageControlNetworkFactory.createNetworkWithT2wt());
Expand Down Expand Up @@ -675,6 +707,25 @@ void voltageControlT3wtTest() {
assertEquals(2, t3wt.getLeg2().getRatioTapChanger().getTapPosition());
}

@Test
void voltageControlT3wtNonPlausibleTargetV() {
selectNetwork(VoltageControlNetworkFactory.createNetworkWithT3wt());

t3wt.getLeg2().getRatioTapChanger()
.setTargetDeadband(0)
.setRegulating(true)
.setTapPosition(2)
.setRegulationTerminal(t3wt.getLeg2().getTerminal())
.setTargetV(60);

parameters.setTransformerVoltageControlOn(true);

LoadFlowResult result = loadFlowRunner.run(network, parameters);
assertTrue(result.isFullyConverged());
assertVoltageEquals(28.147, bus3);
assertEquals(2, t3wt.getLeg2().getRatioTapChanger().getTapPosition());
}

@Test
void remoteVoltageControlT3wtTest() {
selectNetwork(VoltageControlNetworkFactory.createNetworkWithT3wt());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,28 @@ public static Network createThreeCcLinkedByASingleBus() {
return network;
}

public static Network createThreeCcLinkedByASingleBusWithInconsistentVoltages() {
Network network = createThreeCcLinkedByASingleBus();
Bus b2 = network.getBusBreakerView().getBus("b2");
createGenerator(b2, "g2_bis", 0, 2);
Bus b3 = network.getBusBreakerView().getBus("b3");
Bus b3Bis = createBus(network, "b3_s", "b3_bis", 1);

var t2wt = createTransformer(network, "b3_s", b3, b3Bis, "l35", 0.1f, 1d);
t2wt.newRatioTapChanger()
.beginStep()
.setRho(1)
.endStep()
.setTapPosition(0)
.setLoadTapChangingCapabilities(true)
.setRegulating(true)
.setTargetV(2)
.setTargetDeadband(0)
.setRegulationTerminal(t2wt.getTerminal1())
.add();
return network;
}

/**
* <pre>
* b1 (d1) ----------+ b6 (g6) ---PTC----+
Expand Down
Loading