Skip to content

Commit 49c2b5f

Browse files
authored
Merge branch 'main' into Fix_NullPointerException_ModificationByAssignment
2 parents c96239c + 86439f8 commit 49c2b5f

File tree

11 files changed

+185
-21
lines changed

11 files changed

+185
-21
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
<groupId>org.gridsuite</groupId>
2121
<artifactId>gridsuite-network-modification</artifactId>
22-
<version>0.64.0-SNAPSHOT</version>
22+
<version>0.65.0-SNAPSHOT</version>
2323

2424
<packaging>jar</packaging>
2525
<name>Network modification library</name>

src/main/java/org/gridsuite/modification/modifications/GeneratorCreation.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ public void check(Network network) throws NetworkModificationException {
6969
checkIsNotNegativeValue(errorMessage, modificationInfos.getTargetV(), CREATE_GENERATOR_ERROR, "Target Voltage");
7070
checkIsPercentage(errorMessage, modificationInfos.getDroop(), CREATE_GENERATOR_ERROR, "Droop");
7171
checkIsNotNegativeValue(errorMessage, modificationInfos.getRatedS(), CREATE_GENERATOR_ERROR, "Rated apparent power");
72+
checkPowerValues(errorMessage, modificationInfos.getMinP(), modificationInfos.getMaxP(), modificationInfos.getTargetP(),
73+
modificationInfos.getPlannedActivePowerSetPoint(), CREATE_GENERATOR_ERROR);
7274
}
7375

7476
@Override

src/main/java/org/gridsuite/modification/modifications/GeneratorModification.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,28 @@ public void check(Network network) throws NetworkModificationException {
7272
if (modificationInfos.getTargetV() != null) {
7373
checkIsNotNegativeValue(errorMessage, modificationInfos.getTargetV().getValue(), MODIFY_GENERATOR_ERROR, TARGET_VOLTAGE);
7474
}
75+
checkPowerValues(errorMessage, generator);
76+
}
77+
78+
private void checkPowerValues(String errorMessage, Generator generator) {
79+
GeneratorStartup generatorStartup = generator.getExtension(GeneratorStartup.class);
80+
Double oldValue = generatorStartup != null && !Double.isNaN(generatorStartup.getPlannedActivePowerSetpoint())
81+
? generatorStartup.getPlannedActivePowerSetpoint() : null;
82+
double minP = modificationInfos.getMinP() != null ? modificationInfos.getMinP().getValue() : generator.getMinP();
83+
double maxP = modificationInfos.getMaxP() != null ? modificationInfos.getMaxP().getValue() : generator.getMaxP();
84+
double targetP = modificationInfos.getTargetP() != null ? modificationInfos.getTargetP().getValue() : generator.getTargetP();
85+
Double plannedActivePowerSetPoint = modificationInfos.getPlannedActivePowerSetPoint() != null ?
86+
modificationInfos.getPlannedActivePowerSetPoint().applyModification(oldValue) : null;
87+
88+
if (modificationInfos.getPlannedActivePowerSetPoint() != null) {
89+
checkActivePowerValue(errorMessage, FIELD_PLANNED_ACTIVE_POWER_SET_POINT, plannedActivePowerSetPoint, minP, maxP, MODIFY_GENERATOR_ERROR);
90+
}
91+
if (modificationInfos.getMaxP() != null) {
92+
checkMaximumActivePower(errorMessage, minP, targetP, plannedActivePowerSetPoint, maxP, MODIFY_GENERATOR_ERROR);
93+
}
94+
if (modificationInfos.getMinP() != null) {
95+
checkMinimumActivePower(errorMessage, maxP, targetP, plannedActivePowerSetPoint, minP, MODIFY_GENERATOR_ERROR);
96+
}
7597
}
7698

