Skip to content

Commit

Permalink
Sub-networks implementation
Browse files Browse the repository at this point in the history
Signed-off-by: Geoffroy Jamgotchian <geoffroy.jamgotchian@gmail.com>
  • Loading branch information
geofjamg committed Oct 12, 2023
1 parent fb22913 commit 9ce27f2
Show file tree
Hide file tree
Showing 12 changed files with 95 additions and 4 deletions.
7 changes: 6 additions & 1 deletion cpp/src/bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,10 @@ PYBIND11_MODULE(_pypowsybl, m) {

m.def("merge", &pypowsybl::merge, "Merge several networks");

m.def("get_sub_network", &pypowsybl::getSubNetwork, "Get a sub network from its ID", py::arg("network"), py::arg("sub_network_id"));

m.def("detach_sub_network", &pypowsybl::detachSubNetwork, "Detach a sub network from its parent", py::arg("sub_network"));

m.def("update_connectable_status", &pypowsybl::updateConnectableStatus, "Update a connectable (branch or injection) status");

py::enum_<element_type>(m, "ElementType")
Expand Down Expand Up @@ -260,7 +264,8 @@ PYBIND11_MODULE(_pypowsybl, m) {
.value("IDENTIFIABLE", element_type::IDENTIFIABLE)
.value("INJECTION", element_type::INJECTION)
.value("BRANCH", element_type::BRANCH)
.value("TERMINAL", element_type::TERMINAL);
.value("TERMINAL", element_type::TERMINAL)
.value("SUB_NETWORK", element_type::SUB_NETWORK);

py::enum_<filter_attributes_type>(m, "FilterAttributesType")
.value("ALL_ATTRIBUTES", filter_attributes_type::ALL_ATTRIBUTES)
Expand Down
1 change: 1 addition & 0 deletions cpp/src/pypowsybl-api.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ typedef enum {
INJECTION,
BRANCH,
TERMINAL,
SUB_NETWORK
} element_type;

typedef enum {
Expand Down
8 changes: 8 additions & 0 deletions cpp/src/pypowsybl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,14 @@ JavaHandle merge(std::vector<JavaHandle>& networks) {
return callJava<JavaHandle>(::merge, networksData, networkCount);
}

JavaHandle getSubNetwork(const JavaHandle& network, const std::string& subNetworkId) {
return callJava<JavaHandle>(::getSubNetwork, network, (char*) subNetworkId.data());
}

JavaHandle detachSubNetwork(const JavaHandle& subNetwork) {
return callJava<JavaHandle>(::detachSubNetwork, subNetwork);
}

std::vector<std::string> getNetworkImportFormats() {
auto formatsArrayPtr = callJava<array*>(::getNetworkImportFormats);
ToStringVector formats(formatsArrayPtr);
Expand Down
4 changes: 4 additions & 0 deletions cpp/src/pypowsybl.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,10 @@ JavaHandle createNetwork(const std::string& name, const std::string& id);

JavaHandle merge(std::vector<JavaHandle>& others);

JavaHandle getSubNetwork(const JavaHandle& network, const std::string& subNetworkId);

JavaHandle detachSubNetwork(const JavaHandle& subNetwork);

bool updateSwitchPosition(const JavaHandle& network, const std::string& id, bool open);

bool updateConnectableStatus(const JavaHandle& network, const std::string& id, bool connected);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,6 @@ public enum DataframeElementType {
IDENTIFIABLE,
INJECTION,
BRANCH,
TERMINAL
TERMINAL,
SUB_NETWORK
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public static NetworkDataframeMapper getDataframeMapper(DataframeElementType typ

private static Map<DataframeElementType, NetworkDataframeMapper> createMappers() {
Map<DataframeElementType, NetworkDataframeMapper> mappers = new EnumMap<>(DataframeElementType.class);
mappers.put(DataframeElementType.SUB_NETWORK, subNetworks());
mappers.put(DataframeElementType.BUS, buses());
mappers.put(DataframeElementType.LINE, lines());
mappers.put(DataframeElementType.TWO_WINDINGS_TRANSFORMER, twoWindingTransformers());
Expand Down Expand Up @@ -316,6 +317,13 @@ private static void setRegulatedElement(Injection injection, String elementId) {
}
}

private static NetworkDataframeMapper subNetworks() {
return NetworkDataframeMapperBuilder.ofStream(n -> n.getSubnetworks().stream(),
getOrThrow(Network::getSubnetwork, "SubNetwork"))
.stringsIndex("id", Identifiable::getId)
.build();
}

static NetworkDataframeMapper buses() {
return NetworkDataframeMapperBuilder.ofStream(n -> n.getBusView().getBusStream(),
getOrThrow((b, id) -> b.getBusView().getBus(id), "Bus"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,8 @@ public enum ElementType {
IDENTIFIABLE,
INJECTION,
BRANCH,
TERMINAL;
TERMINAL,
SUB_NETWORK;

@CEnumValue
public native int getCValue();
Expand Down
2 changes: 2 additions & 0 deletions java/src/main/java/com/powsybl/python/commons/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,8 @@ public static DataframeElementType convert(PyPowsyblApiHeader.ElementType type)
return DataframeElementType.BRANCH;
case IDENTIFIABLE:
return DataframeElementType.IDENTIFIABLE;
case SUB_NETWORK:
return DataframeElementType.SUB_NETWORK;
default:
throw new PowsyblException("Unknown element type : " + type);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1021,4 +1021,26 @@ public static DataframesMetadataPointer getModificationMetadataWithElementType(I
return res;
});
}

@CEntryPoint(name = "getSubNetwork")
public static ObjectHandle getSubNetwork(IsolateThread thread, ObjectHandle networkHandle, CCharPointer subNetworkId, ExceptionHandlerPointer exceptionHandlerPtr) {
return doCatch(exceptionHandlerPtr, () -> {
Network network = ObjectHandles.getGlobal().get(networkHandle);
String subNetworkIdStr = CTypeUtil.toString(subNetworkId);
Network subnetwork = network.getSubnetwork(subNetworkIdStr);
if (subnetwork == null) {
throw new PowsyblException("Sub network '" + subNetworkIdStr + "' not found");
}
return ObjectHandles.getGlobal().create(subnetwork);
});
}

@CEntryPoint(name = "detachSubNetwork")
public static ObjectHandle detachSubNetwork(IsolateThread thread, ObjectHandle subNetworkHandle, ExceptionHandlerPointer exceptionHandlerPtr) {
return doCatch(exceptionHandlerPtr, () -> {
Network subNetwork = ObjectHandles.getGlobal().get(subNetworkHandle);
Network detachNetwork = subNetwork.detach();
return ObjectHandles.getGlobal().create(detachNetwork);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -618,4 +618,14 @@ void testTerminals() {
.extracting(Series::getName)
.containsExactly("element_id", "voltage_level_id", "bus_id", "element_side", "connected");
}

@Test
void testSubNetworks() {
Network network = EurostagTutorialExample1Factory.create();
List<Series> series = createDataFrame(SUB_NETWORK, network);

assertThat(series)
.extracting(Series::getName)
.containsExactly("id");
}
}
10 changes: 10 additions & 0 deletions pypowsybl/network/impl/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,16 @@ def get_elements(self, element_type: ElementType, all_attributes: bool = False,
result = result[attributes]
return result

def get_sub_networks(self, all_attributes: bool = False, attributes: List[str] = None,
**kwargs: ArrayLike) -> DataFrame:
return self.get_elements(ElementType.SUB_NETWORK, all_attributes, attributes, **kwargs)

def get_sub_network(self, sub_network_id: str) -> Network:
return Network(_pp.get_sub_network(self._handle, sub_network_id))

def detach(self) -> None:
self._handle = _pp.detach_sub_network(self._handle)

def get_buses(self, all_attributes: bool = False, attributes: List[str] = None,
**kwargs: ArrayLike) -> DataFrame:
r"""
Expand Down
21 changes: 20 additions & 1 deletion tests/test_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -1205,7 +1205,26 @@ def test_network_merge():
nl = pp.network.create_micro_grid_nl_network()
assert 4 == len(nl.get_voltage_levels())
be.merge(nl)
assert 10 == len(be.get_voltage_levels())
merge = be
assert 10 == len(merge.get_voltage_levels())
sub_networks = merge.get_sub_networks()
expected_sub_networks = pd.DataFrame(index=pd.Series(name='id',
data=['urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73', 'urn:uuid:77b55f87-fc1e-4046-9599-6c6b4f991a86']))
pd.testing.assert_frame_equal(expected_sub_networks, sub_networks, check_dtype=False)
be_from_merge = merge.get_sub_network('urn:uuid:d400c631-75a0-4c30-8aed-832b0d282e73')
assert 6 == len(be_from_merge.get_voltage_levels())
nl_from_merge = merge.get_sub_network('urn:uuid:77b55f87-fc1e-4046-9599-6c6b4f991a86')
assert 4 == len(nl_from_merge.get_voltage_levels())
be_from_merge.detach()
assert 6 == len(be_from_merge.get_voltage_levels())
assert 4 == len(merge.get_voltage_levels()) # only remain NL in the merge
sub_networks = merge.get_sub_networks()
expected_sub_networks = pd.DataFrame(index=pd.Series(name='id',
data=['urn:uuid:77b55f87-fc1e-4046-9599-6c6b4f991a86']))
pd.testing.assert_frame_equal(expected_sub_networks, sub_networks, check_dtype=False)
nl_from_merge.detach()
assert 4 == len(nl_from_merge.get_voltage_levels())
assert 0 == len(merge.get_voltage_levels()) # merge is empty


def test_linear_shunt_compensator_sections():
Expand Down

0 comments on commit 9ce27f2

Please sign in to comment.