From 999ea918b2879c91f394e8a5a25ecd5a8f6b518c Mon Sep 17 00:00:00 2001 From: souissimai <133104748+souissimai@users.noreply.github.com> Date: Tue, 21 Nov 2023 11:14:32 +0100 Subject: [PATCH] Add actual and upcoming overload : limitViolationInfos (#74) * add actual and upcoming overload duration : limitViolationInfos --------- Signed-off-by: Maissa SOUISSI --- .../server/dto/LimitViolationInfos.java | 9 ++- .../entities/LimitViolationEmbeddable.java | 6 +- .../server/service/LoadFlowWorkerService.java | 64 +++++++++++++++++-- .../changesets/changelog_20231115T10528Z.xml | 14 ++++ .../db/changelog/db.changelog-master.yaml | 3 + .../server/LoadFlowControllerTest.java | 19 +++--- 6 files changed, 98 insertions(+), 17 deletions(-) create mode 100644 src/main/resources/db/changelog/changesets/changelog_20231115T10528Z.xml diff --git a/src/main/java/org/gridsuite/loadflow/server/dto/LimitViolationInfos.java b/src/main/java/org/gridsuite/loadflow/server/dto/LimitViolationInfos.java index 8fedc311..a75baea9 100644 --- a/src/main/java/org/gridsuite/loadflow/server/dto/LimitViolationInfos.java +++ b/src/main/java/org/gridsuite/loadflow/server/dto/LimitViolationInfos.java @@ -29,7 +29,9 @@ public class LimitViolationInfos { private String limitName; - private Integer acceptableDuration; + private Integer actualOverloadDuration; + + private Integer upComingOverloadDuration; private Double value; @@ -38,7 +40,7 @@ public class LimitViolationInfos { private LimitViolationType limitType; public LimitViolationEmbeddable toEmbeddable() { - return new LimitViolationEmbeddable(subjectId, limit, limitName, acceptableDuration, value, side, limitType); + return new LimitViolationEmbeddable(subjectId, limit, limitName, actualOverloadDuration, upComingOverloadDuration, value, side, limitType); } public static LimitViolationInfos toLimitViolationInfos(LimitViolationEmbeddable limitViolationEmbeddable) { @@ -46,7 +48,8 @@ public static LimitViolationInfos toLimitViolationInfos(LimitViolationEmbeddable .subjectId(limitViolationEmbeddable.getSubjectId()) .limit(limitViolationEmbeddable.getLimit()) .limitName(limitViolationEmbeddable.getLimitName()) - .acceptableDuration(limitViolationEmbeddable.getAcceptableDuration()) + .actualOverloadDuration(limitViolationEmbeddable.getActualOverload()) + .upComingOverloadDuration(limitViolationEmbeddable.getUpComingOverload()) .value(limitViolationEmbeddable.getValue()) .side(limitViolationEmbeddable.getSide()) .limitType(limitViolationEmbeddable.getLimitType()) diff --git a/src/main/java/org/gridsuite/loadflow/server/entities/LimitViolationEmbeddable.java b/src/main/java/org/gridsuite/loadflow/server/entities/LimitViolationEmbeddable.java index f7eee36d..9b2973c0 100644 --- a/src/main/java/org/gridsuite/loadflow/server/entities/LimitViolationEmbeddable.java +++ b/src/main/java/org/gridsuite/loadflow/server/entities/LimitViolationEmbeddable.java @@ -34,7 +34,10 @@ public class LimitViolationEmbeddable { private String limitName; @Column - private Integer acceptableDuration; + private Integer actualOverload; + + @Column + private Integer upComingOverload; @Column(name = "value_") private Double value; @@ -45,4 +48,5 @@ public class LimitViolationEmbeddable { @Column @Enumerated(EnumType.STRING) private LimitViolationType limitType; + } diff --git a/src/main/java/org/gridsuite/loadflow/server/service/LoadFlowWorkerService.java b/src/main/java/org/gridsuite/loadflow/server/service/LoadFlowWorkerService.java index 333f81b8..0714c35e 100644 --- a/src/main/java/org/gridsuite/loadflow/server/service/LoadFlowWorkerService.java +++ b/src/main/java/org/gridsuite/loadflow/server/service/LoadFlowWorkerService.java @@ -12,14 +12,14 @@ import com.powsybl.commons.reporter.Reporter; import com.powsybl.commons.reporter.ReporterModel; import com.powsybl.computation.local.LocalComputationManager; -import com.powsybl.iidm.network.Network; -import com.powsybl.iidm.network.VariantManagerConstants; +import com.powsybl.iidm.network.*; import com.powsybl.loadflow.LoadFlow; import com.powsybl.loadflow.LoadFlowParameters; import com.powsybl.loadflow.LoadFlowResult; import com.powsybl.network.store.client.NetworkStoreService; import com.powsybl.network.store.client.PreloadingStrategy; import com.powsybl.security.LimitViolation; +import com.powsybl.security.LimitViolationType; import com.powsybl.security.Security; import org.apache.commons.lang3.StringUtils; import org.gridsuite.loadflow.server.dto.LimitViolationInfos; @@ -50,7 +50,6 @@ public class LoadFlowWorkerService { private static final Logger LOGGER = LoggerFactory.getLogger(LoadFlowWorkerService.class); private static final String LOAD_FLOW_TYPE_REPORT = "LoadFlow"; - private Lock lockRunAndCancelLF = new ReentrantLock(); private ObjectMapper objectMapper; @@ -143,6 +142,59 @@ private void cleanLoadFlowResultsAndPublishCancel(UUID resultUuid, String receiv notificationService.publishStop(resultUuid, receiver); } + private static LoadingLimits.TemporaryLimit getBranchLimitViolationAboveCurrentValue(Branch branch, LimitViolationInfos violationInfo) { + // limits are returned from the store by DESC duration / ASC value + Optional currentLimits = violationInfo.getSide().equals(Branch.Side.ONE.name()) ? branch.getCurrentLimits1() : branch.getCurrentLimits2(); + if (!currentLimits.isPresent() || violationInfo.getValue() < currentLimits.get().getPermanentLimit()) { + return null; + } else { + Optional nextTemporaryLimit = currentLimits.get().getTemporaryLimits().stream() + .filter(tl -> violationInfo.getValue() < tl.getValue()) + .findFirst(); + if (nextTemporaryLimit.isPresent()) { + return nextTemporaryLimit.get(); + } + } + return null; + } + + public static Integer calculateUpcomingOverloadDuration(LimitViolationInfos limitViolationInfo) { + if (limitViolationInfo.getValue() < limitViolationInfo.getLimit()) { + return limitViolationInfo.getUpComingOverloadDuration(); + } + return null; + } + + public static Integer calculateActualOverloadDuration(LimitViolationInfos limitViolationInfo, Network network) { + if (limitViolationInfo.getValue() > limitViolationInfo.getLimit()) { + return limitViolationInfo.getActualOverloadDuration(); + } else { + String equipmentId = limitViolationInfo.getSubjectId(); + LoadingLimits.TemporaryLimit tempLimit = null; + + Line line = network.getLine(equipmentId); + if (line != null) { + tempLimit = getBranchLimitViolationAboveCurrentValue(line, limitViolationInfo); + } else { + TwoWindingsTransformer twoWindingsTransformer = network.getTwoWindingsTransformer(equipmentId); + if (twoWindingsTransformer != null) { + tempLimit = getBranchLimitViolationAboveCurrentValue(twoWindingsTransformer, limitViolationInfo); + } + } + return (tempLimit != null) ? tempLimit.getAcceptableDuration() : null; + } + } + + private List calculateOverloadLimitViolations(List limitViolationInfos, Network network) { + for (LimitViolationInfos violationInfo : limitViolationInfos) { + if (violationInfo.getLimitName() != null && violationInfo.getLimitType() == LimitViolationType.CURRENT) { + violationInfo.setActualOverloadDuration(calculateActualOverloadDuration(violationInfo, network)); + violationInfo.setUpComingOverloadDuration(calculateUpcomingOverloadDuration(violationInfo)); + } + } + return limitViolationInfos; + } + private void cancelLoadFlowAsync(LoadFlowCancelContext cancelContext) { lockRunAndCancelLF.lock(); try { @@ -162,7 +214,8 @@ private void cancelLoadFlowAsync(LoadFlowCancelContext cancelContext) { public static LimitViolationInfos toLimitViolationInfos(LimitViolation violation) { return LimitViolationInfos.builder() .subjectId(violation.getSubjectId()) - .acceptableDuration(violation.getAcceptableDuration()) + .actualOverloadDuration(violation.getAcceptableDuration()) + .upComingOverloadDuration(violation.getAcceptableDuration()) .limit(violation.getLimit()) .limitName(violation.getLimitName()) .value(violation.getValue()) @@ -198,7 +251,8 @@ public Consumer> consumeRun() { LOGGER.info("Just run in {}s", TimeUnit.NANOSECONDS.toSeconds(nanoTime - startTime.getAndSet(nanoTime))); List limitViolationInfos = getLimitViolations(network, resultContext.getRunContext()); - resultRepository.insert(resultContext.getResultUuid(), result, LoadFlowService.computeLoadFlowStatus(result), limitViolationInfos); + List limitViolationsWithCalculatedOverload = calculateOverloadLimitViolations(limitViolationInfos, network); + resultRepository.insert(resultContext.getResultUuid(), result, LoadFlowService.computeLoadFlowStatus(result), limitViolationsWithCalculatedOverload); long finalNanoTime = System.nanoTime(); LOGGER.info("Stored in {}s", TimeUnit.NANOSECONDS.toSeconds(finalNanoTime - startTime.getAndSet(finalNanoTime))); diff --git a/src/main/resources/db/changelog/changesets/changelog_20231115T10528Z.xml b/src/main/resources/db/changelog/changesets/changelog_20231115T10528Z.xml new file mode 100644 index 00000000..d5e8f206 --- /dev/null +++ b/src/main/resources/db/changelog/changesets/changelog_20231115T10528Z.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index ff66c631..2fab3fa4 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -6,3 +6,6 @@ databaseChangeLog: - include: file: changesets/changelog_20231003T105819Z.xml relativeToChangelogFile: true + - include: + file: changesets/changelog_20231115T10528Z.xml + relativeToChangelogFile: true diff --git a/src/test/java/org/gridsuite/loadflow/server/LoadFlowControllerTest.java b/src/test/java/org/gridsuite/loadflow/server/LoadFlowControllerTest.java index 16e55d21..6e044589 100644 --- a/src/test/java/org/gridsuite/loadflow/server/LoadFlowControllerTest.java +++ b/src/test/java/org/gridsuite/loadflow/server/LoadFlowControllerTest.java @@ -30,6 +30,7 @@ import org.gridsuite.loadflow.server.dto.LimitViolationInfos; import org.gridsuite.loadflow.server.dto.LoadFlowParametersInfos; import org.gridsuite.loadflow.server.dto.LoadFlowStatus; +import org.gridsuite.loadflow.server.service.LoadFlowWorkerService; import org.gridsuite.loadflow.server.service.NotificationService; import org.gridsuite.loadflow.server.service.ReportService; import org.gridsuite.loadflow.server.service.UuidGeneratorService; @@ -100,9 +101,11 @@ private static final class LoadFlowResultMock { } private static final class LimitViolationsMock { - static List limitViolations = List.of(new LimitViolation("lineId1", "lineName1", LimitViolationType.CURRENT, "limit1", 60, 200, 0.7F, 150, Branch.Side.ONE), - new LimitViolation("lineId2", "lineName2", LimitViolationType.CURRENT, "limit2", 300, 100, 0.7F, 80, Branch.Side.TWO), - new LimitViolation("genId1", "genName1", LimitViolationType.HIGH_VOLTAGE, "limit3", 120, 500, 0.7F, 370, null)); + static List limitViolations = List.of( + new LimitViolation("NHV1_NHV2_1", "lineName1", LimitViolationType.CURRENT, "limit1", 60, 1500, 0.7F, 1300, Branch.Side.TWO), + new LimitViolation("NHV1_NHV2_1", "lineName1", LimitViolationType.CURRENT, "limit1", 60, 1500, 0.7F, 1000, Branch.Side.TWO), + new LimitViolation("NHV1_NHV2_2", "lineName2", LimitViolationType.CURRENT, "limit2", 300, 900, 0.7F, 1000, Branch.Side.ONE), + new LimitViolation("NHV1_NHV2_2", "lineName2", LimitViolationType.CURRENT, "limit2", 300, 900, 0.7F, 1000, Branch.Side.TWO)); } @Autowired @@ -141,21 +144,21 @@ private static void assertResultsEquals(LoadFlowResult result, org.gridsuite.loa assertEquals(componentResultsDto.get(i).getSlackBusId(), componentResults.get(i).getSlackBusId()); assertEquals(componentResultsDto.get(i).getSlackBusActivePowerMismatch(), componentResults.get(i).getSlackBusActivePowerMismatch(), 0.01); assertEquals(componentResultsDto.get(i).getDistributedActivePower(), componentResults.get(i).getDistributedActivePower(), 0.01); - } } - private static void assertLimitViolationsEquals(List limitViolations, List limitViolationsDto) { + private static void assertLimitViolationsEquals(List limitViolations, List limitViolationsDto, Network network) { assertEquals(limitViolations.size(), limitViolationsDto.size()); for (int i = 0; i < limitViolationsDto.size(); i++) { assertEquals(limitViolationsDto.get(i).getSubjectId(), limitViolations.get(i).getSubjectId()); assertEquals(limitViolationsDto.get(i).getLimit(), limitViolations.get(i).getLimit(), 0.01); assertEquals(limitViolationsDto.get(i).getLimitName(), limitViolations.get(i).getLimitName()); - assertEquals(Optional.ofNullable(limitViolationsDto.get(i).getAcceptableDuration()), Optional.ofNullable(limitViolations.get(i).getAcceptableDuration())); assertEquals(limitViolationsDto.get(i).getValue(), limitViolations.get(i).getValue(), 0.01); assertEquals(limitViolationsDto.get(i).getSide(), limitViolations.get(i).getSide() != null ? limitViolations.get(i).getSide().name() : ""); assertEquals(limitViolationsDto.get(i).getLimitType(), limitViolations.get(i).getLimitType()); + assertEquals(limitViolationsDto.get(i).getActualOverloadDuration(), LoadFlowWorkerService.calculateActualOverloadDuration(LoadFlowWorkerService.toLimitViolationInfos(limitViolations.get(i)), network)); + assertEquals(limitViolationsDto.get(i).getUpComingOverloadDuration(), LoadFlowWorkerService.calculateUpcomingOverloadDuration(LoadFlowWorkerService.toLimitViolationInfos(limitViolations.get(i)))); } } @@ -164,7 +167,7 @@ public void setUp() throws Exception { MockitoAnnotations.initMocks(this); // network store service mocking - network = EurostagTutorialExample1Factory.createWithMoreGenerators(new NetworkFactoryImpl()); + network = EurostagTutorialExample1Factory.createWithFixedCurrentLimits(new NetworkFactoryImpl()); network.getVariantManager().cloneVariant(VariantManagerConstants.INITIAL_VARIANT_ID, VARIANT_1_ID); network.getVariantManager().cloneVariant(VariantManagerConstants.INITIAL_VARIANT_ID, VARIANT_2_ID); network.getVariantManager().cloneVariant(VariantManagerConstants.INITIAL_VARIANT_ID, VARIANT_3_ID); @@ -286,7 +289,7 @@ public void testGetLimitViolations() throws Exception { .andExpect(content().contentType(MediaType.APPLICATION_JSON)) .andReturn(); List limitViolations = mapper.readValue(result.getResponse().getContentAsString(), new TypeReference>() { }); - assertLimitViolationsEquals(LimitViolationsMock.limitViolations, limitViolations); + assertLimitViolationsEquals(LimitViolationsMock.limitViolations, limitViolations, network); } }