Skip to content

Commit 44a358f

Browse files
author
LE SAULNIER Kevin
committed
feat: add upcoming and current overload durations in result
Signed-off-by: LE SAULNIER Kevin <[email protected]>
1 parent 2e96af0 commit 44a358f

File tree

6 files changed

+98
-14
lines changed

6 files changed

+98
-14
lines changed

src/main/java/org/gridsuite/securityanalysis/server/dto/LimitViolationDTO.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ public class LimitViolationDTO {
2424
private String limitName;
2525
private String nextLimitName;
2626
private ThreeSides side;
27-
private int acceptableDuration;
27+
private Integer acceptableDuration;
28+
private Integer upcomingAcceptableDuration;
2829
private double limit;
2930
private Double patlLimit;
3031
private double limitReduction;
@@ -39,7 +40,8 @@ public static LimitViolationDTO toDto(AbstractLimitViolationEntity limitViolatio
3940
.limitName(limitViolation.getLimitName())
4041
.nextLimitName(limitViolation.getNextLimitName())
4142
.side(limitViolation.getSide())
42-
.acceptableDuration((int) limitViolation.getAcceptableDuration())
43+
.acceptableDuration(limitViolation.getAcceptableDuration())
44+
.upcomingAcceptableDuration(limitViolation.getUpcomingAcceptableDuration())
4345
.limit(limitViolation.getLimit())
4446
.patlLimit(limitViolation.getPatlLimit())
4547
.limitReduction(limitViolation.getLimitReduction())

src/main/java/org/gridsuite/securityanalysis/server/entities/AbstractLimitViolationEntity.java

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@
1717
import lombok.experimental.FieldNameConstants;
1818
import lombok.experimental.SuperBuilder;
1919

20-
import java.util.Collection;
21-
import java.util.Iterator;
22-
import java.util.Optional;
23-
import java.util.UUID;
20+
import java.util.*;
2421

2522
/**
2623
* @author Kevin Le Saulnier <kevin.lesaulnier at rte-france.com>
@@ -53,7 +50,9 @@ public abstract class AbstractLimitViolationEntity {
5350
@Enumerated(EnumType.STRING)
5451
private LimitViolationType limitType;
5552

56-
private long acceptableDuration;
53+
private Integer acceptableDuration;
54+
55+
private Integer upcomingAcceptableDuration;
5756

5857
private double limitReduction;
5958

@@ -130,4 +129,47 @@ private static LoadingLimits.TemporaryLimit getNextTemporaryLimit(Branch<?> bran
130129

131130
return null;
132131
}
132+
133+
protected static Integer calculateActualOverloadDuration(LimitViolation limitViolation, Network network) {
134+
if (limitViolation.getValue() > limitViolation.getLimit()) {
135+
return limitViolation.getAcceptableDuration();
136+
} else {
137+
String equipmentId = limitViolation.getSubjectId();
138+
LoadingLimits.TemporaryLimit tempLimit = null;
139+
140+
Line line = network.getLine(equipmentId);
141+
if (line != null) {
142+
tempLimit = getBranchLimitViolationAboveCurrentValue(line, limitViolation);
143+
} else {
144+
TwoWindingsTransformer twoWindingsTransformer = network.getTwoWindingsTransformer(equipmentId);
145+
if (twoWindingsTransformer != null) {
146+
tempLimit = getBranchLimitViolationAboveCurrentValue(twoWindingsTransformer, limitViolation);
147+
}
148+
}
149+
return (tempLimit != null) ? tempLimit.getAcceptableDuration() : Integer.MAX_VALUE;
150+
}
151+
}
152+
153+
protected static Integer calculateUpcomingOverloadDuration(LimitViolation limitViolation) {
154+
if (limitViolation.getValue() < limitViolation.getLimit()) {
155+
return limitViolation.getAcceptableDuration();
156+
}
157+
return null;
158+
}
159+
160+
private static LoadingLimits.TemporaryLimit getBranchLimitViolationAboveCurrentValue(Branch<?> branch, LimitViolation limitViolation) {
161+
// limits are returned from the store by DESC duration / ASC value
162+
Optional<CurrentLimits> currentLimits = limitViolation.getSideAsTwoSides().equals(TwoSides.ONE) ? branch.getCurrentLimits1() : branch.getCurrentLimits2();
163+
if (currentLimits.isEmpty() || limitViolation.getValue() < currentLimits.get().getPermanentLimit()) {
164+
return null;
165+
} else {
166+
Optional<LoadingLimits.TemporaryLimit> nextTemporaryLimit = currentLimits.get().getTemporaryLimits().stream()
167+
.filter(tl -> limitViolation.getValue() < tl.getValue())
168+
.findFirst();
169+
if (nextTemporaryLimit.isPresent()) {
170+
return nextTemporaryLimit.get();
171+
}
172+
}
173+
return null;
174+
}
133175
}

src/main/java/org/gridsuite/securityanalysis/server/entities/ContingencyLimitViolationEntity.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ public static ContingencyLimitViolationEntity toEntity(Network network, LimitVio
4646
.patlLimit(patlLimit)
4747
.patlLoading(computeLoading(limitViolation, patlLimit))
4848
.nextLimitName(getNextLimitName(limitViolation, network))
49-
.acceptableDuration(limitViolation.getAcceptableDuration())
49+
.acceptableDuration(calculateActualOverloadDuration(limitViolation, network))
50+
.upcomingAcceptableDuration(calculateUpcomingOverloadDuration(limitViolation))
5051
.build();
5152

5253
subjectLimitViolation.addContingencyLimitViolation(contingencyLimitViolationEntity);
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
2+
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:pro="http://www.liquibase.org/xml/ns/pro" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
3+
<changeSet author="lesaulnierkev (generated)" id="1757342382341-1">
4+
<addColumn tableName="contingency_limit_violation">
5+
<column name="upcoming_acceptable_duration" type="integer"/>
6+
</addColumn>
7+
</changeSet>
8+
<changeSet author="lesaulnierkev (generated)" id="1757342382341-2">
9+
<addColumn tableName="pre_contingency_limit_violation">
10+
<column name="upcoming_acceptable_duration" type="integer"/>
11+
</addColumn>
12+
</changeSet>
13+
<changeSet author="lesaulnierkev (generated)" id="1757342382341-3">
14+
<modifyDataType
15+
tableName="contingency_limit_violation"
16+
columnName="acceptable_duration"
17+
newDataType="INTEGER"/>
18+
</changeSet>
19+
<changeSet author="lesaulnierkev (generated)" id="1757342382341-4">
20+
<modifyDataType
21+
tableName="pre_contingency_limit_violation"
22+
columnName="acceptable_duration"
23+
newDataType="INTEGER"/>
24+
<!-- CHECK CONVERSION ?????-->
25+
</changeSet>
26+
27+
</databaseChangeLog>

src/main/resources/db/changelog/db.changelog-master.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,6 @@ databaseChangeLog:
4848
- include:
4949
file: changesets/changelog_20250903T125946Z.xml
5050
relativeToChangelogFile: true
51+
- include:
52+
file: changesets/changelog_20250908T143920Z.xml
53+
relativeToChangelogFile: true

src/test/java/org/gridsuite/securityanalysis/server/ContingencyLimitViolationTest.java

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,36 +25,45 @@
2525
@SpringBootTest
2626
class ContingencyLimitViolationTest {
2727

28+
2829
@Test
2930
void testContingencyLimitViolationEntityNewFields() {
30-
testContingencyLimitViolationMapping("10'", 10 * 60, 1200, 1250, TwoSides.TWO, "1'", 1100);
31+
testContingencyLimitViolationMapping("10'", 10 * 60, 1200, 1, 1250, TwoSides.TWO, "1'", 1100, 10 * 60, null);
3132
}
3233

3334
@Test
3435
void testContingencyLimitViolationEntityNewFieldsWithPermanentLimitReached() {
35-
testContingencyLimitViolationMapping(LimitViolationUtils.PERMANENT_LIMIT_NAME, Integer.MAX_VALUE, 1100, 1150, TwoSides.TWO, "10'", 1100);
36+
testContingencyLimitViolationMapping(LimitViolationUtils.PERMANENT_LIMIT_NAME, Integer.MAX_VALUE, 1100, 1, 1150, TwoSides.TWO, "10'", 1100, Integer.MAX_VALUE, null);
3637
}
3738

3839
@Test
3940
void testContingencyLimitViolationEntityNewFieldsWithPermanentLimitReachedAndNoTemporaryLimit() {
40-
testContingencyLimitViolationMapping(LimitViolationUtils.PERMANENT_LIMIT_NAME, Integer.MAX_VALUE, 500, 1000, TwoSides.ONE, null, 500);
41+
testContingencyLimitViolationMapping(LimitViolationUtils.PERMANENT_LIMIT_NAME, Integer.MAX_VALUE, 500, 1, 1000, TwoSides.ONE, null, 500, Integer.MAX_VALUE, null);
4142
}
4243

4344
@Test
4445
void testContingencyLimitViolationEntityNewFieldsWithLastLimitReached() {
45-
testContingencyLimitViolationMapping("N/A", 0, 1100, 3000, TwoSides.TWO, null, 1100);
46+
testContingencyLimitViolationMapping("N/A", 0, 1100, 1, 3000, TwoSides.TWO, null, 1100, 0, null);
47+
}
48+
49+
@Test
50+
void testContingencyLimitViolationEntityNewFieldsWithLimitReductionEffective() {
51+
// for this test to be relevant, "value" needs to be less that "limit"
52+
testContingencyLimitViolationMapping("10'", 60, 1200, 0.8, 1150, TwoSides.TWO, "1'", 1100, 10 * 60, 60);
4653
}
4754

48-
private void testContingencyLimitViolationMapping(String limitName, int acceptableDuration, double limit, double value, TwoSides side, String expectedNextLimitName, long expectedPatlLimit) {
55+
private void testContingencyLimitViolationMapping(String limitName, int acceptableDuration, double limit, double limitReduction, double value, TwoSides side, String expectedNextLimitName, long expectedPatlLimit, Integer expectedAcceptableDuration, Integer expectedUpcomingAcceptableDuration) {
4956
Network network = EurostagTutorialExample1Factory.createWithFixedCurrentLimits();
50-
LimitViolation limitViolation = new LimitViolation("NHV1_NHV2_1", "NHV1_NHV2_1_name", LimitViolationType.CURRENT, limitName, acceptableDuration, limit, 1, value, side);
57+
LimitViolation limitViolation = new LimitViolation("NHV1_NHV2_1", "NHV1_NHV2_1_name", LimitViolationType.CURRENT, limitName, acceptableDuration, limit, limitReduction, value, side);
5158

5259
SubjectLimitViolationEntity subjectLimitViolationEntity = new SubjectLimitViolationEntity("NHV1_NHV2_1", "NHV1_NHV2_1_name");
5360

5461
ContingencyLimitViolationEntity contingencyLimitViolationEntity = ContingencyLimitViolationEntity.toEntity(network, limitViolation, subjectLimitViolationEntity);
5562

5663
assertEquals(expectedNextLimitName, contingencyLimitViolationEntity.getNextLimitName());
5764
assertEquals(expectedPatlLimit, contingencyLimitViolationEntity.getPatlLimit());
65+
assertEquals(expectedAcceptableDuration, contingencyLimitViolationEntity.getAcceptableDuration());
66+
assertEquals(expectedUpcomingAcceptableDuration, contingencyLimitViolationEntity.getUpcomingAcceptableDuration());
5867
assertEquals(100 * limitViolation.getValue() / contingencyLimitViolationEntity.getPatlLimit(), contingencyLimitViolationEntity.getPatlLoading());
5968
}
6069
}

0 commit comments

Comments
 (0)