7799
private void checkActivePowerZeroOrBetweenMinAndMaxActivePowerGenerator(GeneratorModificationInfos modificationInfos, Generator generator, NetworkModificationException.Type exceptionType, String errorMessage) {

src/main/java/org/gridsuite/modification/modifications/byfilter/AbstractModificationByAssignment.java

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import com.powsybl.commons.report.ReportNode;
1111
import com.powsybl.commons.report.TypedValue;
12+
import com.powsybl.iidm.network.Generator;
1213
import com.powsybl.iidm.network.Identifiable;
1314
import com.powsybl.iidm.network.IdentifiableType;
1415
import com.powsybl.iidm.network.Network;
@@ -34,6 +35,7 @@
3435

3536
import static org.gridsuite.modification.dto.byfilter.equipmentfield.FieldUtils.getFieldValue;
3637
import static org.gridsuite.modification.dto.byfilter.equipmentfield.FieldUtils.setFieldValue;
38+
import static org.gridsuite.modification.dto.byfilter.equipmentfield.GeneratorField.*;
3739
import static org.gridsuite.modification.utils.ModificationUtils.*;
3840

3941
/**
@@ -43,6 +45,10 @@ public abstract class AbstractModificationByAssignment extends AbstractModificat
4345
public static final String VALUE_KEY_FILTER_NAME = "filterName";
4446
public static final String VALUE_KEY_FIELD_NAME = "fieldName";
4547
public static final String VALUE_KEY_NAME = "name";
48+
public static final String VALUE_KEY_FIELD_VALUE = "fieldValue";
49+
public static final String VALUE_KEY_MIN_VALUE = "minValue";
50+
public static final String VALUE_KEY_MAX_VALUE = "maxValue";
51+
public static final String VALUE_KEY_TARGET_VALUE = "targetValue";
4652
public static final String VALUE_KEY_EQUIPMENT_NAME = "equipmentName";
4753
public static final String VALUE_KEY_EQUIPMENT_TYPE = "equipmentType";
4854
public static final String VALUE_KEY_EQUIPMENT_COUNT = "equipmentCount";
@@ -57,8 +63,7 @@ public abstract class AbstractModificationByAssignment extends AbstractModificat
5763
public static final String VALUE_KEY_ARROW_NAME = "arrow";
5864
public static final String VALUE_KEY_ARROW_VALUE = "→";
5965
public static final String REPORT_KEY_EQUIPMENT_MODIFIED_ERROR_ZERO = "network.modification.equipmentModifiedError.zero";
60-
public static final String REPORT_KEY_EQUIPMENT_MODIFIED_ERROR_EMPTY = "network.modification.equipmentModifiedError.empty";
61-
public static final String REPORT_KEY_EQUIPMENT_MODIFIED_ERROR_NAN = "network.modification.equipmentModifiedError.nan";
66+
public static final String REPORT_KEY_EQUIPMENT_MODIFIED_ERROR_MISSING = "network.modification.equipmentModifiedError.missing";
6267
public static final String REPORT_KEY_BY_FILTER_MODIFICATION_SOME = "network.modification.byFilterModificationSome";
6368
public static final String REPORT_KEY_BY_FILTER_MODIFICATION_FAILED = "network.modification.byFilterModificationFailed";
6469
public static final String REPORT_KEY_BY_FILTER_MODIFICATION_SUCCESS = "network.modification.byFilterModificationSuccess";
@@ -105,6 +110,25 @@ protected abstract boolean preCheckValue(Identifiable<?> equipment,
105110

106111
protected abstract String getNewValue(Identifiable<?> equipment, AbstractAssignmentInfos abstractAssignmentInfos);
107112

113+
protected boolean checkGeneratorsPowerValues(Identifiable<?> equipment, AbstractAssignmentInfos abstractAssignmentInfos, List<ReportNode> reports) {
114+
if (equipment.getType() == IdentifiableType.GENERATOR) {
115+
Generator generator = (Generator) equipment;
116+
if (abstractAssignmentInfos.getEditedField().equals(PLANNED_ACTIVE_POWER_SET_POINT.name())) {
117+
return validateActivePowerValue(generator, FIELD_PLANNED_ACTIVE_POWER_SET_POINT, reports, Double.parseDouble(getNewValue(equipment, abstractAssignmentInfos)));
118+
} else if (abstractAssignmentInfos.getEditedField().equals(MINIMUM_ACTIVE_POWER.name())) {
119+
return validateMinimumActivePower(generator, reports, Double.parseDouble(getNewValue(equipment, abstractAssignmentInfos)));
120+
} else if (abstractAssignmentInfos.getEditedField().equals(MAXIMUM_ACTIVE_POWER.name())) {
121+
return validateMaximumActivePower(generator, reports, Double.parseDouble(getNewValue(equipment, abstractAssignmentInfos)));
122+
} else if (abstractAssignmentInfos.getEditedField().equals(ACTIVE_POWER_SET_POINT.name())) {
123+
double newValue = Double.parseDouble(getNewValue(equipment, abstractAssignmentInfos));
124+
if (newValue != 0) { // 0 is an exception to the rule
125+
return validateActivePowerValue(generator, FIELD_ACTIVE_POWER_TARGET, reports, newValue);
126+
}
127+
}
128+
}
129+
return true;
130+
}
131+
108132
protected String getOldValue(Identifiable<?> equipment, AbstractAssignmentInfos abstractAssignmentInfos) {
109133
return getFieldValue(equipment, abstractAssignmentInfos.getEditedField());
110134
}

src/main/java/org/gridsuite/modification/modifications/byfilter/ByFormulaModification.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,17 +68,17 @@ protected boolean preCheckValue(Identifiable<?> equipment, AbstractAssignmentInf
6868
FormulaInfos formulaInfos = (FormulaInfos) abstractAssignmentInfos;
6969
Double value1 = formulaInfos.getFieldOrValue1().getRefOrValue(equipment);
7070
Double value2 = formulaInfos.getFieldOrValue2().getRefOrValue(equipment);
71-
if (value1 == null || value2 == null) {
72-
return reportErrorOnEquipment(equipment, notEditableEquipments, REPORT_KEY_EQUIPMENT_MODIFIED_ERROR_EMPTY, reports);
73-
}
74-
71+
// value 1 and value 2 cannot be null because getRefOrValue returns NaN if value is null
7572
if (Double.isNaN(value1) || Double.isNaN(value2)) {
76-
return reportErrorOnEquipment(equipment, notEditableEquipments, REPORT_KEY_EQUIPMENT_MODIFIED_ERROR_NAN, reports);
73+
return reportErrorOnEquipment(equipment, notEditableEquipments, REPORT_KEY_EQUIPMENT_MODIFIED_ERROR_MISSING, reports);
7774
}
7875

7976
if (value2 == 0 && formulaInfos.getOperator() == Operator.DIVISION) {
8077
return reportErrorOnEquipment(equipment, notEditableEquipments, REPORT_KEY_EQUIPMENT_MODIFIED_ERROR_ZERO, reports);
8178
}
79+
if (equipment.getType() == IdentifiableType.GENERATOR) {
80+
return checkGeneratorsPowerValues(equipment, abstractAssignmentInfos, reports);
81+
}
8282
return true;
8383
}
8484

@@ -89,7 +89,7 @@ private boolean reportErrorOnEquipment(Identifiable<?> equipment, List<String> n
8989
.withResourceBundles(NetworkModificationReportResourceBundle.BASE_NAME)
9090
.withMessageTemplate(reportKey)
9191
.withUntypedValue(VALUE_KEY_EQUIPMENT_NAME, equipment.getId())
92-
.withSeverity(TypedValue.DETAIL_SEVERITY)
92+
.withSeverity(TypedValue.WARN_SEVERITY)
9393
.build());
9494
return false;
9595
}

src/main/java/org/gridsuite/modification/modifications/byfilter/ModificationByAssignment.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ protected boolean isEquipmentEditable(Identifiable<?> equipment, AbstractAssignm
7878

7979
@Override
8080
protected boolean preCheckValue(Identifiable<?> equipment, AbstractAssignmentInfos abstractAssignmentInfos, List<ReportNode> reports, List<String> notEditableEquipments) {
81+
if (equipment.getType() == IdentifiableType.GENERATOR) {
82+
return checkGeneratorsPowerValues(equipment, abstractAssignmentInfos, reports);
83+
}
8184
return true;
8285
}
8386

src/main/java/org/gridsuite/modification/utils/ModificationUtils.java

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import static org.gridsuite.modification.dto.OperationalLimitsGroupInfos.Applicability.SIDE1;
3838
import static org.gridsuite.modification.dto.OperationalLimitsGroupInfos.Applicability.SIDE2;
3939
import static org.gridsuite.modification.modifications.AbstractBranchModification.*;
40+
import static org.gridsuite.modification.modifications.byfilter.AbstractModificationByAssignment.*;
4041

4142
/**
4243
* @author Slimane Amar <slimane.amar at rte-france.com>
@@ -71,6 +72,10 @@ public final class ModificationUtils {
7172
private static final String COULD_NOT_ACTION_EQUIPMENT_ON_SIDE = COULD_NOT_ACTION_EQUIPMENT + " on side %s";
7273
public static final String CONNECT = "connect";
7374
public static final String DISCONNECT = "disconnect";
75+
public static final String FIELD_MAX_ACTIVE_POWER = "Maximum active power";
76+
public static final String FIELD_MIN_ACTIVE_POWER = "Minimum active power";
77+
public static final String FIELD_PLANNED_ACTIVE_POWER_SET_POINT = "Planned active power set point";
78+
public static final String FIELD_ACTIVE_POWER_TARGET = "Active power target";
7479

7580
public static String applicabilityToString(OperationalLimitsGroupInfos.Applicability applicability) {
7681
return switch (applicability) {
@@ -1921,6 +1926,110 @@ public static void checkLimitsGroupExist(String errorMessage, String limitsGroup
19211926
}
19221927
}
19231928

1929+
public static void checkActivePowerValue(String errorMessage, String fieldName, double newValue, double minP, double maxP, NetworkModificationException.Type exceptionType) throws NetworkModificationException {
1930+
if (newValue > maxP || newValue < minP) {
1931+
String message = String.format("Invalid value %.2f field %s should be within interval [%.2f; %.2f]", newValue, fieldName, minP, maxP);
1932+
throw new NetworkModificationException(exceptionType, errorMessage + message);
1933+
}
1934+
}
1935+
1936+
public static void checkPowerValues(String errorMessage, double minP, double maxP, double targetP, Double plannedActivePowerSetPoint, NetworkModificationException.Type exceptionType) throws NetworkModificationException {
1937+
if (targetP != 0) { // exception for the rule minP <= targetP <= maxP
1938+
checkActivePowerValue(errorMessage, FIELD_ACTIVE_POWER_TARGET, targetP, minP, maxP, exceptionType);
1939+
}
1940+
if (plannedActivePowerSetPoint != null) {
1941+
checkActivePowerValue(errorMessage, FIELD_PLANNED_ACTIVE_POWER_SET_POINT, plannedActivePowerSetPoint, minP, maxP, exceptionType);
1942+
}
1943+
checkMinimumActivePower(errorMessage, maxP, targetP, plannedActivePowerSetPoint, minP, exceptionType);
1944+
checkMaximumActivePower(errorMessage, minP, targetP, plannedActivePowerSetPoint, maxP, exceptionType);
1945+
}
1946+
1947+
public static void checkMinimumActivePower(String errorMessage, double maxP, double targetP, Double pImp, double newValue, NetworkModificationException.Type exceptionType) throws NetworkModificationException {
1948+
// targetP = 0 is an exception to the rule
1949+
double pMin = targetP != 0 ? Math.min(targetP, maxP) : maxP;
1950+
if (pImp != null) {
1951+
pMin = Math.min(pMin, pImp);
1952+
}
1953+
if (pMin < newValue) {
1954+
throw new NetworkModificationException(exceptionType, errorMessage + String.format("Invalid value %.2f of field %s should be be smaller or equal to %.2f", newValue, FIELD_MIN_ACTIVE_POWER, pMin));
1955+
}
1956+
}
1957+
1958+
public static void checkMaximumActivePower(String errorMessage, double minP, double targetP, Double plannedActivePowerSetPoint, double newValue, NetworkModificationException.Type exceptionType) throws NetworkModificationException {
1959+
// targetP = 0 is an exception to the rule
1960+
double pMax = targetP != 0 ? Math.max(targetP, minP) : minP;
1961+
if (plannedActivePowerSetPoint != null) {
1962+
pMax = Math.max(pMax, plannedActivePowerSetPoint);
1963+
}
1964+
if (pMax > newValue) {
1965+
throw new NetworkModificationException(exceptionType, errorMessage + String.format("Invalid value %.2f of field %s should be be greater or equal to %.2f", newValue, FIELD_MAX_ACTIVE_POWER, pMax));
1966+
}
1967+
}
1968+
1969+
public static boolean validateMinimumActivePower(Generator generator, List<ReportNode> reports, double newValue) {
1970+
GeneratorStartup generatorStartup = generator.getExtension(GeneratorStartup.class);
1971+
Double plannedActivePowerSetPoint = generatorStartup != null && !Double.isNaN(generatorStartup.getPlannedActivePowerSetpoint()) ? generatorStartup.getPlannedActivePowerSetpoint() : null;
1972+
1973+
// targetP = 0 is an exception to the rule
1974+
double minP = generator.getTargetP() != 0 ? Math.min(generator.getTargetP(), generator.getMaxP()) : generator.getMaxP();
1975+
if (plannedActivePowerSetPoint != null) {
1976+
minP = Math.min(minP, plannedActivePowerSetPoint);
1977+
}
1978+
1979+
if (minP < newValue) {
1980+
reports.add(ReportNode.newRootReportNode()
1981+
.withMessageTemplate("network.modification.generator.ValueShouldBeSmallerThan")
1982+
.withUntypedValue(VALUE_KEY_EQUIPMENT_NAME, generator.getId())
1983+
.withUntypedValue(VALUE_KEY_FIELD_NAME, FIELD_MIN_ACTIVE_POWER)
1984+
.withUntypedValue(VALUE_KEY_FIELD_VALUE, newValue)
1985+
.withUntypedValue(VALUE_KEY_TARGET_VALUE, minP)
1986+
.withSeverity(TypedValue.WARN_SEVERITY)
1987+
.build());
1988+
return false;
1989+
}
1990+
return true;
1991+
}
1992+
1993+
public static boolean validateMaximumActivePower(Generator generator, List<ReportNode> reports, double newValue) {
1994+
GeneratorStartup generatorStartup = generator.getExtension(GeneratorStartup.class);
1995+
Double pImp = generatorStartup != null && !Double.isNaN(generatorStartup.getPlannedActivePowerSetpoint()) ? generatorStartup.getPlannedActivePowerSetpoint() : null;
1996+
1997+
// targetP = 0 is an exception to the rule
1998+
double maxP = generator.getTargetP() != 0 ? Math.max(generator.getTargetP(), generator.getMinP()) : generator.getMinP();
1999+
if (pImp != null) {
2000+
maxP = Math.min(maxP, pImp);
2001+
}
2002+
2003+
if (newValue < maxP) {
2004+
reports.add(ReportNode.newRootReportNode()
2005+
.withMessageTemplate("network.modification.generator.ValueShouldBeGreaterThan")
2006+
.withUntypedValue(VALUE_KEY_EQUIPMENT_NAME, generator.getId())
2007+
.withUntypedValue(VALUE_KEY_FIELD_NAME, FIELD_MAX_ACTIVE_POWER)
2008+
.withUntypedValue(VALUE_KEY_FIELD_VALUE, newValue)
2009+
.withUntypedValue(VALUE_KEY_TARGET_VALUE, maxP)
2010+
.withSeverity(TypedValue.WARN_SEVERITY)
2011+
.build());
2012+
return false;
2013+
}
2014+
return true;
2015+
}
2016+
2017+
public static boolean validateActivePowerValue(Generator generator, String fieldName, List<ReportNode> reports, double newValue) {
2018+
if (newValue > generator.getMaxP() || newValue < generator.getMinP()) {
2019+
reports.add(ReportNode.newRootReportNode()
2020+
.withMessageTemplate("network.modification.generator.ValueShouldBeWithinInterval")
2021+
.withUntypedValue(VALUE_KEY_EQUIPMENT_NAME, generator.getId())
2022+
.withUntypedValue(VALUE_KEY_FIELD_NAME, fieldName)
2023+
.withUntypedValue(VALUE_KEY_FIELD_VALUE, newValue)
2024+
.withUntypedValue(VALUE_KEY_MIN_VALUE, generator.getMinP())
2025+
.withUntypedValue(VALUE_KEY_MAX_VALUE, generator.getMaxP())
2026+
.withSeverity(TypedValue.WARN_SEVERITY)
2027+
.build());
2028+
return false;
2029+
}
2030+
return true;
2031+
}
2032+
19242033
public static List<OperationalLimitsGroupInfos> getOperationalLimitsGroupsOnSide(List<OperationalLimitsGroupInfos> operationalLimitsGroupInfos,
19252034
OperationalLimitsGroupInfos.Applicability applicability) {
19262035
if (operationalLimitsGroupInfos == null || operationalLimitsGroupInfos.isEmpty()) {

0 commit comments

Comments
 (0)