Skip to content

Commit

Permalink
Add concise and detailed logs for missing or inconsistent voltage lev…
Browse files Browse the repository at this point in the history
…els limits. (#68)

* Add synthetic and detailed logs for inconsistent voltage levels limits (limit < 0 and low limit > high limit)
* Modifications after code review.
* Fix Sonar issues

---------

Signed-off-by: Franck LECUYER <franck.lecuyer@rte-france.com>
  • Loading branch information
FranckLecuyer authored May 16, 2024
1 parent f42abda commit 0f4983e
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,6 @@ private static void checkParameters(Network network, String variantId, OpenReacP
Objects.requireNonNull(config);
Objects.requireNonNull(manager);
Objects.requireNonNull(reportNode);
parameters.checkIntegrity(network);
parameters.checkIntegrity(network, Reports.createParameterIntegrityReporter(reportNode, network.getId()));
}
}
8 changes: 8 additions & 0 deletions open-reac/src/main/java/com/powsybl/openreac/Reports.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,12 @@ public static void reportVariableShuntCompensatorsSize(ReportNode reportNode, in
.withUntypedValue("size", variableShuntCompensatorsSize)
.add();
}

public static ReportNode createParameterIntegrityReporter(ReportNode reportNode, String networkId) {
return reportNode.newReportNode()
.withMessageTemplate("openReacParameterIntegrity", "Open reac parameter integrity on network '${networkId}'")
.withUntypedValue("networkId", networkId)
.add();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@
*/
package com.powsybl.openreac.parameters.input;

import com.powsybl.commons.report.ReportNode;
import com.powsybl.commons.report.TypedValue;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.VoltageLevel;
import com.powsybl.openreac.exceptions.InvalidParametersException;
import com.powsybl.openreac.parameters.input.algo.*;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.stream.Collectors;

/**
* This class stores all inputs parameters specific to the OpenReac optimizer.
Expand Down Expand Up @@ -533,13 +535,69 @@ public List<OpenReacAlgoParam> getAllAlgorithmParams() {
return allAlgoParams;
}

private void checkLowAndHighVoltageLimitIntegrity(Network network, boolean integrityVoltageLimitOverrides,
Map<String, Pair<Double, Double>> voltageLevelsWithInconsistentLimits,
ReportNode reportNode) {
Map<String, Pair<Integer, Integer>> voltageLevelsWithMissingLimits = new TreeMap<>();

// Check integrity of low/high voltage limits, taking into account voltage limit overrides
boolean integrityVoltageLevelLimits = checkLowVoltageLevelLimits(network, voltageLevelsWithMissingLimits);
integrityVoltageLevelLimits &= checkHighVoltageLevelLimits(network, voltageLevelsWithMissingLimits);

if (!integrityVoltageLevelLimits || !integrityVoltageLimitOverrides) {
if (!voltageLevelsWithMissingLimits.isEmpty()) {
reportNode.newReportNode()
.withMessageTemplate("nbVoltageLevelsWithMissingLimits", "${size} voltage level(s) have undefined low and/or high voltage limits")
.withSeverity(TypedValue.INFO_SEVERITY)
.withUntypedValue("size", voltageLevelsWithMissingLimits.size())
.add();
voltageLevelsWithMissingLimits.forEach((key, value) -> {
String messageSuffix = "has undefined low and high voltage limits";
if (value.getLeft() == 0) {
messageSuffix = "has undefined high voltage limit";
} else if (value.getRight() == 0) {
messageSuffix = "has undefined low voltage limit";
}
reportNode.newReportNode()
.withMessageTemplate("voltageLevelWithMissingLimits", "${vlId} " + messageSuffix)
.withSeverity(TypedValue.TRACE_SEVERITY)
.withUntypedValue("vlId", key)
.add();
});
}
if (!voltageLevelsWithInconsistentLimits.isEmpty()) {
reportNode.newReportNode()
.withMessageTemplate("nbVoltageLevelsWithInconsistentLimits", "${size} voltage level(s) have inconsistent low and/or high voltage limits")
.withSeverity(TypedValue.INFO_SEVERITY)
.withUntypedValue("size", voltageLevelsWithInconsistentLimits.size())
.add();
voltageLevelsWithInconsistentLimits.forEach((key, value) -> reportNode.newReportNode()
.withMessageTemplate("voltageLevelWithInconsistentLimits", "${vlId} has one or two inconsistent voltage limits (low voltage limit = ${low}, high voltage limit = ${high})")
.withSeverity(TypedValue.TRACE_SEVERITY)
.withUntypedValue("vlId", key)
.withUntypedValue("low", value.getLeft())
.withUntypedValue("high", value.getRight())
.add());
}

if (!integrityVoltageLevelLimits) {
throw new InvalidParametersException("At least one voltage level has an undefined or incorrect voltage limit.");
} else {
throw new InvalidParametersException("At least one voltage limit override is inconsistent.");
}
}
}

/**
* Do some checks on the parameters given, such as provided IDs must correspond to the given network element
*
* @param network Network on which ID are going to be infered
* @param network Network on which ID are going to be infered
* @param reportNode aggregates functional logging
* @throws InvalidParametersException if the parameters contain some incoherences.
*/
public void checkIntegrity(Network network) throws InvalidParametersException {
public void checkIntegrity(Network network, ReportNode reportNode) throws InvalidParametersException {
Map<String, Pair<Double, Double>> voltageLevelsWithInconsistentLimits = new TreeMap<>();

for (String shuntId : getVariableShuntCompensators()) {
if (network.getShuntCompensator(shuntId) == null) {
throw new InvalidParametersException("Shunt " + shuntId + " not found in the network.");
Expand All @@ -562,24 +620,27 @@ public void checkIntegrity(Network network) throws InvalidParametersException {
}

// Check integrity of voltage overrides
boolean integrityVoltageLimitOverrides = checkVoltageLimitOverrides(network);
if (!integrityVoltageLimitOverrides) {
throw new InvalidParametersException("At least one voltage limit override is inconsistent.");
}
boolean integrityVoltageLimitOverrides = checkVoltageLimitOverrides(network, voltageLevelsWithInconsistentLimits);

// Check integrity of low/high voltage limits, taking into account voltage limit overrides
boolean integrityVoltageLevelLimits = checkLowVoltageLevelLimits(network);
integrityVoltageLevelLimits &= checkHighVoltageLevelLimits(network);
if (!integrityVoltageLevelLimits) {
throw new InvalidParametersException("At least one voltage level has an undefined or incorrect voltage limit.");
}
checkLowAndHighVoltageLimitIntegrity(network, integrityVoltageLimitOverrides, voltageLevelsWithInconsistentLimits, reportNode);

boolean integrityAlgorithmParameters = checkAlgorithmParametersIntegrity();
if (!integrityAlgorithmParameters) {
throw new InvalidParametersException("At least one algorithm parameter is inconsistent.");
}
}

/**
* Do some checks on the parameters given, such as provided IDs must correspond to the given network element
*
* @param network Network on which ID are going to be infered
* @throws InvalidParametersException if the parameters contain some incoherences.
*/
public void checkIntegrity(Network network) throws InvalidParametersException {
checkIntegrity(network, ReportNode.NO_OP);
}

/**
* @return true if the algorithm parameters are consistent, false otherwise.
*/
Expand Down Expand Up @@ -628,7 +689,7 @@ public boolean checkAlgorithmParametersIntegrity() {
* @return true if the low voltage level limits are correct taking into account low voltage limit overrides,
* false otherwise.
*/
boolean checkLowVoltageLevelLimits(Network network) {
boolean checkLowVoltageLevelLimits(Network network, Map<String, Pair<Integer, Integer>> voltageLevelsWithMissingLimits) {
boolean integrityVoltageLevelLimits = true;

for (VoltageLevel vl : network.getVoltageLevels()) {
Expand All @@ -637,9 +698,11 @@ boolean checkLowVoltageLevelLimits(Network network) {
if (Double.isNaN(lowLimit)) {
List<VoltageLimitOverride> overrides = getSpecificVoltageLimits(vl.getId(), VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT);
if (overrides.size() != 1) {
voltageLevelsWithMissingLimits.merge(vl.getId(), Pair.of(1, 0), (old, value) -> Pair.of(old.getLeft() + 1, old.getRight()));
LOGGER.warn("Voltage level {} has no low voltage limit defined. Please add one or use a voltage limit override.", vl.getId());
integrityVoltageLevelLimits = false;
} else if (overrides.get(0).isRelative()) { // we have one and just one
voltageLevelsWithMissingLimits.merge(vl.getId(), Pair.of(1, 0), (old, value) -> Pair.of(old.getLeft() + 1, old.getRight()));
LOGGER.warn("Relative voltage override impossible on undefined low voltage limit for voltage level {}.", vl.getId());
integrityVoltageLevelLimits = false;
}
Expand All @@ -655,7 +718,7 @@ boolean checkLowVoltageLevelLimits(Network network) {
* @return true if the high voltage level limits are correct taking into account high voltage limit overrides,
* false otherwise.
*/
boolean checkHighVoltageLevelLimits(Network network) {
boolean checkHighVoltageLevelLimits(Network network, Map<String, Pair<Integer, Integer>> voltageLevelsWithMissingLimits) {
boolean integrityVoltageLevelLimits = true;

for (VoltageLevel vl : network.getVoltageLevels()) {
Expand All @@ -664,9 +727,11 @@ boolean checkHighVoltageLevelLimits(Network network) {
if (Double.isNaN(highLimit)) {
List<VoltageLimitOverride> overrides = getSpecificVoltageLimits(vl.getId(), VoltageLimitOverride.VoltageLimitType.HIGH_VOLTAGE_LIMIT);
if (overrides.size() != 1) {
voltageLevelsWithMissingLimits.merge(vl.getId(), Pair.of(0, 1), (old, value) -> Pair.of(old.getLeft(), old.getRight() + 1));
LOGGER.warn("Voltage level {} has no high voltage limit defined. Please add one or use a voltage limit override.", vl.getId());
integrityVoltageLevelLimits = false;
} else if (overrides.get(0).isRelative()) {
voltageLevelsWithMissingLimits.merge(vl.getId(), Pair.of(0, 1), (old, value) -> Pair.of(old.getLeft(), old.getRight() + 1));
LOGGER.warn("Relative voltage override impossible on undefined high voltage limit for voltage level {}.", vl.getId());
integrityVoltageLevelLimits = false;
}
Expand All @@ -677,12 +742,57 @@ boolean checkHighVoltageLevelLimits(Network network) {
return integrityVoltageLevelLimits;
}

private boolean checkRelativeVoltageLimitOverrides(VoltageLimitOverride voltageLimitOverride, VoltageLevel voltageLevel,
Map<String, Pair<Double, Double>> voltageLevelsLimitsAfterOverride,
Map<String, Pair<Double, Double>> voltageLevelsWithInconsistentLimits) {
boolean integrityVoltageLimitOverrides = true;
double value = voltageLimitOverride.getVoltageLimitType() == VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT ?
voltageLevel.getLowVoltageLimit() : voltageLevel.getHighVoltageLimit();
if (Double.isNaN(value)) {
LOGGER.warn("Voltage level {} has undefined {}, relative voltage limit override is impossible.",
voltageLevel.getId(), voltageLimitOverride.getVoltageLimitType());
integrityVoltageLimitOverrides = false;
} else {
// verify voltage limit override does not lead to negative limit value
double valueAfter = value + voltageLimitOverride.getLimit();
if (voltageLimitOverride.getVoltageLimitType() == VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT) {
voltageLevelsLimitsAfterOverride.merge(voltageLevel.getId(), Pair.of(valueAfter, voltageLevel.getHighVoltageLimit()), (old, newValue) -> Pair.of(valueAfter, old.getRight()));
if (valueAfter < 0) {
voltageLevelsWithInconsistentLimits.merge(voltageLevel.getId(), Pair.of(valueAfter, voltageLevel.getHighVoltageLimit()), (old, newValue) -> Pair.of(valueAfter, old.getRight()));
}
} else {
voltageLevelsLimitsAfterOverride.merge(voltageLevel.getId(), Pair.of(voltageLevel.getLowVoltageLimit(), valueAfter), (old, newValue) -> Pair.of(old.getLeft(), valueAfter));
if (valueAfter < 0) {
voltageLevelsWithInconsistentLimits.merge(voltageLevel.getId(), Pair.of(voltageLevel.getLowVoltageLimit(), valueAfter), (old, newValue) -> Pair.of(old.getLeft(), valueAfter));
}
}
if (valueAfter < 0) {
LOGGER.warn("Voltage level {} relative override leads to a negative {}.",
voltageLevel.getId(), voltageLimitOverride.getVoltageLimitType());
integrityVoltageLimitOverrides = false;
}
}
return integrityVoltageLimitOverrides;
}

private void checkAbsoluteVoltageLimitOverrides(VoltageLimitOverride voltageLimitOverride, VoltageLevel voltageLevel,
Map<String, Pair<Double, Double>> voltageLevelsLimitsAfterOverride) {
if (voltageLimitOverride.getVoltageLimitType() == VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT) {
voltageLevelsLimitsAfterOverride.merge(voltageLevel.getId(), Pair.of(voltageLimitOverride.getLimit(), voltageLevel.getHighVoltageLimit()), (old, newValue) -> Pair.of(voltageLimitOverride.getLimit(), old.getRight()));
} else {
voltageLevelsLimitsAfterOverride.merge(voltageLevel.getId(), Pair.of(voltageLevel.getLowVoltageLimit(), voltageLimitOverride.getLimit()), (old, newValue) -> Pair.of(old.getLeft(), voltageLimitOverride.getLimit()));
}
}

/**
* @param network the network on which are applied voltage limit overrides.
* @return true if the integrity of voltage limit overrides is verified, false otherwise.
*/
boolean checkVoltageLimitOverrides(Network network) {
boolean checkVoltageLimitOverrides(Network network,
Map<String, Pair<Double, Double>> voltageLevelsWithInconsistentLimits) {
// Check integrity of voltage overrides
Map<String, Pair<Double, Double>> voltageLevelsLimitsAfterOverride = new HashMap<>();

boolean integrityVoltageLimitOverrides = true;
for (VoltageLimitOverride voltageLimitOverride : getSpecificVoltageLimits()) {
String voltageLevelId = voltageLimitOverride.getVoltageLevelId();
Expand All @@ -696,26 +806,28 @@ boolean checkVoltageLimitOverrides(Network network) {
}

if (voltageLimitOverride.isRelative()) {
double value = voltageLimitOverride.getVoltageLimitType() == VoltageLimitOverride.VoltageLimitType.LOW_VOLTAGE_LIMIT ?
voltageLevel.getLowVoltageLimit() : voltageLevel.getHighVoltageLimit();
if (Double.isNaN(value)) {
LOGGER.warn("Voltage level {} has undefined {}, relative voltage limit override is impossible.",
voltageLevelId, voltageLimitOverride.getVoltageLimitType());
integrityVoltageLimitOverrides = false;
}
// verify voltage limit override does not lead to negative limit value
if (value + voltageLimitOverride.getLimit() < 0) {
LOGGER.warn("Voltage level {} relative override leads to a negative {}.",
voltageLevelId, voltageLimitOverride.getVoltageLimitType());
integrityVoltageLimitOverrides &= checkRelativeVoltageLimitOverrides(voltageLimitOverride, voltageLevel, voltageLevelsLimitsAfterOverride, voltageLevelsWithInconsistentLimits);
} else {
checkAbsoluteVoltageLimitOverrides(voltageLimitOverride, voltageLevel, voltageLevelsLimitsAfterOverride);
}
}

// check low limit is lower than high limit after overrides
if (integrityVoltageLimitOverrides) {
for (Map.Entry<String, Pair<Double, Double>> entry : voltageLevelsLimitsAfterOverride.entrySet()) {
String vlId = entry.getKey();
if (entry.getValue().getLeft() > entry.getValue().getRight()) {
voltageLevelsWithInconsistentLimits.merge(vlId, Pair.of(entry.getValue().getLeft(), entry.getValue().getRight()), (old, newValue) -> Pair.of(entry.getValue().getLeft(), entry.getValue().getRight()));
integrityVoltageLimitOverrides = false;
}
}
}

return integrityVoltageLimitOverrides;
}

private List<VoltageLimitOverride> getSpecificVoltageLimits(String voltageLevelId, VoltageLimitOverride.VoltageLimitType type) {
return specificVoltageLimits.stream()
.filter(limit -> limit.getVoltageLevelId().equals(voltageLevelId) && limit.getVoltageLimitType() == type).collect(Collectors.toList());
.filter(limit -> limit.getVoltageLevelId().equals(voltageLevelId) && limit.getVoltageLimitType() == type).toList();
}
}
Loading

0 comments on commit 0f4983e

Please sign in to comment.