Skip to content

Commit 4aaa3d5

Browse files
authored
add new fields to security analysis results (tab N) (#200)
for the tab N of security analysis results : * fix `equipment` field * add new fields : `patlLoading`, `patlLimit`, `upcomingAcceptableDuration`, `acceptableDuration`, `nextLimitName
1 parent 01ef152 commit 4aaa3d5

File tree

4 files changed

+153
-88
lines changed

4 files changed

+153
-88
lines changed

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,22 @@ public static List<PreContingencyLimitViolationEntity> toEntityList(Network netw
4343
}
4444

4545
public static PreContingencyLimitViolationEntity toEntity(Network network, LimitViolation limitViolation, SubjectLimitViolationEntity subjectLimitViolation) {
46+
Double patlLimit = getPatlLimit(limitViolation, network);
4647
return PreContingencyLimitViolationEntity.builder()
4748
.subjectLimitViolation(subjectLimitViolation)
4849
.limit(limitViolation.getLimit())
4950
.limitName(limitViolation.getLimitName())
5051
.limitType(limitViolation.getLimitType())
51-
.acceptableDuration(limitViolation.getAcceptableDuration())
52+
.acceptableDuration(calculateActualOverloadDuration(limitViolation, network))
53+
.upcomingAcceptableDuration(calculateUpcomingOverloadDuration(limitViolation))
5254
.limitReduction(limitViolation.getLimitReduction())
5355
.value(limitViolation.getValue())
5456
.side(limitViolation.getSide())
57+
.patlLimit(patlLimit)
5558
.loading(computeLoading(limitViolation, limitViolation.getLimit()))
59+
.patlLoading(computeLoading(limitViolation, patlLimit))
5660
.locationId(ComputationResultUtils.getViolationLocationId(limitViolation, network))
61+
.nextLimitName(getNextLimitName(limitViolation, network))
5762
.build();
5863
}
5964
}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
package org.gridsuite.securityanalysis.server;
8+
9+
import com.powsybl.iidm.network.Network;
10+
import com.powsybl.iidm.network.TwoSides;
11+
import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
12+
import com.powsybl.iidm.network.util.LimitViolationUtils;
13+
import com.powsybl.security.LimitViolation;
14+
import com.powsybl.security.LimitViolationType;
15+
import org.gridsuite.securityanalysis.server.entities.AbstractLimitViolationEntity;
16+
import org.gridsuite.securityanalysis.server.entities.SubjectLimitViolationEntity;
17+
import org.junit.jupiter.api.Test;
18+
19+
import static com.powsybl.iidm.network.test.EurostagTutorialExample1Factory.NGEN_NHV1;
20+
import static com.powsybl.iidm.network.test.EurostagTutorialExample1Factory.NHV1_NHV2_1;
21+
import static org.junit.jupiter.api.Assertions.assertEquals;
22+
23+
/**
24+
* @author Caroline Jeandat <caroline.jeandat at rte-france.com>
25+
*/
26+
abstract class AbstractLimitViolationTest<T extends AbstractLimitViolationEntity> {
27+
28+
@Test
29+
void testLimitViolationEntityNewFields() {
30+
testLimitViolationMapping("10'", 10 * 60, 1200, 1, 1250, TwoSides.TWO, "1'", 1100, 10 * 60, null);
31+
}
32+
33+
@Test
34+
void testLimitViolationEntityNewFieldsWithPermanentLimitReached() {
35+
testLimitViolationMapping(LimitViolationUtils.PERMANENT_LIMIT_NAME, Integer.MAX_VALUE, 1100, 1, 1150,
36+
TwoSides.TWO, "10'", 1100, Integer.MAX_VALUE, null);
37+
}
38+
39+
@Test
40+
void testLimitViolationEntityNewFieldsWithPermanentLimitReachedAndNoTemporaryLimit() {
41+
testLimitViolationMapping(LimitViolationUtils.PERMANENT_LIMIT_NAME, Integer.MAX_VALUE, 500, 1, 1000,
42+
TwoSides.ONE, null, 500, Integer.MAX_VALUE, null);
43+
}
44+
45+
@Test
46+
void testLimitViolationEntityNewFieldsWithLastLimitReached() {
47+
testLimitViolationMapping("N/A", 0, 1100, 1, 3000, TwoSides.TWO, null, 1100, 0, null);
48+
}
49+
50+
@Test
51+
void testLimitViolationEntityNewFieldsWithLimitReductionEffective() {
52+
// for this test to be relevant, "value" needs to be less that "limit"
53+
testLimitViolationMapping("10'", 60, 1200, 0.8, 1150, TwoSides.TWO, "1'", 1100, 10 * 60, 60);
54+
}
55+
56+
@Test
57+
void test2wtLimitViolationEntityNewFieldsWithLimitReductionEffective() {
58+
// for this test to be relevant, "value" needs to be less that "limit"
59+
Network network = EurostagTutorialExample1Factory.createWithFixedCurrentLimits();
60+
// create limit set for two windings transformer
61+
network.getTwoWindingsTransformer(NGEN_NHV1).getOrCreateSelectedOperationalLimitsGroup1().newCurrentLimits()
62+
.setPermanentLimit(100)
63+
.beginTemporaryLimit()
64+
.setName("10'")
65+
.setValue(200)
66+
.setAcceptableDuration(60 * 10)
67+
.endTemporaryLimit()
68+
.beginTemporaryLimit()
69+
.setName("1'")
70+
.setValue(300)
71+
.setAcceptableDuration(60)
72+
.endTemporaryLimit()
73+
.beginTemporaryLimit()
74+
.setName("N/A")
75+
.setValue(Double.MAX_VALUE)
76+
.setAcceptableDuration(0)
77+
.endTemporaryLimit()
78+
.add();
79+
80+
LimitViolation limitViolation = new LimitViolation(NGEN_NHV1, "NGEN_NHV1_name", LimitViolationType.CURRENT,
81+
"10'", 60, 200, 0.8, 180, TwoSides.ONE);
82+
83+
SubjectLimitViolationEntity subjectLimitViolationEntity = new SubjectLimitViolationEntity(NGEN_NHV1,
84+
"NGEN_NHV1_name");
85+
86+
AbstractLimitViolationEntity limitViolationEntity = createLimitViolationEntity(network, limitViolation,
87+
subjectLimitViolationEntity);
88+
89+
assertEquals("1'", limitViolationEntity.getNextLimitName());
90+
assertEquals(100, limitViolationEntity.getPatlLimit());
91+
assertEquals(60 * 10, limitViolationEntity.getAcceptableDuration());
92+
assertEquals(60, limitViolationEntity.getUpcomingAcceptableDuration());
93+
assertEquals(100 * limitViolation.getValue() / limitViolationEntity.getPatlLimit(),
94+
limitViolationEntity.getPatlLoading());
95+
}
96+
97+
private void testLimitViolationMapping(String limitName, int acceptableDuration, double limit,
98+
double limitReduction, double value, TwoSides side, String expectedNextLimitName, long expectedPatlLimit,
99+
Integer expectedAcceptableDuration, Integer expectedUpcomingAcceptableDuration) {
100+
Network network = EurostagTutorialExample1Factory.createWithFixedCurrentLimits();
101+
LimitViolation limitViolation = new LimitViolation(NHV1_NHV2_1, "NHV1_NHV2_1_name", LimitViolationType.CURRENT,
102+
limitName, acceptableDuration, limit, limitReduction, value, side);
103+
104+
SubjectLimitViolationEntity subjectLimitViolationEntity = new SubjectLimitViolationEntity(NHV1_NHV2_1,
105+
"NHV1_NHV2_1_name");
106+
107+
T limitViolationEntity = createLimitViolationEntity(network, limitViolation,
108+
subjectLimitViolationEntity);
109+
110+
assertEquals(expectedNextLimitName, limitViolationEntity.getNextLimitName());
111+
assertEquals(expectedPatlLimit, limitViolationEntity.getPatlLimit());
112+
assertEquals(expectedAcceptableDuration, limitViolationEntity.getAcceptableDuration());
113+
assertEquals(expectedUpcomingAcceptableDuration, limitViolationEntity.getUpcomingAcceptableDuration());
114+
assertEquals(100 * limitViolation.getValue() / limitViolationEntity.getPatlLimit(),
115+
limitViolationEntity.getPatlLoading());
116+
}
117+
118+
protected abstract T createLimitViolationEntity(Network network,
119+
LimitViolation limitViolation, SubjectLimitViolationEntity subjectLimitViolationEntity);
120+
}

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

Lines changed: 4 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -7,100 +7,17 @@
77
package org.gridsuite.securityanalysis.server;
88

99
import com.powsybl.iidm.network.Network;
10-
import com.powsybl.iidm.network.TwoSides;
11-
import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory;
12-
import com.powsybl.iidm.network.util.LimitViolationUtils;
1310
import com.powsybl.security.LimitViolation;
14-
import com.powsybl.security.LimitViolationType;
1511
import org.gridsuite.securityanalysis.server.entities.ContingencyLimitViolationEntity;
1612
import org.gridsuite.securityanalysis.server.entities.SubjectLimitViolationEntity;
17-
import org.junit.jupiter.api.Test;
18-
import org.springframework.boot.test.context.SpringBootTest;
19-
20-
import static com.powsybl.iidm.network.test.EurostagTutorialExample1Factory.NGEN_NHV1;
21-
import static com.powsybl.iidm.network.test.EurostagTutorialExample1Factory.NHV1_NHV2_1;
22-
import static org.junit.jupiter.api.Assertions.assertEquals;
2313

2414
/**
2515
* @author Kevin Le Saulnier <kevin.lesaulnier at rte-france.com>
2616
*/
27-
@SpringBootTest
28-
class ContingencyLimitViolationTest {
29-
@Test
30-
void testContingencyLimitViolationEntityNewFields() {
31-
testContingencyLimitViolationMapping("10'", 10 * 60, 1200, 1, 1250, TwoSides.TWO, "1'", 1100, 10 * 60, null);
32-
}
33-
34-
@Test
35-
void testContingencyLimitViolationEntityNewFieldsWithPermanentLimitReached() {
36-
testContingencyLimitViolationMapping(LimitViolationUtils.PERMANENT_LIMIT_NAME, Integer.MAX_VALUE, 1100, 1, 1150, TwoSides.TWO, "10'", 1100, Integer.MAX_VALUE, null);
37-
}
38-
39-
@Test
40-
void testContingencyLimitViolationEntityNewFieldsWithPermanentLimitReachedAndNoTemporaryLimit() {
41-
testContingencyLimitViolationMapping(LimitViolationUtils.PERMANENT_LIMIT_NAME, Integer.MAX_VALUE, 500, 1, 1000, TwoSides.ONE, null, 500, Integer.MAX_VALUE, null);
42-
}
43-
44-
@Test
45-
void testContingencyLimitViolationEntityNewFieldsWithLastLimitReached() {
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);
53-
}
54-
55-
@Test
56-
void test2wtContingencyLimitViolationEntityNewFieldsWithLimitReductionEffective() {
57-
// for this test to be relevant, "value" needs to be less that "limit"
58-
Network network = EurostagTutorialExample1Factory.createWithFixedCurrentLimits();
59-
// create limit set for two windings transformer
60-
network.getTwoWindingsTransformer(NGEN_NHV1).getOrCreateSelectedOperationalLimitsGroup1().newCurrentLimits()
61-
.setPermanentLimit(100)
62-
.beginTemporaryLimit()
63-
.setName("10'")
64-
.setValue(200)
65-
.setAcceptableDuration(60 * 10)
66-
.endTemporaryLimit()
67-
.beginTemporaryLimit()
68-
.setName("1'")
69-
.setValue(300)
70-
.setAcceptableDuration(60)
71-
.endTemporaryLimit()
72-
.beginTemporaryLimit()
73-
.setName("N/A")
74-
.setValue(Double.MAX_VALUE)
75-
.setAcceptableDuration(0)
76-
.endTemporaryLimit()
77-
.add();
78-
79-
LimitViolation limitViolation = new LimitViolation(NGEN_NHV1, "NGEN_NHV1_name", LimitViolationType.CURRENT, "10'", 60, 200, 0.8, 180, TwoSides.ONE);
80-
81-
SubjectLimitViolationEntity subjectLimitViolationEntity = new SubjectLimitViolationEntity(NGEN_NHV1, "NGEN_NHV1_name");
82-
83-
ContingencyLimitViolationEntity contingencyLimitViolationEntity = ContingencyLimitViolationEntity.toEntity(network, limitViolation, subjectLimitViolationEntity);
84-
85-
assertEquals("1'", contingencyLimitViolationEntity.getNextLimitName());
86-
assertEquals(100, contingencyLimitViolationEntity.getPatlLimit());
87-
assertEquals(60 * 10, contingencyLimitViolationEntity.getAcceptableDuration());
88-
assertEquals(60, contingencyLimitViolationEntity.getUpcomingAcceptableDuration());
89-
assertEquals(100 * limitViolation.getValue() / contingencyLimitViolationEntity.getPatlLimit(), contingencyLimitViolationEntity.getPatlLoading());
90-
}
91-
92-
private void testContingencyLimitViolationMapping(String limitName, int acceptableDuration, double limit, double limitReduction, double value, TwoSides side, String expectedNextLimitName, long expectedPatlLimit, Integer expectedAcceptableDuration, Integer expectedUpcomingAcceptableDuration) {
93-
Network network = EurostagTutorialExample1Factory.createWithFixedCurrentLimits();
94-
LimitViolation limitViolation = new LimitViolation(NHV1_NHV2_1, "NHV1_NHV2_1_name", LimitViolationType.CURRENT, limitName, acceptableDuration, limit, limitReduction, value, side);
95-
96-
SubjectLimitViolationEntity subjectLimitViolationEntity = new SubjectLimitViolationEntity(NHV1_NHV2_1, "NHV1_NHV2_1_name");
97-
98-
ContingencyLimitViolationEntity contingencyLimitViolationEntity = ContingencyLimitViolationEntity.toEntity(network, limitViolation, subjectLimitViolationEntity);
17+
class ContingencyLimitViolationTest extends AbstractLimitViolationTest<ContingencyLimitViolationEntity> {
9918

100-
assertEquals(expectedNextLimitName, contingencyLimitViolationEntity.getNextLimitName());
101-
assertEquals(expectedPatlLimit, contingencyLimitViolationEntity.getPatlLimit());
102-
assertEquals(expectedAcceptableDuration, contingencyLimitViolationEntity.getAcceptableDuration());
103-
assertEquals(expectedUpcomingAcceptableDuration, contingencyLimitViolationEntity.getUpcomingAcceptableDuration());
104-
assertEquals(100 * limitViolation.getValue() / contingencyLimitViolationEntity.getPatlLimit(), contingencyLimitViolationEntity.getPatlLoading());
19+
@Override
20+
protected ContingencyLimitViolationEntity createLimitViolationEntity(Network network, LimitViolation limitViolation, SubjectLimitViolationEntity subjectLimitViolationEntity) {
21+
return ContingencyLimitViolationEntity.toEntity(network, limitViolation, subjectLimitViolationEntity);
10522
}
10623
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
package org.gridsuite.securityanalysis.server;
8+
9+
import com.powsybl.iidm.network.Network;
10+
import com.powsybl.security.LimitViolation;
11+
import org.gridsuite.securityanalysis.server.entities.PreContingencyLimitViolationEntity;
12+
import org.gridsuite.securityanalysis.server.entities.SubjectLimitViolationEntity;
13+
14+
/**
15+
* @author Caroline Jeandat <caroline.jeandat at rte-france.com>
16+
*/
17+
class PreContingencyLimitViolationTest extends AbstractLimitViolationTest<PreContingencyLimitViolationEntity> {
18+
19+
@Override
20+
protected PreContingencyLimitViolationEntity createLimitViolationEntity(Network network, LimitViolation limitViolation, SubjectLimitViolationEntity subjectLimitViolationEntity) {
21+
return PreContingencyLimitViolationEntity.toEntity(network, limitViolation, subjectLimitViolationEntity);
22+
}
23+
}

0 commit comments

Comments
 (0)