Skip to content

Commit

Permalink
Add computation utility class (#84)
Browse files Browse the repository at this point in the history
Signed-off-by: jamal-khey <[email protected]>
  • Loading branch information
jamal-khey authored Dec 5, 2024
1 parent 94d02b5 commit f527047
Show file tree
Hide file tree
Showing 3 changed files with 264 additions and 0 deletions.
6 changes: 6 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@
<version>${powsybl-network-store-client.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.powsybl</groupId>
<artifactId>powsybl-security-analysis-api</artifactId>
<optional>true</optional>
</dependency>

<!-- APT libraries -->
<dependency>
Expand All @@ -146,6 +151,7 @@
<artifactId>slf4j-simple</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/**
* Copyright (c) 2024, 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 com.powsybl.ws.commons.computation.utils;

import com.powsybl.iidm.network.*;
import com.powsybl.security.BusBreakerViolationLocation;
import com.powsybl.security.LimitViolation;
import com.powsybl.security.NodeBreakerViolationLocation;
import com.powsybl.security.ViolationLocation;

import java.util.*;
import java.util.stream.Collectors;

import static com.powsybl.iidm.network.IdentifiableType.BUSBAR_SECTION;
import static com.powsybl.security.ViolationLocation.Type.NODE_BREAKER;

/**
* @author Jamal KHEYYAD <jamal.kheyyad at rte-international.com>
*/
public final class ComputationResultUtils {

private ComputationResultUtils() {
}

public static String getViolationLocationId(LimitViolation limitViolation, Network network) {
Optional<ViolationLocation> violationLocation = limitViolation.getViolationLocation();
if (violationLocation.isEmpty()) {
return limitViolation.getSubjectId();
}

ViolationLocation location = violationLocation.get();
if (location.getType() == NODE_BREAKER) {
return getNodeBreakerViolationLocationId((NodeBreakerViolationLocation) location, network);
} else {
return getBusBreakerViolationLocationId((BusBreakerViolationLocation) location, network, limitViolation.getSubjectId());
}
}

private static String getNodeBreakerViolationLocationId(NodeBreakerViolationLocation nodeBreakerViolationLocation, Network network) {
VoltageLevel vl = network.getVoltageLevel(nodeBreakerViolationLocation.getVoltageLevelId());

List<String> busBarIds = nodeBreakerViolationLocation.getNodes().stream()
.map(node -> vl.getNodeBreakerView().getTerminal(node))
.filter(Objects::nonNull)
.map(Terminal::getConnectable)
.filter(t -> t.getType() == BUSBAR_SECTION)
.map(Identifiable::getId)
.distinct()
.toList();

String busId = null;
if (!busBarIds.isEmpty()) {
busId = getBusId(vl, new HashSet<>(busBarIds));
}
return formatViolationLocationId(busId != null ? List.of() : busBarIds, busId != null ? busId : nodeBreakerViolationLocation.getVoltageLevelId());
}

private static String getBusId(VoltageLevel voltageLevel, Set<String> sjbIds) {
Optional<Bus> bus = voltageLevel.getBusView()
.getBusStream()
.filter(b -> {
Set<String> busSjbIds = b.getConnectedTerminalStream().map(Terminal::getConnectable).filter(c -> c.getType() == BUSBAR_SECTION).map(Connectable::getId).collect(Collectors.toSet());
return busSjbIds.equals(sjbIds);
})
.findFirst();
return bus.map(Identifiable::getId).orElse(null);
}

private static String formatViolationLocationId(List<String> elementsIds, String subjectId) {
return !elementsIds.isEmpty() ?
subjectId + " (" + String.join(", ", elementsIds) + ")" :
subjectId;
}

private static String getBusBreakerViolationLocationId(BusBreakerViolationLocation busBreakerViolationLocation, Network network, String subjectId) {
List<String> busBreakerIds = busBreakerViolationLocation
.getBusView(network)
.getBusStream()
.map(Identifiable::getId)
.distinct()
.toList();

return busBreakerIds.size() == 1 ? formatViolationLocationId(List.of(), busBreakerIds.get(0)) : formatViolationLocationId(busBreakerIds, subjectId);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
/**
* Copyright (c) 2024, 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 com.powsybl.ws.commons.computation;

import com.powsybl.iidm.network.*;
import com.powsybl.network.store.iidm.impl.NetworkFactoryImpl;
import com.powsybl.security.BusBreakerViolationLocation;
import com.powsybl.security.LimitViolation;
import com.powsybl.security.NodeBreakerViolationLocation;
import com.powsybl.security.ViolationLocation;
import com.powsybl.ws.commons.computation.utils.ComputationResultUtils;
import org.junit.jupiter.api.Test;

import java.util.List;
import java.util.Optional;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

/**
* @author Jamal KHEYYAD <jamal.kheyyad at rte-international.com>
*/
class ComputationUtilTest {

static Network createBusBreakerNetwork() {
Network network = new NetworkFactoryImpl().createNetwork("network", "test");
Substation p1 = network.newSubstation()
.setId("P1")
.setCountry(Country.FR)
.setTso("RTE")
.setGeographicalTags("A")
.add();
VoltageLevel vl = p1.newVoltageLevel()
.setId("VLGEN")
.setNominalV(24.0)
.setTopologyKind(TopologyKind.BUS_BREAKER)
.add();

Bus ngen = vl.getBusBreakerView().newBus()
.setId("NGEN")
.add();

Bus ngen2 = vl.getBusBreakerView().newBus()
.setId("NGEN2")
.add();

vl.newLoad()
.setId("LD")
.setBus(ngen.getId())
.setConnectableBus(ngen.getId())
.setP0(600.0)
.setQ0(200.0)
.add();

vl.newLoad()
.setId("LD2")
.setBus(ngen2.getId())
.setConnectableBus(ngen2.getId())
.setP0(600.0)
.setQ0(200.0)
.add();

return network;
}

public static Network createNodeBreakerNetwork() {
Network network = Network.create("network", "test");
Substation s = network.newSubstation()
.setId("S")
.add();
VoltageLevel vl = s.newVoltageLevel()
.setId("VL1")
.setNominalV(400)
.setLowVoltageLimit(370.)
.setHighVoltageLimit(420.)
.setTopologyKind(TopologyKind.NODE_BREAKER)
.add();
vl.getNodeBreakerView().newBusbarSection()
.setId("BBS1")
.setNode(0)
.add();
vl.getNodeBreakerView().newBusbarSection()
.setId("BBS2")
.setNode(1)
.add();

vl.newLoad()
.setId("LD")
.setNode(3)
.setP0(600.0)
.setQ0(200.0)
.add();

vl.getNodeBreakerView().newBreaker()
.setId("BR")
.setOpen(false)
.setNode1(0)
.setNode2(3)
.add();

return network;
}

@Test
void testViolationLocationIdBusBreaker() {
Network network = createBusBreakerNetwork();

LimitViolation limitViolation = mock(LimitViolation.class);

when(limitViolation.getViolationLocation()).thenReturn(Optional.of(new BusBreakerViolationLocation(List.of("NGEN"))));
assertEquals("VLGEN_0", ComputationResultUtils.getViolationLocationId(limitViolation, network));

when(limitViolation.getViolationLocation()).thenReturn(Optional.of(new BusBreakerViolationLocation(List.of("NGEN2"))));
assertEquals("VLGEN_1", ComputationResultUtils.getViolationLocationId(limitViolation, network));

when(limitViolation.getViolationLocation()).thenReturn(Optional.of(new BusBreakerViolationLocation(List.of("NGEN", "NGEN2"))));
when(limitViolation.getSubjectId()).thenReturn("VLGEN");
assertEquals("VLGEN (VLGEN_0, VLGEN_1)", ComputationResultUtils.getViolationLocationId(limitViolation, network));

when(limitViolation.getViolationLocation()).thenReturn(Optional.of(new BusBreakerViolationLocation(List.of())));
when(limitViolation.getSubjectId()).thenReturn("VLGEN");
assertEquals("VLGEN", ComputationResultUtils.getViolationLocationId(limitViolation, network));
}

@Test
void testNoViolationLocationIdBusBreaker() {
Network network = createBusBreakerNetwork();
LimitViolation limitViolation = mock(LimitViolation.class);

when(limitViolation.getViolationLocation()).thenReturn(Optional.empty());
when(limitViolation.getSubjectId()).thenReturn("subjectId");
assertEquals("subjectId", ComputationResultUtils.getViolationLocationId(limitViolation, network));
}

@Test
void testViolationLocationIdNodeBreaker() {
Network network = createNodeBreakerNetwork();

NodeBreakerViolationLocation nodeBreakerViolationLocation = mock(NodeBreakerViolationLocation.class);
when(nodeBreakerViolationLocation.getType()).thenReturn(ViolationLocation.Type.NODE_BREAKER);
when(nodeBreakerViolationLocation.getVoltageLevelId()).thenReturn("VL1");
when(nodeBreakerViolationLocation.getNodes()).thenReturn(List.of());

LimitViolation limitViolation = mock(LimitViolation.class);
when(limitViolation.getViolationLocation()).thenReturn(Optional.of(nodeBreakerViolationLocation));
when(limitViolation.getSubjectId()).thenReturn("VLHV1");

String locationId = ComputationResultUtils.getViolationLocationId(limitViolation, network);
assertEquals("VL1", locationId);

when(nodeBreakerViolationLocation.getNodes()).thenReturn(List.of(0, 1));
locationId = ComputationResultUtils.getViolationLocationId(limitViolation, network);
assertEquals("VL1 (BBS1, BBS2)", locationId);

when(nodeBreakerViolationLocation.getNodes()).thenReturn(List.of(0));
locationId = ComputationResultUtils.getViolationLocationId(limitViolation, network);
assertEquals("VL1_0", locationId);

when(nodeBreakerViolationLocation.getNodes()).thenReturn(List.of(1));
locationId = ComputationResultUtils.getViolationLocationId(limitViolation, network);
assertEquals("VL1 (BBS2)", locationId);
}
}

0 comments on commit f527047

Please sign in to comment.