From 461985c26fe1477c71beed8014af188bbb43ae11 Mon Sep 17 00:00:00 2001 From: basseche Date: Fri, 17 Jan 2025 11:46:18 +0100 Subject: [PATCH] Fix precision by formula modification (#18) --- .../byfilter/ByFormulaModification.java | 18 ++++++++--- .../AbstractByFormulaModificationTest.java | 2 ++ ...VoltageLevelByFormulaModificationTest.java | 31 ++++++++++++++++--- 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/gridsuite/modification/modifications/byfilter/ByFormulaModification.java b/src/main/java/org/gridsuite/modification/modifications/byfilter/ByFormulaModification.java index 72964d6..192a6e8 100644 --- a/src/main/java/org/gridsuite/modification/modifications/byfilter/ByFormulaModification.java +++ b/src/main/java/org/gridsuite/modification/modifications/byfilter/ByFormulaModification.java @@ -19,6 +19,8 @@ import org.gridsuite.modification.dto.byfilter.formula.Operator; import javax.annotation.Nonnull; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.util.Collections; import java.util.List; @@ -99,13 +101,19 @@ protected String getNewValue(Identifiable equipment, AbstractAssignmentInfos return applyOperation(formulaInfos.getOperator(), value1, value2).toString(); } + static final int MAX_SCALE = 10; + private Double applyOperation(Operator operator, @Nonnull Double value1, @Nonnull Double value2) { + BigDecimal bValue1 = BigDecimal.valueOf(value1); + BigDecimal bValue2 = BigDecimal.valueOf(value2); + return switch (operator) { - case ADDITION -> value1 + value2; - case SUBTRACTION -> value1 - value2; - case MULTIPLICATION -> value1 * value2; - case DIVISION -> value1 / value2; - case PERCENTAGE -> (value1 / 100) * value2; + case ADDITION -> bValue1.add(bValue2).doubleValue(); + case SUBTRACTION -> bValue1.subtract(bValue2).doubleValue(); + case MULTIPLICATION -> bValue1.multiply(bValue2).doubleValue(); + case DIVISION -> bValue1.divide(bValue2, MAX_SCALE, RoundingMode.HALF_EVEN).doubleValue(); + case PERCENTAGE -> bValue1.divide(BigDecimal.valueOf(100.0), MAX_SCALE, RoundingMode.HALF_EVEN) + .multiply(bValue2).doubleValue(); }; } diff --git a/src/test/java/org/gridsuite/modification/modifications/byfilter/formula/AbstractByFormulaModificationTest.java b/src/test/java/org/gridsuite/modification/modifications/byfilter/formula/AbstractByFormulaModificationTest.java index b800214..1147c66 100644 --- a/src/test/java/org/gridsuite/modification/modifications/byfilter/formula/AbstractByFormulaModificationTest.java +++ b/src/test/java/org/gridsuite/modification/modifications/byfilter/formula/AbstractByFormulaModificationTest.java @@ -41,6 +41,7 @@ abstract class AbstractByFormulaModificationTest extends AbstractNetworkModifica protected static final UUID FILTER_ID_4 = UUID.randomUUID(); protected static final UUID FILTER_ID_5 = UUID.randomUUID(); protected static final UUID FILTER_ID_6 = UUID.randomUUID(); + protected static final UUID FILTER_ID_7 = UUID.randomUUID(); protected static final UUID FILTER_WITH_ALL_WRONG_IDS = UUID.randomUUID(); protected static final UUID FILTER_WITH_ONE_WRONG_ID = UUID.randomUUID(); protected final FilterInfos filter1 = new FilterInfos(FILTER_ID_1, "filter1"); @@ -49,6 +50,7 @@ abstract class AbstractByFormulaModificationTest extends AbstractNetworkModifica protected final FilterInfos filter4 = new FilterInfos(FILTER_ID_4, "filter4"); protected final FilterInfos filter5 = new FilterInfos(FILTER_ID_5, "filter5"); protected final FilterInfos filter6 = new FilterInfos(FILTER_ID_6, "filter6"); + protected final FilterInfos filter7 = new FilterInfos(FILTER_ID_7, "filter7"); protected final FilterInfos filterWithOneWrongId = new FilterInfos(FILTER_WITH_ONE_WRONG_ID, "filterWithOneWrongId"); @Mock diff --git a/src/test/java/org/gridsuite/modification/modifications/byfilter/formula/VoltageLevelByFormulaModificationTest.java b/src/test/java/org/gridsuite/modification/modifications/byfilter/formula/VoltageLevelByFormulaModificationTest.java index cf92423..739065d 100644 --- a/src/test/java/org/gridsuite/modification/modifications/byfilter/formula/VoltageLevelByFormulaModificationTest.java +++ b/src/test/java/org/gridsuite/modification/modifications/byfilter/formula/VoltageLevelByFormulaModificationTest.java @@ -37,6 +37,7 @@ class VoltageLevelByFormulaModificationTest extends AbstractByFormulaModificatio private static final String VOLTAGE_LEVEL_ID_5 = "v5"; private static final String VOLTAGE_LEVEL_ID_6 = "v6"; private static final String VOLTAGE_LEVEL_ID_7 = "v7"; + private static final String VOLTAGE_LEVEL_ID_8 = "v8"; @Override protected void createEquipments() { @@ -72,6 +73,9 @@ protected void createEquipments() { getNetwork().getSubstation("s1").newVoltageLevel().setId(VOLTAGE_LEVEL_ID_7) .setTopologyKind(TopologyKind.NODE_BREAKER).setNominalV(380.).add(); + + getNetwork().getSubstation("s2").newVoltageLevel().setId(VOLTAGE_LEVEL_ID_8) + .setTopologyKind(TopologyKind.NODE_BREAKER).setNominalV(100.).add(); } @Override @@ -105,7 +109,12 @@ protected Map getTestFilters() { new IdentifiableAttributes(VOLTAGE_LEVEL_ID_7, getIdentifiableType(), 5.0))) .build(); - return Map.of(FILTER_ID_1, filter1, FILTER_ID_2, filter2, FILTER_ID_3, filter3, FILTER_ID_4, filter4, FILTER_ID_5, filter5, FILTER_ID_6, filter6); + FilterEquipments filter7 = FilterEquipments.builder().filterId(FILTER_ID_7).identifiableAttributes(List.of( + new IdentifiableAttributes(VOLTAGE_LEVEL_ID_8, getIdentifiableType(), 8.0))) + .build(); + + return Map.of(FILTER_ID_1, filter1, FILTER_ID_2, filter2, FILTER_ID_3, filter3, FILTER_ID_4, filter4, + FILTER_ID_5, filter5, FILTER_ID_6, filter6, FILTER_ID_7, filter7); } @Override @@ -173,8 +182,20 @@ protected List getFormulaInfos() { ReferenceFieldOrValue.builder().equipmentField(VoltageLevelField.LOW_SHORT_CIRCUIT_CURRENT_LIMIT.name()).build() ); + FormulaInfos formulaInfos10 = getFormulaInfo(VoltageLevelField.LOW_VOLTAGE_LIMIT.name(), + List.of(filter7), + Operator.MULTIPLICATION, + ReferenceFieldOrValue.builder().value(100.).build(), + ReferenceFieldOrValue.builder().value(1.1).build()); + + FormulaInfos formulaInfos11 = getFormulaInfo(VoltageLevelField.HIGH_VOLTAGE_LIMIT.name(), + List.of(filter7), + Operator.DIVISION, + ReferenceFieldOrValue.builder().value(1000.).build(), + ReferenceFieldOrValue.builder().value(3.).build()); + return List.of(formulaInfos1, formulaInfos2, formulaInfos3, formulaInfos4, formulaInfos5, - formulaInfos6, formulaInfos7, formulaInfos8, formulaInfos9); + formulaInfos6, formulaInfos7, formulaInfos8, formulaInfos9, formulaInfos10, formulaInfos11); } @Override @@ -216,7 +237,9 @@ protected void assertAfterNetworkModificationApplication() { assertTrue(Double.isNaN(getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_7).getLowVoltageLimit())); assertTrue(Double.isNaN(getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_7).getHighVoltageLimit())); - //assertLogMessageWithoutRank("Cannot modify equipment v7 : At least one of the value or referenced field is null", REPORT_KEY_EQUIPMENT_MODIFIED_ERROR, reportService); - //assertLogMessageWithoutRank("Some of the equipment have been modified : 14 equipment(s) modified and 4 equipment(s) not modified", REPORT_KEY_BY_FILTER_MODIFICATION_SOME, reportService); + + //Precision tests + assertEquals(110., getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_8).getLowVoltageLimit(), 0.); + assertEquals(333.3333333333, getNetwork().getVoltageLevel(VOLTAGE_LEVEL_ID_8).getHighVoltageLimit(), 0.); //scale is defined in byFormulaModifcation (10) } }