Skip to content

Commit

Permalink
Get switches and internal connections from given node (#391)
Browse files Browse the repository at this point in the history
Signed-off-by: Sébastien LAIGRE <[email protected]>
  • Loading branch information
sebalaig committed Jan 31, 2022
1 parent 388768a commit 460504f
Show file tree
Hide file tree
Showing 9 changed files with 228 additions and 2 deletions.
6 changes: 6 additions & 0 deletions include/powsybl/iidm/VoltageLevelViews.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ class NodeBreakerView {

virtual stdcxx::const_range<unsigned long> getNodes() const = 0;

virtual stdcxx::const_range<unsigned long> getNodesInternalConnectedTo(unsigned long node) const = 0;

virtual stdcxx::CReference<Terminal> getOptionalTerminal(unsigned long node) const = 0;

virtual stdcxx::Reference<Terminal> getOptionalTerminal(unsigned long node) = 0;
Expand All @@ -143,6 +145,10 @@ class NodeBreakerView {

virtual stdcxx::range<Switch> getSwitches() = 0;

virtual stdcxx::const_range<Switch> getSwitches(unsigned long node) const = 0;

virtual stdcxx::range<Switch> getSwitches(unsigned long node) = 0;

virtual stdcxx::CReference<Terminal> getTerminal(unsigned long node) const = 0;

virtual stdcxx::Reference<Terminal> getTerminal(unsigned long node) = 0;
Expand Down
10 changes: 10 additions & 0 deletions include/powsybl/math/UndirectedGraph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,22 @@ class UndirectedGraph {

const stdcxx::Reference<E>& getEdgeObject(unsigned long e) const;

const_range<E> getEdgeObjectsConnectedToVertex(unsigned long vertex) const;

const std::vector<unsigned long>& getEdgeConnectedToVertex(unsigned long vertex) const;

std::vector<unsigned long> getEdgesConnectedToVertex(unsigned long vertex) const;

const_range<E> getEdgeObjects() const;

range<E> getEdgeObjects();

const_range<E> getEdgeObjects(unsigned long v1, unsigned long v2) const;

unsigned long getEdgeVertex1(unsigned long edge) const;

unsigned long getEdgeVertex2(unsigned long edge) const;

const_range<unsigned long> getEdges() const;

unsigned long getMaxVertex() const;
Expand Down
32 changes: 32 additions & 0 deletions include/powsybl/math/UndirectedGraph.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,26 @@ const stdcxx::Reference<E>& UndirectedGraph<V, E>::getEdgeObject(unsigned long e
return m_edges[e]->getObject();
}

template <typename V, typename E>
typename UndirectedGraph<V, E>::template const_range<E> UndirectedGraph<V, E>::getEdgeObjectsConnectedToVertex(unsigned long vertex) const {
const auto& edgeMapper = [this](const unsigned long& e) {
return getEdgeObject(e);
};

return getEdgeConnectedToVertex(vertex) | boost::adaptors::transformed(edgeMapper);
}

template <typename V, typename E>
const std::vector<unsigned long>& UndirectedGraph<V, E>::getEdgeConnectedToVertex(unsigned long vertex) const {
checkVertex(vertex);
return getAdjacencyList()[vertex];
}

template <typename V, typename E>
std::vector<unsigned long> UndirectedGraph<V, E>::getEdgesConnectedToVertex(unsigned long vertex) const {
return getEdgeConnectedToVertex(vertex);
}

template <typename V, typename E>
typename UndirectedGraph<V, E>::template const_range<E> UndirectedGraph<V, E>::getEdgeObjects() const {
const auto& filter = [](const std::unique_ptr<Edge>& edge) {
Expand Down Expand Up @@ -255,6 +275,18 @@ typename UndirectedGraph<V, E>::template const_range<E> UndirectedGraph<V, E>::g
boost::adaptors::transformed(Edge::map);
}

template <typename V, typename E>
unsigned long UndirectedGraph<V, E>::getEdgeVertex1(unsigned long edge) const {
checkEdge(edge);
return m_edges[edge]->getVertex1();
}

template <typename V, typename E>
unsigned long UndirectedGraph<V, E>::getEdgeVertex2(unsigned long edge) const {
checkEdge(edge);
return m_edges[edge]->getVertex2();
}

template <typename V, typename E>
typename UndirectedGraph<V, E>::template const_range<unsigned long> UndirectedGraph<V, E>::getEdges() const {
const auto& filter = [this](const unsigned long e) {
Expand Down
1 change: 0 additions & 1 deletion src/iidm/BusBreakerVoltageLevel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ bool BusBreakerVoltageLevel::connect(Terminal& terminal) {
return true;
}


void BusBreakerVoltageLevel::deleteVariantArrayElement(unsigned long index) {
VoltageLevel::deleteVariantArrayElement(index);
m_variants.deleteVariantArrayElement(index);
Expand Down
1 change: 1 addition & 0 deletions src/iidm/BusBreakerVoltageLevel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <set>
#include <string>

#include <powsybl/PowsyblException.hpp>
#include <powsybl/iidm/VariantArray.hpp>
#include <powsybl/iidm/VoltageLevel.hpp>
#include <powsybl/math/UndirectedGraph.hpp>
Expand Down
37 changes: 37 additions & 0 deletions src/iidm/NodeBreakerVoltageLevelViews.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,19 @@ stdcxx::const_range<unsigned long> NodeBreakerViewImpl::getNodes() const {
return m_voltageLevel.getGraph().getVertices();
}

stdcxx::const_range<unsigned long> NodeBreakerViewImpl::getNodesInternalConnectedTo(unsigned long node) const {
const auto& isNull = [this](unsigned long edge) {
return !static_cast<bool>(m_voltageLevel.getGraph().getEdgeObject(edge));
};

const auto& mapper = [this, node](unsigned long edge) {
unsigned long vertex1 = m_voltageLevel.getGraph().getEdgeVertex1(edge);
return vertex1 != node ? vertex1 : m_voltageLevel.getGraph().getEdgeVertex2(edge);
};

return m_voltageLevel.getGraph().getEdgeConnectedToVertex(node) | boost::adaptors::filtered(isNull) | boost::adaptors::transformed(mapper);
}

stdcxx::CReference<Terminal> NodeBreakerViewImpl::getOptionalTerminal(unsigned long node) const {
if (m_voltageLevel.getGraph().vertexExists(node)) {
return stdcxx::cref<Terminal>(m_voltageLevel.getGraph().getVertexObject(node));
Expand Down Expand Up @@ -255,6 +268,30 @@ stdcxx::range<Switch> NodeBreakerViewImpl::getSwitches() {
return m_voltageLevel.getGraph().getEdgeObjects() | boost::adaptors::filtered(filter) | boost::adaptors::transformed(mapper);
}

stdcxx::const_range<Switch> NodeBreakerViewImpl::getSwitches(unsigned long node) const {
const auto& notNull = [](const stdcxx::Reference<Switch>& sw) {
return static_cast<bool>(sw);
};

const auto& deref = [](const stdcxx::Reference<Switch>& sw) -> const Switch& {
return sw.get();
};

return m_voltageLevel.getGraph().getEdgeObjectsConnectedToVertex(node) | boost::adaptors::filtered(notNull) | boost::adaptors::transformed(deref);
}

stdcxx::range<Switch> NodeBreakerViewImpl::getSwitches(unsigned long node) {
const auto& notNull = [](const stdcxx::Reference<Switch>& sw) {
return static_cast<bool>(sw);
};

const auto& deref = [](const stdcxx::Reference<Switch>& sw) -> const Switch& {
return sw.get();
};

return m_voltageLevel.getGraph().getEdgeObjectsConnectedToVertex(node) | boost::adaptors::filtered(notNull) | boost::adaptors::transformed(deref);
}

stdcxx::CReference<Terminal> NodeBreakerViewImpl::getTerminal(unsigned long node) const {
return stdcxx::cref(m_voltageLevel.getTerminal(node));
}
Expand Down
6 changes: 6 additions & 0 deletions src/iidm/NodeBreakerVoltageLevelViews.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ class NodeBreakerViewImpl : public voltage_level::NodeBreakerView {

stdcxx::const_range<unsigned long> getNodes() const override;

stdcxx::const_range<unsigned long> getNodesInternalConnectedTo(unsigned long node) const override;

stdcxx::CReference<Terminal> getOptionalTerminal(unsigned long node) const override;

stdcxx::Reference<Terminal> getOptionalTerminal(unsigned long node) override;
Expand All @@ -54,6 +56,10 @@ class NodeBreakerViewImpl : public voltage_level::NodeBreakerView {

stdcxx::range<Switch> getSwitches() override;

stdcxx::const_range<Switch> getSwitches(unsigned long node) const override;

stdcxx::range<Switch> getSwitches(unsigned long node) override;

stdcxx::CReference<Terminal> getTerminal(unsigned long node) const override;

stdcxx::Reference<Terminal> getTerminal(unsigned long node) override;
Expand Down
83 changes: 83 additions & 0 deletions test/iidm/NodeBreakerVoltageLevelTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1434,6 +1434,89 @@ BOOST_AUTO_TEST_CASE(testCalculatedBus) {
BOOST_CHECK(!network.getBusBreakerView().getBus("unknownBus"));
}

BOOST_AUTO_TEST_CASE(getSwitches) {
Network network("test", "test");
Substation& s = network.newSubstation()
.setId("S")
.setCountry(Country::FR)
.add();
VoltageLevel& vl = s.newVoltageLevel()
.setId("VL")
.setNominalV(400.0)
.setTopologyKind(TopologyKind::NODE_BREAKER)
.add();
vl.getNodeBreakerView().newBusbarSection()
.setId("BBS1")
.setNode(0)
.add();
vl.getNodeBreakerView().newBusbarSection()
.setId("BBS2")
.setNode(1)
.add();
vl.getNodeBreakerView().newBreaker()
.setId("C")
.setNode1(1)
.setNode2(0)
.setOpen(true)
.add();
vl.getNodeBreakerView().newBreaker()
.setId("B2")
.setNode1(0)
.setNode2(2)
.setOpen(true)
.add();
vl.getNodeBreakerView().newBreaker()
.setId("B1")
.setNode1(2)
.setNode2(3)
.setOpen(false)
.add();
vl.getNodeBreakerView().newBreaker()
.setId("B3")
.setNode1(3)
.setNode2(1)
.setOpen(false)
.add();
vl.newLoad()
.setId("LD")
.setNode(2)
.setP0(1)
.setQ0(1)
.add();

vl.getNodeBreakerView().newInternalConnection().setNode1(2).setNode2(0).add();
vl.getNodeBreakerView().newInternalConnection().setNode1(0).setNode2(1).add();
vl.getNodeBreakerView().newInternalConnection().setNode1(3).setNode2(0).add();

const VoltageLevel& cVl = vl;

auto switches = vl.getNodeBreakerView().getSwitches(0);
const auto& cSwitches = cVl.getNodeBreakerView().getSwitches(0);
BOOST_CHECK_EQUAL(2, boost::size(switches));
BOOST_CHECK_EQUAL(2, boost::size(cSwitches));

for (const std::string& name : {"C", "B2"}) {
const auto& lookup = [&name](const Switch& sw) {
return sw.getId() == name;
};
auto it = std::find_if(switches.begin(), switches.end(), lookup);
BOOST_CHECK(it != switches.end());
}

auto internalConnections = vl.getNodeBreakerView().getNodesInternalConnectedTo(0);
const auto& cInternalConnections = cVl.getNodeBreakerView().getNodesInternalConnectedTo(0);
BOOST_CHECK_EQUAL(3, boost::size(internalConnections));
BOOST_CHECK_EQUAL(3, boost::size(cInternalConnections));

for (const unsigned long expectedNode : {1, 2, 3}) {
const auto& lookup = [&expectedNode](unsigned long node) {
return node == expectedNode;
};
const auto& it = std::find_if(internalConnections.begin(), internalConnections.end(), lookup);
BOOST_CHECK(it != internalConnections.end());
}
}

BOOST_AUTO_TEST_SUITE_END()

} // namespace iidm
Expand Down
54 changes: 53 additions & 1 deletion test/math/UndirectedGraphTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ BOOST_AUTO_TEST_CASE(getEdgeObject) {
graph.addVertex();
graph.addEdge(0, 1, stdcxx::ref(expected));

const stdcxx::Reference<E>& edge = graph.getEdgeObject(0);
stdcxx::Reference<E> edge = graph.getEdgeObject(0);
BOOST_TEST(stdcxx::areSame(expected, edge.get()));

const auto& objects = graph.getEdgeObjects();
Expand Down Expand Up @@ -319,6 +319,58 @@ BOOST_AUTO_TEST_CASE(traverse) {
BOOST_CHECK_EQUAL_COLLECTIONS(expected.cbegin(), expected.cend(), encountered.cbegin(), encountered.cend());
}

BOOST_AUTO_TEST_CASE(testGetEdgesFromVertex) {
UndirectedGraph<V, E> graph;
graph.addVertex();
graph.addVertex();
graph.addVertex();
graph.addEdge(0, 1, stdcxx::ref<E>());
graph.addEdge(1, 2, stdcxx::ref<E>());

const std::vector<unsigned long>& connectedTo1Ref = {0UL, 1UL};
const std::vector<unsigned long>& connectedTo1 = graph.getEdgesConnectedToVertex(1);
BOOST_CHECK_EQUAL_COLLECTIONS(connectedTo1Ref.begin(), connectedTo1Ref.end(), connectedTo1.begin(), connectedTo1.end());

const std::vector<unsigned long>& connectedTo0Ref = {0UL};
const std::vector<unsigned long>& connectedTo0 = graph.getEdgesConnectedToVertex(0);
BOOST_CHECK_EQUAL_COLLECTIONS(connectedTo0Ref.begin(), connectedTo0Ref.end(), connectedTo0.begin(), connectedTo0.end());
}

BOOST_AUTO_TEST_CASE(testGetEdgeObjectFromVertex) {
UndirectedGraph<V, E> graph;
graph.addVertex();
graph.addVertex();
graph.addVertex();

E arrow01("Arrow01");
E arrow12("Arrow12");
graph.addEdge(0, 1, stdcxx::ref(arrow01));
graph.addEdge(1, 2, stdcxx::ref(arrow12));

const auto& connectedTo1 = graph.getEdgeObjectsConnectedToVertex(1);
BOOST_CHECK_EQUAL(2, boost::size(connectedTo1));

std::vector<std::string> refConnectedTo1 = {"Arrow01", "Arrow12"};
for (const std::string& name : refConnectedTo1) {
const auto& lookup = [&name](const stdcxx::Reference<E>& edge) {
return edge.get().getName() == name;
};
auto it = std::find_if(connectedTo1.begin(), connectedTo1.end(), lookup);
BOOST_CHECK(it != connectedTo1.end());
}

const auto& connectedTo0 = graph.getEdgeObjectsConnectedToVertex(0);
BOOST_CHECK_EQUAL(1, boost::size(connectedTo0));
std::vector<std::string> refConnectedTo0 = {"Arrow01"};
for (const std::string& name : refConnectedTo0) {
const auto& lookup = [&name](const stdcxx::Reference<E>& edge) {
return edge.get().getName() == name;
};
auto it = std::find_if(connectedTo0.begin(), connectedTo0.end(), lookup);
BOOST_CHECK(it != connectedTo0.end());
}
}

BOOST_AUTO_TEST_SUITE_END()

} // namespace math
Expand Down

0 comments on commit 460504f

Please sign in to comment.