From 0b531a1188d5cbb74fd065e161fd99f5c8a43d20 Mon Sep 17 00:00:00 2001 From: LE SAULNIER Kevin Date: Thu, 4 Sep 2025 14:53:21 +0200 Subject: [PATCH 1/7] feat: new fields in SA results - limit violations Signed-off-by: LE SAULNIER Kevin --- .../server/dto/LimitViolationDTO.java | 6 ++ .../AbstractLimitViolationEntity.java | 70 +++++++++++++++++-- .../ContingencyLimitViolationEntity.java | 14 ++-- .../PreContingencyLimitViolationEntity.java | 2 +- .../changesets/changelog_20250903T125946Z.xml | 43 ++++++++++++ .../db/changelog/db.changelog-master.yaml | 3 + 6 files changed, 128 insertions(+), 10 deletions(-) create mode 100644 src/main/resources/db/changelog/changesets/changelog_20250903T125946Z.xml diff --git a/src/main/java/org/gridsuite/securityanalysis/server/dto/LimitViolationDTO.java b/src/main/java/org/gridsuite/securityanalysis/server/dto/LimitViolationDTO.java index 3dbee102..bcd34264 100644 --- a/src/main/java/org/gridsuite/securityanalysis/server/dto/LimitViolationDTO.java +++ b/src/main/java/org/gridsuite/securityanalysis/server/dto/LimitViolationDTO.java @@ -22,24 +22,30 @@ public class LimitViolationDTO { private LimitViolationType limitType; private String limitName; + private String nextLimitName; private ThreeSides side; private int acceptableDuration; private double limit; + private Double patlLimit; private double limitReduction; private double value; private Double loading; + private Double patlLoading; private String locationId; public static LimitViolationDTO toDto(AbstractLimitViolationEntity limitViolation) { return LimitViolationDTO.builder() .limitType(limitViolation.getLimitType()) .limitName(limitViolation.getLimitName()) + .nextLimitName(limitViolation.getNextLimitName()) .side(limitViolation.getSide()) .acceptableDuration((int) limitViolation.getAcceptableDuration()) .limit(limitViolation.getLimit()) + .patlLimit(limitViolation.getPatlLimit()) .limitReduction(limitViolation.getLimitReduction()) .value(limitViolation.getValue()) .loading(limitViolation.getLoading()) + .patlLoading(limitViolation.getPatlLoading()) .locationId(limitViolation.getLocationId()) .build(); } diff --git a/src/main/java/org/gridsuite/securityanalysis/server/entities/AbstractLimitViolationEntity.java b/src/main/java/org/gridsuite/securityanalysis/server/entities/AbstractLimitViolationEntity.java index 2bc0dc7c..7432c8a5 100644 --- a/src/main/java/org/gridsuite/securityanalysis/server/entities/AbstractLimitViolationEntity.java +++ b/src/main/java/org/gridsuite/securityanalysis/server/entities/AbstractLimitViolationEntity.java @@ -6,7 +6,8 @@ */ package org.gridsuite.securityanalysis.server.entities; -import com.powsybl.iidm.network.ThreeSides; +import com.powsybl.iidm.network.*; +import com.powsybl.iidm.network.util.LimitViolationUtils; import com.powsybl.security.LimitViolation; import com.powsybl.security.LimitViolationType; import jakarta.persistence.*; @@ -16,6 +17,8 @@ import lombok.experimental.FieldNameConstants; import lombok.experimental.SuperBuilder; +import java.util.Iterator; +import java.util.Optional; import java.util.UUID; /** @@ -40,8 +43,12 @@ public abstract class AbstractLimitViolationEntity { @Column(name = "limitValue") private double limit; + private Double patlLimit; + private String limitName; + private String nextLimitName; + @Enumerated(EnumType.STRING) private LimitViolationType limitType; @@ -58,12 +65,67 @@ public abstract class AbstractLimitViolationEntity { @Column(name = "loading") private Double loading; + private Double patlLoading; + @Column private String locationId; - public static Double computeLoading(LimitViolation limitViolation) { - return LimitViolationType.CURRENT.equals(limitViolation.getLimitType()) - ? 100 * limitViolation.getValue() / limitViolation.getLimit() + public static Double computeLoading(LimitViolation limitViolation, Double limit) { + return LimitViolationType.CURRENT.equals(limitViolation.getLimitType()) && limit != null + ? 100 * limitViolation.getValue() / limit : null; } + + public static Double getPatlLimit(LimitViolation limitViolation, Network network) { + String equipmentId = limitViolation.getSubjectId(); + Branch branch = network.getBranch(equipmentId); + ThreeSides limitViolationSide = limitViolation.getSide(); + if (branch == null || limitViolationSide == null) { + return null; + } + + Optional currentLimits = limitViolationSide.name().equals(TwoSides.ONE.name()) ? branch.getCurrentLimits1() : branch.getCurrentLimits2(); + if (currentLimits.isPresent()) { + return currentLimits.get().getPermanentLimit(); + } + return null; + } + + public static String getNextLimitName(LimitViolation limitViolation, Network network) { + String equipmentId = limitViolation.getSubjectId(); + Branch branch = network.getBranch(equipmentId); + if (branch == null) { + return null; + } + LoadingLimits.TemporaryLimit temporaryLimit = getNextTemporaryLimit(branch, limitViolation); + return temporaryLimit != null ? temporaryLimit.getName() : null; + } + + private static LoadingLimits.TemporaryLimit getNextTemporaryLimit(Branch branch, LimitViolation limitViolation) { + // limits are returned from the store by DESC duration / ASC value + ThreeSides limitViolationSide = limitViolation.getSide(); + String limitName = limitViolation.getLimitName(); + if (limitViolationSide == null || limitName == null) { + return null; + } + + Optional currentLimits = limitViolationSide.name().equals(TwoSides.ONE.name()) ? branch.getCurrentLimits1() : branch.getCurrentLimits2(); + if (currentLimits.isEmpty()) { + return null; + } + + if (limitName.equals(LimitViolationUtils.PERMANENT_LIMIT_NAME)) { + return currentLimits.get().getTemporaryLimits().stream().findFirst().orElse(null); + } + + Iterator temporaryLimitIterator = currentLimits.get().getTemporaryLimits().iterator(); + while (temporaryLimitIterator.hasNext()) { + LoadingLimits.TemporaryLimit currentTemporaryLimit = temporaryLimitIterator.next(); + if (currentTemporaryLimit.getName().equals(limitViolation.getLimitName())) { + return temporaryLimitIterator.hasNext() ? temporaryLimitIterator.next() : null; + } + } + + return null; + } } diff --git a/src/main/java/org/gridsuite/securityanalysis/server/entities/ContingencyLimitViolationEntity.java b/src/main/java/org/gridsuite/securityanalysis/server/entities/ContingencyLimitViolationEntity.java index 2e5e0539..8b41f9be 100644 --- a/src/main/java/org/gridsuite/securityanalysis/server/entities/ContingencyLimitViolationEntity.java +++ b/src/main/java/org/gridsuite/securityanalysis/server/entities/ContingencyLimitViolationEntity.java @@ -6,16 +6,15 @@ */ package org.gridsuite.securityanalysis.server.entities; -import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.*; import com.powsybl.security.LimitViolation; +import com.powsybl.security.LimitViolationType; import org.gridsuite.computation.utils.ComputationResultUtils; import jakarta.persistence.*; import lombok.*; import lombok.experimental.FieldNameConstants; import lombok.experimental.SuperBuilder; - - /** * @author Kevin Le Saulnier */ @@ -33,17 +32,22 @@ public class ContingencyLimitViolationEntity extends AbstractLimitViolationEntit private ContingencyEntity contingency; public static ContingencyLimitViolationEntity toEntity(Network network, LimitViolation limitViolation, SubjectLimitViolationEntity subjectLimitViolation) { + Double patlLimit = getPatlLimit(limitViolation, network); + ContingencyLimitViolationEntity contingencyLimitViolationEntity = ContingencyLimitViolationEntity.builder() .limit(limitViolation.getLimit()) .limitName(limitViolation.getLimitName()) .limitType(limitViolation.getLimitType()) - .acceptableDuration(limitViolation.getAcceptableDuration()) .limitReduction(limitViolation.getLimitReduction()) .value(limitViolation.getValue()) .side(limitViolation.getSide()) - .loading(computeLoading(limitViolation)) + .loading(computeLoading(limitViolation, limitViolation.getLimit())) .locationId(ComputationResultUtils.getViolationLocationId(limitViolation, network)) .subjectLimitViolation(subjectLimitViolation) + .patlLimit(patlLimit) + .patlLoading(computeLoading(limitViolation, patlLimit)) + .nextLimitName(getNextLimitName(limitViolation, network)) + .acceptableDuration(limitViolation.getAcceptableDuration()) .build(); subjectLimitViolation.addContingencyLimitViolation(contingencyLimitViolationEntity); diff --git a/src/main/java/org/gridsuite/securityanalysis/server/entities/PreContingencyLimitViolationEntity.java b/src/main/java/org/gridsuite/securityanalysis/server/entities/PreContingencyLimitViolationEntity.java index 771d014d..710c6626 100644 --- a/src/main/java/org/gridsuite/securityanalysis/server/entities/PreContingencyLimitViolationEntity.java +++ b/src/main/java/org/gridsuite/securityanalysis/server/entities/PreContingencyLimitViolationEntity.java @@ -52,7 +52,7 @@ public static PreContingencyLimitViolationEntity toEntity(Network network, Limit .limitReduction(limitViolation.getLimitReduction()) .value(limitViolation.getValue()) .side(limitViolation.getSide()) - .loading(computeLoading(limitViolation)) + .loading(computeLoading(limitViolation, limitViolation.getLimit())) .locationId(ComputationResultUtils.getViolationLocationId(limitViolation, network)) .build(); } diff --git a/src/main/resources/db/changelog/changesets/changelog_20250903T125946Z.xml b/src/main/resources/db/changelog/changesets/changelog_20250903T125946Z.xml new file mode 100644 index 00000000..9c0cd2e5 --- /dev/null +++ b/src/main/resources/db/changelog/changesets/changelog_20250903T125946Z.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index 4c87c5db..366cada8 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -45,3 +45,6 @@ databaseChangeLog: - include: file: changesets/changelog_20250827T095600Z.xml relativeToChangelogFile: true + - include: + file: changesets/changelog_20250903T125946Z.xml + relativeToChangelogFile: true From 2d417f61fa4ccc97fa12f27c7fa1b0fc4920f0c7 Mon Sep 17 00:00:00 2001 From: LE SAULNIER Kevin Date: Thu, 4 Sep 2025 14:56:53 +0200 Subject: [PATCH 2/7] fix: checkstyle Signed-off-by: LE SAULNIER Kevin --- .../server/entities/ContingencyLimitViolationEntity.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/org/gridsuite/securityanalysis/server/entities/ContingencyLimitViolationEntity.java b/src/main/java/org/gridsuite/securityanalysis/server/entities/ContingencyLimitViolationEntity.java index 8b41f9be..3bd83583 100644 --- a/src/main/java/org/gridsuite/securityanalysis/server/entities/ContingencyLimitViolationEntity.java +++ b/src/main/java/org/gridsuite/securityanalysis/server/entities/ContingencyLimitViolationEntity.java @@ -8,7 +8,6 @@ import com.powsybl.iidm.network.*; import com.powsybl.security.LimitViolation; -import com.powsybl.security.LimitViolationType; import org.gridsuite.computation.utils.ComputationResultUtils; import jakarta.persistence.*; import lombok.*; From b4fb9fadf1bdf1b4f09edf55c005d23f3f734882 Mon Sep 17 00:00:00 2001 From: LE SAULNIER Kevin Date: Fri, 5 Sep 2025 09:07:06 +0200 Subject: [PATCH 3/7] fix: tests Signed-off-by: LE SAULNIER Kevin --- .../changesets/changelog_20250903T125946Z.xml | 10 --- .../server/SecurityAnalysisProviderMock.java | 66 +++++++++---------- 2 files changed, 33 insertions(+), 43 deletions(-) diff --git a/src/main/resources/db/changelog/changesets/changelog_20250903T125946Z.xml b/src/main/resources/db/changelog/changesets/changelog_20250903T125946Z.xml index 9c0cd2e5..d1b680ca 100644 --- a/src/main/resources/db/changelog/changesets/changelog_20250903T125946Z.xml +++ b/src/main/resources/db/changelog/changesets/changelog_20250903T125946Z.xml @@ -20,16 +20,6 @@ - - - - - - - - - - diff --git a/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisProviderMock.java b/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisProviderMock.java index 53bfaf91..2201d464 100644 --- a/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisProviderMock.java +++ b/src/test/java/org/gridsuite/securityanalysis/server/SecurityAnalysisProviderMock.java @@ -231,17 +231,17 @@ private static SubjectLimitViolationDTO toSubjectLimitViolationDTO(LimitViolatio return new SubjectLimitViolationDTO( limitViolation.getSubjectId(), - new LimitViolationDTO( - limitViolation.getLimitType(), - limitViolation.getLimitName(), - limitViolation.getSide(), - limitViolation.getAcceptableDuration(), - limitViolation.getLimit(), - limitViolation.getLimitReduction(), - limitViolation.getValue(), - computedLoading, - ComputationResultUtils.getViolationLocationId(limitViolation, getNetwork()) - ) + LimitViolationDTO.builder() + .limitType(limitViolation.getLimitType()) + .limitName(limitViolation.getLimitName()) + .side(limitViolation.getSide()) + .acceptableDuration(limitViolation.getAcceptableDuration()) + .limit(limitViolation.getLimit()) + .limitReduction(limitViolation.getLimitReduction()) + .value(limitViolation.getValue()) + .loading(computedLoading) + .locationId(ComputationResultUtils.getViolationLocationId(limitViolation, getNetwork())) + .build() ); } @@ -258,17 +258,17 @@ private static PreContingencyLimitViolationResultDTO toPreContingencyResultDTO(L return new PreContingencyLimitViolationResultDTO( limitViolation.getSubjectId(), status.name(), - new LimitViolationDTO( - limitViolation.getLimitType(), - limitViolation.getLimitName(), - limitViolation.getSide(), - limitViolation.getAcceptableDuration(), - limitViolation.getLimit(), - limitViolation.getLimitReduction(), - limitViolation.getValue(), - computedLoading, - ComputationResultUtils.getViolationLocationId(limitViolation, getNetwork()) - )); + LimitViolationDTO.builder() + .limitType(limitViolation.getLimitType()) + .limitName(limitViolation.getLimitName()) + .side(limitViolation.getSide()) + .acceptableDuration(limitViolation.getAcceptableDuration()) + .limit(limitViolation.getLimit()) + .limitReduction(limitViolation.getLimitReduction()) + .value(limitViolation.getValue()) + .loading(computedLoading) + .locationId(ComputationResultUtils.getViolationLocationId(limitViolation, getNetwork())) + .build()); } private static ContingencyResultDTO toContingencyResultDTO(Contingency contingency, String status, List limitViolations) { @@ -295,17 +295,17 @@ private static ContingencyLimitViolationDTO toContingencyLimitViolationDTO(Conti status, contingency.getElements().stream().map(e -> new ContingencyElementDTO(e.getId(), e.getType())).toList() ), - new LimitViolationDTO( - limitViolation.getLimitType(), - limitViolation.getLimitName(), - limitViolation.getSide(), - limitViolation.getAcceptableDuration(), - limitViolation.getLimit(), - limitViolation.getLimitReduction(), - limitViolation.getValue(), - computedLoading, - ComputationResultUtils.getViolationLocationId(limitViolation, getNetwork()) - ) + LimitViolationDTO.builder() + .limitType(limitViolation.getLimitType()) + .limitName(limitViolation.getLimitName()) + .side(limitViolation.getSide()) + .acceptableDuration(limitViolation.getAcceptableDuration()) + .limit(limitViolation.getLimit()) + .limitReduction(limitViolation.getLimitReduction()) + .value(limitViolation.getValue()) + .loading(computedLoading) + .locationId(ComputationResultUtils.getViolationLocationId(limitViolation, getNetwork())) + .build() ); } From 7900edb9673fa98806acb58af6294bd4c50481a1 Mon Sep 17 00:00:00 2001 From: LE SAULNIER Kevin Date: Fri, 5 Sep 2025 11:39:13 +0200 Subject: [PATCH 4/7] test: coverage Signed-off-by: LE SAULNIER Kevin --- .../AbstractLimitViolationEntity.java | 6 +- .../server/ContingencyLimitViolationTest.java | 56 +++++++++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 src/test/java/org/gridsuite/securityanalysis/server/ContingencyLimitViolationTest.java diff --git a/src/main/java/org/gridsuite/securityanalysis/server/entities/AbstractLimitViolationEntity.java b/src/main/java/org/gridsuite/securityanalysis/server/entities/AbstractLimitViolationEntity.java index 7432c8a5..a055b884 100644 --- a/src/main/java/org/gridsuite/securityanalysis/server/entities/AbstractLimitViolationEntity.java +++ b/src/main/java/org/gridsuite/securityanalysis/server/entities/AbstractLimitViolationEntity.java @@ -70,13 +70,13 @@ public abstract class AbstractLimitViolationEntity { @Column private String locationId; - public static Double computeLoading(LimitViolation limitViolation, Double limit) { + protected static Double computeLoading(LimitViolation limitViolation, Double limit) { return LimitViolationType.CURRENT.equals(limitViolation.getLimitType()) && limit != null ? 100 * limitViolation.getValue() / limit : null; } - public static Double getPatlLimit(LimitViolation limitViolation, Network network) { + protected static Double getPatlLimit(LimitViolation limitViolation, Network network) { String equipmentId = limitViolation.getSubjectId(); Branch branch = network.getBranch(equipmentId); ThreeSides limitViolationSide = limitViolation.getSide(); @@ -91,7 +91,7 @@ public static Double getPatlLimit(LimitViolation limitViolation, Network network return null; } - public static String getNextLimitName(LimitViolation limitViolation, Network network) { + protected static String getNextLimitName(LimitViolation limitViolation, Network network) { String equipmentId = limitViolation.getSubjectId(); Branch branch = network.getBranch(equipmentId); if (branch == null) { diff --git a/src/test/java/org/gridsuite/securityanalysis/server/ContingencyLimitViolationTest.java b/src/test/java/org/gridsuite/securityanalysis/server/ContingencyLimitViolationTest.java new file mode 100644 index 00000000..e1f7fc83 --- /dev/null +++ b/src/test/java/org/gridsuite/securityanalysis/server/ContingencyLimitViolationTest.java @@ -0,0 +1,56 @@ +/** + * Copyright (c) 2023, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package org.gridsuite.securityanalysis.server; + +import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.TwoSides; +import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; +import com.powsybl.iidm.network.util.LimitViolationUtils; +import com.powsybl.security.LimitViolation; +import com.powsybl.security.LimitViolationBuilder; +import com.powsybl.security.LimitViolationType; +import org.gridsuite.securityanalysis.server.entities.ContingencyLimitViolationEntity; +import org.gridsuite.securityanalysis.server.entities.SubjectLimitViolationEntity; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * @author Kevin Le Saulnier + */ +@SpringBootTest +class ContingencyLimitViolationTest { + + @Test + void testContingencyLimitViolationEntityNewFields() { + Network network = EurostagTutorialExample1Factory.createWithFixedCurrentLimits(); + LimitViolation limitViolation = new LimitViolation("NHV1_NHV2_1", "NHV1_NHV2_1", LimitViolationType.CURRENT, "10'", 10 * 60, 1200, 1, 1250, TwoSides.TWO); + + SubjectLimitViolationEntity subjectLimitViolationEntity = new SubjectLimitViolationEntity("NHV1_NHV2_1", "NHV1_NHV2_1_name"); + + ContingencyLimitViolationEntity contingencyLimitViolationEntity = ContingencyLimitViolationEntity.toEntity(network, limitViolation, subjectLimitViolationEntity); + + assertEquals("1'", contingencyLimitViolationEntity.getNextLimitName()); + assertEquals(1100, contingencyLimitViolationEntity.getPatlLimit()); + assertEquals(100 * limitViolation.getValue() / contingencyLimitViolationEntity.getPatlLimit(), contingencyLimitViolationEntity.getPatlLoading()); + } + + @Test + void testContingencyLimitViolationEntityNewFieldsWithPermanentLimitReached() { + Network network = EurostagTutorialExample1Factory.createWithFixedCurrentLimits(); + LimitViolation limitViolation = new LimitViolation("NHV1_NHV2_1", "NHV1_NHV2_1", LimitViolationType.CURRENT, LimitViolationUtils.PERMANENT_LIMIT_NAME, 10 * 60, 1100, 1, 1150, TwoSides.TWO); + + SubjectLimitViolationEntity subjectLimitViolationEntity = new SubjectLimitViolationEntity("NHV1_NHV2_1", "NHV1_NHV2_1_name"); + + ContingencyLimitViolationEntity contingencyLimitViolationEntity = ContingencyLimitViolationEntity.toEntity(network, limitViolation, subjectLimitViolationEntity); + + assertEquals("10'", contingencyLimitViolationEntity.getNextLimitName()); + assertEquals(1100, contingencyLimitViolationEntity.getPatlLimit()); + assertEquals(100 * limitViolation.getValue() / contingencyLimitViolationEntity.getPatlLimit(), contingencyLimitViolationEntity.getPatlLoading()); + } +} From aae7f1f02cd9ffa528ec95651058115ca5260823 Mon Sep 17 00:00:00 2001 From: LE SAULNIER Kevin Date: Fri, 5 Sep 2025 11:39:36 +0200 Subject: [PATCH 5/7] fix: checkstyle Signed-off-by: LE SAULNIER Kevin --- .../securityanalysis/server/ContingencyLimitViolationTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/java/org/gridsuite/securityanalysis/server/ContingencyLimitViolationTest.java b/src/test/java/org/gridsuite/securityanalysis/server/ContingencyLimitViolationTest.java index e1f7fc83..56d46e82 100644 --- a/src/test/java/org/gridsuite/securityanalysis/server/ContingencyLimitViolationTest.java +++ b/src/test/java/org/gridsuite/securityanalysis/server/ContingencyLimitViolationTest.java @@ -11,7 +11,6 @@ import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; import com.powsybl.iidm.network.util.LimitViolationUtils; import com.powsybl.security.LimitViolation; -import com.powsybl.security.LimitViolationBuilder; import com.powsybl.security.LimitViolationType; import org.gridsuite.securityanalysis.server.entities.ContingencyLimitViolationEntity; import org.gridsuite.securityanalysis.server.entities.SubjectLimitViolationEntity; From 2cd3ce62a410da31a69ce228fe2b923099598b45 Mon Sep 17 00:00:00 2001 From: LE SAULNIER Kevin Date: Fri, 5 Sep 2025 12:04:32 +0200 Subject: [PATCH 6/7] test: coverage Signed-off-by: LE SAULNIER Kevin --- .../server/ContingencyLimitViolationTest.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/test/java/org/gridsuite/securityanalysis/server/ContingencyLimitViolationTest.java b/src/test/java/org/gridsuite/securityanalysis/server/ContingencyLimitViolationTest.java index 56d46e82..4127cec5 100644 --- a/src/test/java/org/gridsuite/securityanalysis/server/ContingencyLimitViolationTest.java +++ b/src/test/java/org/gridsuite/securityanalysis/server/ContingencyLimitViolationTest.java @@ -27,29 +27,34 @@ class ContingencyLimitViolationTest { @Test void testContingencyLimitViolationEntityNewFields() { - Network network = EurostagTutorialExample1Factory.createWithFixedCurrentLimits(); - LimitViolation limitViolation = new LimitViolation("NHV1_NHV2_1", "NHV1_NHV2_1", LimitViolationType.CURRENT, "10'", 10 * 60, 1200, 1, 1250, TwoSides.TWO); - - SubjectLimitViolationEntity subjectLimitViolationEntity = new SubjectLimitViolationEntity("NHV1_NHV2_1", "NHV1_NHV2_1_name"); + testContingencyLimitViolationMapping("10'", 10 * 60, 1200, 1250, TwoSides.TWO, "1'", 1100); + } - ContingencyLimitViolationEntity contingencyLimitViolationEntity = ContingencyLimitViolationEntity.toEntity(network, limitViolation, subjectLimitViolationEntity); + @Test + void testContingencyLimitViolationEntityNewFieldsWithPermanentLimitReached() { + testContingencyLimitViolationMapping(LimitViolationUtils.PERMANENT_LIMIT_NAME, Integer.MAX_VALUE, 1100, 1150, TwoSides.TWO, "10'", 1100); + } - assertEquals("1'", contingencyLimitViolationEntity.getNextLimitName()); - assertEquals(1100, contingencyLimitViolationEntity.getPatlLimit()); - assertEquals(100 * limitViolation.getValue() / contingencyLimitViolationEntity.getPatlLimit(), contingencyLimitViolationEntity.getPatlLoading()); + @Test + void testContingencyLimitViolationEntityNewFieldsWithPermanentLimitReachedAndNoTemporaryLimit() { + testContingencyLimitViolationMapping(LimitViolationUtils.PERMANENT_LIMIT_NAME, Integer.MAX_VALUE, 500, 1000, TwoSides.ONE, null, 500); } @Test - void testContingencyLimitViolationEntityNewFieldsWithPermanentLimitReached() { + void testContingencyLimitViolationEntityNewFieldsWithLastLimitReached() { + testContingencyLimitViolationMapping("N/A", 0, 1100, 3000, TwoSides.TWO, null, 1100); + } + + private void testContingencyLimitViolationMapping(String limitName, int acceptableDuration, double limit, double value, TwoSides side, String expectedNextLimitName, long expectedPatlLimit) { Network network = EurostagTutorialExample1Factory.createWithFixedCurrentLimits(); - LimitViolation limitViolation = new LimitViolation("NHV1_NHV2_1", "NHV1_NHV2_1", LimitViolationType.CURRENT, LimitViolationUtils.PERMANENT_LIMIT_NAME, 10 * 60, 1100, 1, 1150, TwoSides.TWO); + LimitViolation limitViolation = new LimitViolation("NHV1_NHV2_1", "NHV1_NHV2_1_name", LimitViolationType.CURRENT, limitName, acceptableDuration, limit, 1, value, side); SubjectLimitViolationEntity subjectLimitViolationEntity = new SubjectLimitViolationEntity("NHV1_NHV2_1", "NHV1_NHV2_1_name"); ContingencyLimitViolationEntity contingencyLimitViolationEntity = ContingencyLimitViolationEntity.toEntity(network, limitViolation, subjectLimitViolationEntity); - assertEquals("10'", contingencyLimitViolationEntity.getNextLimitName()); - assertEquals(1100, contingencyLimitViolationEntity.getPatlLimit()); + assertEquals(expectedNextLimitName, contingencyLimitViolationEntity.getNextLimitName()); + assertEquals(expectedPatlLimit, contingencyLimitViolationEntity.getPatlLimit()); assertEquals(100 * limitViolation.getValue() / contingencyLimitViolationEntity.getPatlLimit(), contingencyLimitViolationEntity.getPatlLoading()); } } From 78197047ec8542f9ece9d40c8d1983238cfb385f Mon Sep 17 00:00:00 2001 From: LE SAULNIER Kevin Date: Fri, 5 Sep 2025 15:04:29 +0200 Subject: [PATCH 7/7] fix: PR remarks Signed-off-by: LE SAULNIER Kevin --- .../server/entities/AbstractLimitViolationEntity.java | 10 ++++++---- .../server/ContingencyLimitViolationTest.java | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/gridsuite/securityanalysis/server/entities/AbstractLimitViolationEntity.java b/src/main/java/org/gridsuite/securityanalysis/server/entities/AbstractLimitViolationEntity.java index a055b884..e3263195 100644 --- a/src/main/java/org/gridsuite/securityanalysis/server/entities/AbstractLimitViolationEntity.java +++ b/src/main/java/org/gridsuite/securityanalysis/server/entities/AbstractLimitViolationEntity.java @@ -17,6 +17,7 @@ import lombok.experimental.FieldNameConstants; import lombok.experimental.SuperBuilder; +import java.util.Collection; import java.util.Iterator; import java.util.Optional; import java.util.UUID; @@ -84,7 +85,7 @@ protected static Double getPatlLimit(LimitViolation limitViolation, Network netw return null; } - Optional currentLimits = limitViolationSide.name().equals(TwoSides.ONE.name()) ? branch.getCurrentLimits1() : branch.getCurrentLimits2(); + Optional currentLimits = branch.getCurrentLimits(limitViolationSide.toTwoSides()); if (currentLimits.isPresent()) { return currentLimits.get().getPermanentLimit(); } @@ -109,16 +110,17 @@ private static LoadingLimits.TemporaryLimit getNextTemporaryLimit(Branch bran return null; } - Optional currentLimits = limitViolationSide.name().equals(TwoSides.ONE.name()) ? branch.getCurrentLimits1() : branch.getCurrentLimits2(); + Optional currentLimits = branch.getCurrentLimits(limitViolationSide.toTwoSides()); if (currentLimits.isEmpty()) { return null; } + Collection temporaryLimits = currentLimits.get().getTemporaryLimits(); if (limitName.equals(LimitViolationUtils.PERMANENT_LIMIT_NAME)) { - return currentLimits.get().getTemporaryLimits().stream().findFirst().orElse(null); + return temporaryLimits.stream().findFirst().orElse(null); } - Iterator temporaryLimitIterator = currentLimits.get().getTemporaryLimits().iterator(); + Iterator temporaryLimitIterator = temporaryLimits.iterator(); while (temporaryLimitIterator.hasNext()) { LoadingLimits.TemporaryLimit currentTemporaryLimit = temporaryLimitIterator.next(); if (currentTemporaryLimit.getName().equals(limitViolation.getLimitName())) { diff --git a/src/test/java/org/gridsuite/securityanalysis/server/ContingencyLimitViolationTest.java b/src/test/java/org/gridsuite/securityanalysis/server/ContingencyLimitViolationTest.java index 4127cec5..3a78c3d9 100644 --- a/src/test/java/org/gridsuite/securityanalysis/server/ContingencyLimitViolationTest.java +++ b/src/test/java/org/gridsuite/securityanalysis/server/ContingencyLimitViolationTest.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2023, RTE (http://www.rte-france.com) + * Copyright (c) 2025, RTE (http://www.rte-france.com) * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/.