diff --git a/ding0/examples/example_single_grid_district.py b/ding0/examples/example_single_grid_district.py index f7f13ea2..3d27aef9 100644 --- a/ding0/examples/example_single_grid_district.py +++ b/ding0/examples/example_single_grid_district.py @@ -27,6 +27,7 @@ from sqlalchemy.orm import sessionmaker import oedialect + # define logger logger = setup_logger() diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/config/__init__.py b/tests/config/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/core/__init__.py b/tests/core/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/core/network/__init__.py b/tests/core/network/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/core/network/test_grids.py b/tests/core/network/test_grids.py new file mode 100644 index 00000000..dd0a0189 --- /dev/null +++ b/tests/core/network/test_grids.py @@ -0,0 +1,452 @@ +import pytest + +from egoio.tools import db +from sqlalchemy.orm import sessionmaker +import oedialect + +import networkx as nx +import pandas as pd + +from shapely.geometry import Point, LineString, LinearRing, Polygon +from ding0.core import NetworkDing0 +from ding0.core.network import (RingDing0, BranchDing0, CircuitBreakerDing0, + GeneratorDing0, GeneratorFluctuatingDing0) +from ding0.core.network.stations import MVStationDing0, LVStationDing0 +from ding0.core.network.grids import MVGridDing0, LVGridDing0 + + +class TestMVGridDing0(object): + + @pytest.fixture + def empty_mvgridding0(self): + """ + Returns an empty MVGridDing0 object with an MVStationDing0 object + with id_db = 0 and + with geo_data = shapely.geometry.Point(0.5, 0.5) + """ + station = MVStationDing0(id_db=0, geo_data=Point(0.5, 0.5)) + grid = MVGridDing0(id_db=0, station=station) + return grid + + def test_empty_mvgridding0(self, empty_mvgridding0): + """ + Check that initialization of an object of the + class MVGridDing0 results in the right attributes being empty + lists or NoneType objects, with the exception of the + MVStationDing0 object's id_db and geo_data, which are + 0 and shapely.geometry.Point(0.5, 0.5), respectively. + """ + assert empty_mvgridding0._rings == [] + assert empty_mvgridding0._circuit_breakers == [] + assert empty_mvgridding0.default_branch_kind is None + assert empty_mvgridding0.default_branch_type is None + assert empty_mvgridding0.default_branch_kind_settle is None + assert empty_mvgridding0.default_branch_type_settle is None + assert empty_mvgridding0.default_branch_kind_aggregated is None + assert empty_mvgridding0.default_branch_type_aggregated is None + assert empty_mvgridding0._station.id_db == 0 + assert empty_mvgridding0._station.geo_data == Point(0.5, 0.5) + + def test_add_circuit_breakers(self, empty_mvgridding0): + """ + Adding a circuit breaker into an empty_mvgridding0 and check if it + works. + """ + circuit_breaker = CircuitBreakerDing0(id_db=0, + geo_data=Point(0, 0), + grid=empty_mvgridding0) + empty_mvgridding0.add_circuit_breaker(circuit_breaker) + circuit_breakers_in_grid = list(empty_mvgridding0.circuit_breakers()) + assert len(circuit_breakers_in_grid) == 1 + assert circuit_breakers_in_grid[0] == circuit_breaker + + def test_add_circuit_breakers_negative(self, empty_mvgridding0): + """ + Adding a GeneratorDing0 as a circuit_breaker through the + add_circuit_breaker just to see if the function rejects it. + """ + bad_object = GeneratorDing0(id_db=0) + empty_mvgridding0.add_circuit_breaker(bad_object) + circuit_breakers_in_grid = list(empty_mvgridding0.circuit_breakers()) + assert len(circuit_breakers_in_grid) == 0 + + @pytest.fixture + def circuit_breaker_mvgridding0(self): + """ + Returns an MVGridDing0 object with a branch and a + circuit breaker. + """ + station = MVStationDing0(id_db=0, geo_data=Point(0.5, 0.5)) + grid = MVGridDing0(id_db=0, station=station) + branch = BranchDing0(id_db=0, length=2.0, kind='cable') + circuit_breaker = CircuitBreakerDing0(id_db=0, + geo_data=Point(0, 0), + branch=branch, + grid=grid) + grid.add_circuit_breaker(circuit_breaker) + grid._graph.add_edge(circuit_breaker, station, + branch=branch) + return grid + + def test_open_circuit_breakers(self, circuit_breaker_mvgridding0): + """ + Checks that using open_circuit_breakers function used from + the MVGridDing0 object actually opens all the circuit breakers. + """ + circuit_breakers_in_grid = list( + circuit_breaker_mvgridding0.circuit_breakers() + ) + assert circuit_breakers_in_grid[0].status == 'closed' + circuit_breaker_mvgridding0.open_circuit_breakers() + assert circuit_breakers_in_grid[0].status == 'open' + + def test_close_circuit_breakers(self, circuit_breaker_mvgridding0): + """ + Checks that using close_circuit_breakers function used from + the MVGridDing0 object actually closes all the circuit breakers. + """ + circuit_breakers_in_grid = list( + circuit_breaker_mvgridding0.circuit_breakers() + ) + assert circuit_breakers_in_grid[0].status == 'closed' + circuit_breaker_mvgridding0.open_circuit_breakers() + assert circuit_breakers_in_grid[0].status == 'open' + circuit_breaker_mvgridding0.close_circuit_breakers() + assert circuit_breakers_in_grid[0].status == 'closed' + + @pytest.fixture + def ring_mvgridding0(self): + """ + Returns an MVGridDing0 object with 2 branches, + a circuit breaker and a ring. + """ + station = MVStationDing0(id_db=0, geo_data=Point(1, 1)) + grid = MVGridDing0(id_db=0, + station=station) + generator1 = GeneratorDing0(id_db=0, + geo_data=Point(1, 2), + mv_grid=grid) + grid.add_generator(generator1) + generator2 = GeneratorDing0(id_db=1, + geo_data=Point(2, 1), + mv_grid=grid) + grid.add_generator(generator2) + generator3 = GeneratorDing0(id_db=2, + geo_data=Point(2, 2), + mv_grid=grid) + grid.add_generator(generator3) + ring = RingDing0(grid=grid) + branch1 = BranchDing0(id_db='0', length=2.0, kind='cable', ring=ring) + branch1a = BranchDing0(id_db='0a', lenght=1.2, kind='cable', ring=ring) + branch2 = BranchDing0(id_db='1', lenght=3.0, kind='line', ring=ring) + branch2a = BranchDing0(id_db='1a', lenght=2.0, kind='line', ring=ring) + branch3 = BranchDing0(id_db='2', length=2.5, kind='line') + circuit_breaker1 = CircuitBreakerDing0(id_db=0, + geo_data=Point(0, 0), + branch=branch1, + grid=grid) + grid.add_circuit_breaker(circuit_breaker1) + grid._graph.add_edge(generator1, station, + branch=branch1) + grid._graph.add_edge(circuit_breaker1, generator1, + branch=branch1a) + grid._graph.add_edge(generator2, station, + branch=branch2) + grid._graph.add_edge(circuit_breaker1, generator2, + branch=branch2a) + grid._graph.add_edge(generator3, generator2, branch=branch3) + grid.add_ring(ring) + return (ring, grid) + + def test_add_ring(self, ring_mvgridding0): + """ + Check if the number of rings is increased and the correct ring + is added by using the add_ring function inside of MVGriDing0. + """ + ring, grid = ring_mvgridding0 + assert len(grid._rings) == 1 + assert grid._rings[0] == ring + + def test_rings_count(self, ring_mvgridding0): + """ + Check if the number of rings is correctly reflected using the + rings_count function in MVGridDing0 and the correct ring + is added by using the add_ring function inside of MVGriDing0. + """ + ring, grid = ring_mvgridding0 + assert grid.rings_count() == 1 + assert grid._rings[0] == ring + + def test_get_ring_from_node(self, ring_mvgridding0): + """ + Checks that the ring obtained from the get_ring_from_node object + works as expected returning the correct ring. + """ + ring, grid = ring_mvgridding0 + station = grid.station() + assert grid.get_ring_from_node(station) == ring + + def test_rings_nodes_root_only_include_root(self, ring_mvgridding0): + """ + Checks that the ring obtained from the rings_nodes function + setting the include_root_node parameter to "True" + contains the list of nodes that are expected. + """ + ring, grid = ring_mvgridding0 + station = grid.station() + generators = list(grid.generators()) + circuit_breakers = list(grid.circuit_breakers()) + rings_nodes_expected = [generators[0], + circuit_breakers[0], + generators[1], + station] + rings_nodes = list(grid.rings_nodes(include_root_node=True))[0] + assert rings_nodes == rings_nodes_expected + + def test_rings_nodes_root_only_exclude_root(self, ring_mvgridding0): + """ + Checks that the ring obtained from the rings_nodes function + setting the include_root_node parameter to "False" + contains the list of nodes that are expected. + """ + ring, grid = ring_mvgridding0 + generators = list(grid.generators()) + circuit_breakers = list(grid.circuit_breakers()) + rings_nodes_expected = [generators[0], + circuit_breakers[0], + generators[1]] + rings_nodes = list(grid.rings_nodes(include_root_node=False))[0] + assert rings_nodes == rings_nodes_expected + + def test_rings_nodes_include_satellites_include_root(self, + ring_mvgridding0): + """ + Checks that the ring obtained from the rings_nodes function + setting the include_root_node parameter to "True" and + setting the include_satellites to "True" + contains the list of nodes that are expected. + """ + ring, grid = ring_mvgridding0 + station = grid.station() + generators = list(grid.generators()) + circuit_breakers = list(grid.circuit_breakers()) + rings_nodes_expected = [generators[0], + circuit_breakers[0], + generators[1], + #station, + generators[2]] + rings_nodes = list(grid.rings_nodes(include_root_node=True, + include_satellites=True))[0] + assert rings_nodes == rings_nodes_expected + + def test_rings_nodes_include_satellites_exclude_root(self, + ring_mvgridding0): + """ + Checks that the ring obtained from the rings_nodes function + setting the include_root_node parameter to "False" and + setting the include_satellites to "True" + contains the list of nodes that are expected. + """ + ring, grid = ring_mvgridding0 + generators = list(grid.generators()) + circuit_breakers = list(grid.circuit_breakers()) + rings_nodes_expected = [generators[0], + circuit_breakers[0], + generators[1], + generators[2]] + rings_nodes = list(grid.rings_nodes(include_root_node=False, + include_satellites=True))[0] + assert rings_nodes == rings_nodes_expected + + def test_rings_full_data(self, ring_mvgridding0): + """ + Checks if the function rings_full_data produces the expected + list of rings, list of branches and list of ring_nodes. + """ + ring, grid = ring_mvgridding0 + station = grid.station() + generators = list(grid.generators()) + circuit_breakers = list(grid.circuit_breakers()) + branches = sorted(list(map(lambda x: x['branch'], + grid.graph_edges())), + key=lambda x: repr(x)) + ring_expected = ring + # branches following the ring + branches_expected = [branches[1], + branches[0], + branches[3], + branches[2]] + rings_nodes_expected = [generators[0], + circuit_breakers[0], + generators[1], + station] + (ring_out, + branches_out, + rings_nodes_out) = list(grid.rings_full_data())[0] + assert ring_out == ring_expected + assert branches_out == branches_expected + assert rings_nodes_out == rings_nodes_expected + + def test_graph_nodes_from_subtree_station(self, ring_mvgridding0): + """ + Check the output of function graph_nodes_from_subtree using the + station as the source node. With this input, there should be no + nodes. This should mean an empty list is returned by the + graph_nodes_from_subtree function. + """ + ring, grid = ring_mvgridding0 + station = grid.station() + with pytest.raises(UnboundLocalError): + nodes_out = grid.graph_nodes_from_subtree(station) + # nodes_expected = [] + # assert nodes_out == nodes_expected + + def test_graph_nodes_from_subtree_circuit_breaker(self, ring_mvgridding0): + """ + Check the output of function graph_nodes_from_subtree using the + circuit breaker as the source node. With this input, there should be no + nodes. This should mean an empty list is returned by the + graph_nodes_from_subtree function. + """ + ring, grid = ring_mvgridding0 + circuit_breakers = list(grid.circuit_breakers()) + nodes_out = grid.graph_nodes_from_subtree(circuit_breakers[0]) + nodes_expected = [] + assert nodes_out == nodes_expected + + def test_graph_nodes_from_subtree_ring_branch_left(self, ring_mvgridding0): + """ + Check the output of function graph_nodes_from_subtree using the + generator on the left branch as the source node. + With this input, there should be no nodes. + This should mean an empty list is returned by the + graph_nodes_from_subtree function. + """ + ring, grid = ring_mvgridding0 + generators = list(grid.generators()) + nodes_out = grid.graph_nodes_from_subtree(generators[0]) + nodes_expected = [] + assert nodes_out == nodes_expected + + def test_graph_nodes_from_subtree_ring_branch_right(self, + ring_mvgridding0): + """ + Check the output of function graph_nodes_from_subtree using the + generator on the right branch as the source node. + With this input, there should be one node, + the generator outside the ring connected to the right branch using + a stub. This should mean a list with this specific generator + should be returned by the graph_nodes_from_subtree function. + """ + ring, grid = ring_mvgridding0 + generators = list(grid.generators()) + nodes_out = grid.graph_nodes_from_subtree(generators[1]) + nodes_expected = [generators[2]] + assert nodes_out == nodes_expected + + def test_graph_nodes_from_subtree_off_ring(self, ring_mvgridding0): + """ + Check the output of function graph_nodes_from_subtree using the + generator outside of the ring as the source node. + With this input, there should be no nodes. + This should mean an empty list is returned by the + graph_nodes_from_subtree function. + """ + ring, grid = ring_mvgridding0 + generators = list(grid.generators()) + with pytest.raises(UnboundLocalError): + nodes_out = grid.graph_nodes_from_subtree(generators[2]) + # nodes_expected = [] + # assert nodes_out == nodes_expected + + @pytest.fixture + def oedb_session(self): + """ + Returns an ego.io oedb session and closes it on finishing the test + """ + engine = db.connection(section='oedb') + session = sessionmaker(bind=engine)() + yield session + print("closing session") + session.close() + + def test_routing(self, oedb_session): + """ + Using the grid district 460 as an example, the properties of the + networkx graph is tested before routing and after routing. + """ + # instantiate new ding0 network object + nd = NetworkDing0(name='network') + + nd.import_mv_grid_districts(oedb_session, + mv_grid_districts_no=[460]) + # STEP 2: Import generators + nd.import_generators(oedb_session) + # STEP 3: Parametrize MV grid + nd.mv_parametrize_grid() + # STEP 4: Validate MV Grid Districts + nd.validate_grid_districts() + # STEP 5: Build LV grids + nd.build_lv_grids() + + graph = nd._mv_grid_districts[0].mv_grid._graph + + assert len(list(graph.nodes())) == 256 + assert len(list(graph.edges())) == 0 + assert len(list(nx.isolates(graph))) == 256 + assert pd.Series(dict(graph.degree())).sum(axis=0) == 0 + assert pd.Series(dict(graph.degree())).mean(axis=0) == 0.0 + assert len(list(nx.get_edge_attributes(graph, 'branch'))) == 0 + assert nx.average_node_connectivity(graph) == 0.0 + assert pd.Series( + nx.degree_centrality(graph) + ).mean(axis=0) == 0.0 + assert pd.Series( + nx.closeness_centrality(graph) + ).mean(axis=0) == 0.0 + assert pd.Series( + nx.betweenness_centrality(graph) + ).mean(axis=0) == 0.0 + + nd.mv_routing() + + assert len(list(graph.nodes())) == 269 + assert len(list(graph.edges())) == 218 + assert len(list(nx.isolates(graph))) == 54 + assert pd.Series(dict(graph.degree())).sum(axis=0) == 436 + assert pd.Series( + dict(graph.degree()) + ).mean(axis=0) == pytest.approx(1.62, 0.001) + assert len(list(nx.get_edge_attributes(graph, 'branch'))) == 218 + assert nx.average_node_connectivity(graph) == pytest.approx( + 0.688, + abs=0.0001 + ) + assert pd.Series( + nx.degree_centrality(graph) + ).mean(axis=0) == pytest.approx(0.006, abs=0.001) + assert pd.Series( + nx.closeness_centrality(graph) + ).mean(axis=0) == pytest.approx(0.042474, abs=0.00001) + assert pd.Series( + nx.betweenness_centrality(graph) + ).mean(axis=0) == pytest.approx(0.0354629, abs=0.00001) + assert pd.Series( + nx.edge_betweenness_centrality(graph) + ).mean(axis=0) == pytest.approx(0.04636150, abs=0.00001) + + +class TestLVGridDing0(object): + + @pytest.fixture + def empty_lvgridding0(self): + """ + Returns and empty LVGridDing0 object + """ + lv_station = LVStationDing0(id_db=0, geo_data=Point(1, 1)) + grid = LVGridDing0(id_db=0, station=lv_station) + return grid + + +if __name__ == "__main__": + pass diff --git a/tests/core/network/test_network.py b/tests/core/network/test_network.py new file mode 100644 index 00000000..f868afef --- /dev/null +++ b/tests/core/network/test_network.py @@ -0,0 +1,357 @@ +import pytest +from shapely.geometry import Point, LineString, LinearRing, Polygon +from ding0.core import NetworkDing0 +from ding0.core.network import (GridDing0, + StationDing0, TransformerDing0, + RingDing0, BranchDing0, + CableDistributorDing0, CircuitBreakerDing0, + GeneratorDing0, GeneratorFluctuatingDing0, + LoadDing0) +from ding0.core.structure.regions import LVLoadAreaCentreDing0 + + +class TestGridDing0(object): + + @pytest.fixture + def empty_grid(self): + """ + Returns an empty GridDing0 object. + """ + return GridDing0() + + @pytest.fixture + def cable_distributor_grid(self): + """ + Returns a GridDing0 object with 2 CableDistributorDing0 + objects at Point(0, 0) and id_db=0, + and at Point(0, 1) and id_db=1 + """ + cable_distributor_grid = GridDing0() + geo_data1 = Point(0, 0) + cable_distributor1 = CableDistributorDing0(id_db=0, + geo_data=geo_data1, + grid=cable_distributor_grid) + geo_data2 = Point(0, 1) + cable_distributor2 = CableDistributorDing0(id_db=1, + geo_data=geo_data2, + grid=cable_distributor_grid) + # There is no setter function for providing a list + # of cable_distributors to the empty_grid + cable_distributor_grid._cable_distributors = [cable_distributor1, + cable_distributor2] + return cable_distributor_grid + + def test_get_cable_distributors_list(self, cable_distributor_grid): + cable_distributor_list = list( + cable_distributor_grid.cable_distributors() + ) + assert len(cable_distributor_list) == 2 + assert cable_distributor_list[0].id_db == 0 + assert cable_distributor_list[0].geo_data == Point(0, 0) + assert cable_distributor_list[1].id_db == 1 + assert cable_distributor_list[1].geo_data == Point(0, 1) + + def test_cable_distributors_count(self, cable_distributor_grid): + assert cable_distributor_grid.cable_distributors_count() == 2 + + @pytest.fixture + def load_grid(self): + """ + Returns a GridDing0 object with 2 LoadDing0 + objects at Point(0, 0) and id_db=0, and + another at Point(0, 1) and id_db=1, + Note: this function causes the id_db to be increased by 1. + Thus changing the id_db to 1 and 2 respectively + """ + load_grid = GridDing0() + geo_data1 = Point(0, 0) + load1 = LoadDing0(id_db=0, + geo_data=geo_data1, + grid=load_grid) + # There is no setter function for providing a list + # of loads to the empty_grid + load_grid._loads = [load1] + geo_data2 = Point(0, 1) + load2 = LoadDing0(id_db=0, + geo_data=geo_data2, + grid=load_grid) + load_grid._loads.append(load2) + return load_grid + + def test_loads_list(self, load_grid): + load_list = list(load_grid.loads()) + assert len(load_list) == 2 + assert load_list[0].id_db == 1 + assert load_list[0].geo_data == Point(0, 0) + assert load_list[1].id_db == 2 + assert load_list[1].geo_data == Point(0, 1) + + def test_loads_count(self, load_grid): + assert load_grid.loads_count() == 2 + + @pytest.fixture + def generator_grid(self): + """ + Returns a GridDing0 object with + 2 GeneratorDing0 objects + at Point(0, 0) and id_db=0 and + at Point(0, 1) and id_db=1, and + 2 GeneratorFluctuatingDing0 objects + at Point(1, 0), id_db=2, weather_cell_id=0 and + at Point(1, 1), id_db=3, weather_cell_id=1 + """ + generator_grid = GridDing0() + geo_data1 = Point(0, 0) + generator1 = GeneratorDing0(id_db=0, + geo_data=geo_data1) + geo_data2 = Point(0, 1) + generator2 = GeneratorDing0(id_db=1, + geo_data=geo_data2) + geo_data3 = Point(1, 0) + generator3 = GeneratorFluctuatingDing0(id_db=2, + weather_cell_id=0, + geo_data=geo_data3) + geo_data4 = Point(1, 1) + generator4 = GeneratorFluctuatingDing0(id_db=3, + weather_cell_id=1, + geo_data=geo_data4) + generator_grid._generators = [generator1, + generator2, + generator3, + generator4] + return generator_grid + + def test_add_generator(self, empty_grid): + geo_data1 = Point(0, 0) + generator1 = GeneratorDing0(id_db=0, + geo_data=geo_data1) + empty_grid.add_generator(generator1) + assert len(list(empty_grid.generators())) == 1 + geo_data2 = Point(0, 1) + generator2 = GeneratorDing0(id_db=1, + geo_data=geo_data2) + empty_grid.add_generator(generator2) + assert len(list(empty_grid.generators())) == 2 + geo_data3 = Point(1, 0) + generator3 = GeneratorFluctuatingDing0(id_db=2, + weather_cell_id=0, + geo_data=geo_data3) + empty_grid.add_generator(generator3) + assert len(list(empty_grid.generators())) == 3 + geo_data4 = Point(1, 1) + generator4 = GeneratorFluctuatingDing0(id_db=3, + weather_cell_id=1, + geo_data=geo_data4) + empty_grid.add_generator(generator4) + assert len(list(empty_grid.generators())) == 4 + generator_list = list(empty_grid.generators()) + assert generator_list[0].id_db == 0 + assert generator_list[0].geo_data == geo_data1 + assert generator_list[1].id_db == 1 + assert generator_list[1].geo_data == geo_data2 + assert generator_list[2].id_db == 2 + assert generator_list[2].weather_cell_id == 0 + assert generator_list[2].geo_data == geo_data3 + assert generator_list[3].id_db == 3 + assert generator_list[3].weather_cell_id == 1 + assert generator_list[3].geo_data == geo_data4 + + # check for all positive cases of graph_add_node + def test_graph_add_node_station(self, empty_grid): + station1 = StationDing0() + empty_grid.graph_add_node(station1) + assert station1 in empty_grid._graph.nodes() + assert len(list(empty_grid._graph.nodes())) == 1 + + def test_graph_add_node_cable_distributor(self, empty_grid): + cable_distributor1 = CableDistributorDing0() + empty_grid.graph_add_node(cable_distributor1) + assert cable_distributor1 in empty_grid._graph.nodes() + assert len(list(empty_grid._graph.nodes())) == 1 + + def test_graph_add_node_lv_load_area_centre(self, empty_grid): + lv_load_area_centre1 = LVLoadAreaCentreDing0() + empty_grid.graph_add_node(lv_load_area_centre1) + assert lv_load_area_centre1 in empty_grid._graph.nodes() + assert len(list(empty_grid._graph.nodes())) == 1 + + def test_graph_add_node_generator(self, empty_grid): + # an add_node is called within add_generator + geo_data1 = Point(0, 0) + generator1 = GeneratorDing0(id_db=0, + geo_data=geo_data1) + empty_grid.graph_add_node(generator1) + assert generator1 in empty_grid._graph.nodes() + assert len(list(empty_grid._graph.nodes())) == 1 + + def test_graph_add_node_add_generator(self, empty_grid): + # an add_node is called within add_generator + geo_data1 = Point(0, 0) + generator1 = GeneratorDing0(id_db=0, + geo_data=geo_data1) + empty_grid.add_generator(generator1) + assert generator1 in empty_grid._graph.nodes() + # make sure that another call of add_nodes + # does nothing + len_nodes_before = len(list(empty_grid._graph.nodes())) + empty_grid.graph_add_node(generator1) + len_nodes_after = len(list(empty_grid._graph.nodes())) + assert len_nodes_before == len_nodes_after + + def test_graph_add_node_generator_fluctuating(self, empty_grid): + # an add_node is called within add_generator + geo_data1 = Point(0, 0) + generator1 = GeneratorFluctuatingDing0(id_db=0, + geo_data=geo_data1) + empty_grid.add_generator(generator1) + assert generator1 in empty_grid._graph.nodes() + # make sure that another call of add_nodes + # does nothing + len_nodes_before = len(list(empty_grid._graph.nodes())) + empty_grid.graph_add_node(generator1) + len_nodes_after = len(list(empty_grid._graph.nodes())) + assert len_nodes_before == len_nodes_after + + # negative tests for graph_add_node + def test_graph_add_node_load(self, empty_grid): + load1 = LoadDing0(grid=empty_grid) + empty_grid._loads = [load1] + # make sure that call of add_nodes + # does nothing + len_nodes_before = len(list(empty_grid._graph.nodes())) + empty_grid.graph_add_node(load1) + len_nodes_after = len(list(empty_grid._graph.nodes())) + assert len_nodes_before == len_nodes_after + + def test_graph_add_node_branch(self, empty_grid): + branch1 = BranchDing0() + # make sure that call of add_nodes + # does nothing + len_nodes_before = len(list(empty_grid._graph.nodes())) + empty_grid.graph_add_node(branch1) + len_nodes_after = len(list(empty_grid._graph.nodes())) + assert len_nodes_before == len_nodes_after + + def test_graph_add_node_grid(self, empty_grid): + grid1 = GridDing0() + # make sure that call of add_nodes + # does nothing + len_nodes_before = len(list(empty_grid._graph.nodes())) + empty_grid.graph_add_node(grid1) + len_nodes_after = len(list(empty_grid._graph.nodes())) + assert len_nodes_before == len_nodes_after + + @pytest.fixture + def simple_graph_grid(self): + grid = GridDing0(id_db=0) + station = StationDing0(id_db=0, geo_data=Point(0, 0)) + generator = GeneratorDing0(id_db=0, + geo_data=Point(0, 1), + mv_grid=grid) + grid.graph_add_node(station) + grid.add_generator(generator) + branch = BranchDing0(id_db=0, + length=2.0, + kind='cable') + grid._graph.add_edge(generator, station, branch=branch) + return (grid, station, generator, branch) + + def test_graph_nodes_from_branch(self, simple_graph_grid): + grid, station, generator, branch = simple_graph_grid + nodes_from_branch = grid.graph_nodes_from_branch(branch) + assert type(nodes_from_branch) == tuple + assert nodes_from_branch == (station, generator) + + def test_graph_branches_from_node(self, simple_graph_grid): + grid, station, generator, branch = simple_graph_grid + branches_from_node = grid.graph_branches_from_node(station) + assert branches_from_node == [(generator, dict(branch=branch))] + + def test_graph_edges(self, simple_graph_grid): + grid, station, generator, branch = simple_graph_grid + graph_edges = list(grid.graph_edges()) + assert graph_edges[0] == dict(adj_nodes=(station, generator), + branch=branch) + + def test_find_path(self, simple_graph_grid): + grid, station, generator, branch = simple_graph_grid + path = grid.find_path(generator, station) + assert path == [generator, station] + + def test_graph_path_length(self, simple_graph_grid): + grid, station, generator, branch = simple_graph_grid + path_length = grid.graph_path_length(generator, station) + assert path_length == 2.0 + + def test_graph_isolated_nodes(self, simple_graph_grid): + grid, station, generator, branch = simple_graph_grid + isolates = grid.graph_isolated_nodes() + assert isolates == [] + + +class TestStationDing0(object): + + @pytest.fixture + def empty_stationding0(self): + """ + Returns an empty StationDing0 object + """ + return StationDing0() + + @pytest.fixture + def test_empty_stationding0(self, empty_stationding0): + assert empty_stationding0.id_db is None + assert empty_stationding0.geo_data is None + assert empty_stationding0.grid is None + assert empty_stationding0.v_level_operation is None + assert list(empty_stationding0.transformers()) == [] + + def test_add_transformer(self, empty_stationding0): + transformer1 = TransformerDing0(id_db=0, + v_level=4, + s_max_longterm=400.0, + s_max_shortterm=600.0, + s_max_emergency=800.0, + phase_angle=0.0, + tap_ratio=1.02, + r=0.02, + x=0.002) + transformer2 = TransformerDing0(id_db=1, + v_level=4, + s_max_longterm=600.0, + s_max_shortterm=900.0, + s_max_emergency=1100.0, + phase_angle=0.01, + tap_ratio=1.00, + r=0.01, + x=0.001) + empty_stationding0.add_transformer(transformer1) # added 1 + empty_stationding0.add_transformer(transformer2) # added 2 + transformer_list = list(empty_stationding0.transformers()) + assert len(transformer_list) == 2 + transformer1_in_empty_stationding0 = transformer_list[0] + assert transformer1_in_empty_stationding0 == transformer1 + assert transformer1_in_empty_stationding0.id_db == 0 + assert transformer1_in_empty_stationding0.v_level == 4 + assert transformer1_in_empty_stationding0.s_max_a == 400.0 + assert transformer1_in_empty_stationding0.s_max_b == 600.0 + assert transformer1_in_empty_stationding0.s_max_c == 800.0 + assert transformer1_in_empty_stationding0.phase_angle == 0.0 + assert transformer1_in_empty_stationding0.tap_ratio == 1.02 + assert transformer1_in_empty_stationding0.r == 0.02 + assert transformer1_in_empty_stationding0.x == 0.002 + transformer2_in_empty_stationding0 = transformer_list[1] + assert transformer2_in_empty_stationding0 == transformer2 + assert transformer2_in_empty_stationding0.id_db == 1 + assert transformer2_in_empty_stationding0.v_level == 4 + assert transformer2_in_empty_stationding0.s_max_a == 600.0 + assert transformer2_in_empty_stationding0.s_max_b == 900.0 + assert transformer2_in_empty_stationding0.s_max_c == 1100.0 + assert transformer2_in_empty_stationding0.phase_angle == 0.01 + assert transformer2_in_empty_stationding0.tap_ratio == 1.00 + assert transformer2_in_empty_stationding0.r == 0.01 + assert transformer2_in_empty_stationding0.x == 0.001 + + +if __name__ == "__main__": + pass diff --git a/tests/core/network/test_stations.py b/tests/core/network/test_stations.py new file mode 100644 index 00000000..d5174877 --- /dev/null +++ b/tests/core/network/test_stations.py @@ -0,0 +1,23 @@ +import pytest +from ding0.core.network import GridDing0, \ + GeneratorDing0, GeneratorFluctuatingDing0 + + +class TestMVStationDing0(object): + + @pytest.fixture + def empty_gridding0(self): + """ + Returns an empty GridDing0 object + """ + return GridDing0() + + def test_mv_grid_districts(self): + pass + + def test_run_ding0(self): + pass + + +if __name__ == "__main__": + pass diff --git a/tests/core/test_core.py b/tests/core/test_core.py new file mode 100644 index 00000000..981cd7d6 --- /dev/null +++ b/tests/core/test_core.py @@ -0,0 +1,43 @@ +import pytest + +from egoio.tools import db +from sqlalchemy.orm import sessionmaker +import oedialect + +from ding0.core import NetworkDing0 + + +class TestNetworkDing0(object): + + @pytest.fixture + def emptyNetworkDing0(self): + """ + Returns an empty NetworkDing0 object for testing + """ + return NetworkDing0() + + @pytest.fixture + def oedb_session(self): + """ + Returns an ego.io oedb session and closes it on finishing the test + """ + engine = db.connection(section='oedb') + session = sessionmaker(bind=engine)() + yield session + print("closing session") + session.close() + + def test_empty_mv_grid_districts(self, emptyNetworkDing0): + mv_grid_districts = list(emptyNetworkDing0.mv_grid_districts()) + empty_list = [] + assert mv_grid_districts == empty_list + + def test_import_mv_grid_districts(self, oedb_session): + with pytest.raises(TypeError): + NetworkDing0.import_mv_grid_districts( + oedb_session, + mv_grid_districts_no=['5'] + ) + + # def test_run_ding0(self): + # pass diff --git a/tests/core/test_powerflow.py b/tests/core/test_powerflow.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/core/test_structure.py b/tests/core/test_structure.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/data/__init__.py b/tests/data/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/flexopt/__init__.py b/tests/flexopt/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/grid/__init__.py b/tests/grid/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/tools/__init__.py b/tests/tools/__init__.py new file mode 100644 index 00000000..e69de29b