22
22
from ding0 .core .network .stations import *
23
23
from ding0 .core .structure .regions import *
24
24
from ding0 .core .powerflow import *
25
- from ding0 .tools import pypsa_io
25
+ from ding0 .tools . pypsa_io import initialize_component_dataframes , fill_mvgd_component_dataframes
26
26
from ding0 .tools .animation import AnimationDing0
27
27
from ding0 .tools .plots import plot_mv_topology
28
28
from ding0 .flexopt .reinforce_grid import *
29
+ from ding0 .tools .logger import get_default_home_dir
30
+ from ding0 .tools .tools import merge_two_dicts_of_dataframes
29
31
30
32
import os
31
33
import logging
38
40
from sqlalchemy import func
39
41
from geoalchemy2 .shape import from_shape
40
42
import subprocess
43
+ import json
41
44
import oedialect
42
45
43
46
if not 'READTHEDOCS' in os .environ :
@@ -266,33 +269,28 @@ def run_ding0(self, session, mv_grid_districts_no=None, debug=False, export_figu
266
269
Generators are connected to grids, used approach depends on voltage
267
270
level.
268
271
269
- * STEP 8: Set IDs for all branches in MV and LV grids
270
-
271
- While IDs of imported objects can be derived from dataset's ID, branches
272
- are created in steps 5+6 and need unique IDs (e.g. for PF calculation).
273
-
274
- * STEP 9: Relocate switch disconnectors in MV grid
272
+ * STEP 8: Relocate switch disconnectors in MV grid
275
273
276
274
Switch disconnectors are set during routing process (step 6) according
277
275
to the load distribution within a ring. After further modifications of
278
276
the grid within step 6+7 they have to be relocated (note: switch
279
277
disconnectors are called circuit breakers in DING0 for historical reasons).
280
278
281
- * STEP 10 : Open all switch disconnectors in MV grid
279
+ * STEP 9 : Open all switch disconnectors in MV grid
282
280
283
281
Under normal conditions, rings are operated in open state (half-rings).
284
282
Furthermore, this is required to allow powerflow for MV grid.
285
283
286
- * STEP 11 : Do power flow analysis of MV grid
284
+ * STEP 10 : Do power flow analysis of MV grid
287
285
288
286
The technically working MV grid created in step 6 was extended by satellite
289
287
loads and generators. It is finally tested again using powerflow calculation.
290
288
291
- * STEP 12 : Reinforce MV grid
289
+ * STEP 11 : Reinforce MV grid
292
290
293
291
MV grid is eventually reinforced persuant to results from step 11.
294
292
295
- STEP 13 : Close all switch disconnectors in MV grid
293
+ * STEP 12 : Close all switch disconnectors in MV grid
296
294
The rings are finally closed to hold a complete graph (if the SDs are open,
297
295
the edges adjacent to a SD will not be exported!)
298
296
"""
@@ -326,18 +324,15 @@ def run_ding0(self, session, mv_grid_districts_no=None, debug=False, export_figu
326
324
if export_figures :
327
325
plot_mv_topology (grid , subtitle = 'Generators connected' , filename = '2_generators_connected.png' )
328
326
329
- # STEP 8: Set IDs for all branches in MV and LV grids
330
- self .set_branch_ids ()
331
-
332
- # STEP 9: Relocate switch disconnectors in MV grid
327
+ # STEP 8: Relocate switch disconnectors in MV grid
333
328
self .set_circuit_breakers (debug = debug )
334
329
if export_figures :
335
330
plot_mv_topology (grid , subtitle = 'Circuit breakers relocated' , filename = '3_circuit_breakers_relocated.png' )
336
331
337
- # STEP 10 : Open all switch disconnectors in MV grid
332
+ # STEP 9 : Open all switch disconnectors in MV grid
338
333
self .control_circuit_breakers (mode = 'open' )
339
334
340
- # STEP 11 : Do power flow analysis of MV grid
335
+ # STEP 10 : Do power flow analysis of MV grid
341
336
self .run_powerflow (session , method = 'onthefly' , export_pypsa = False , debug = debug )
342
337
if export_figures :
343
338
plot_mv_topology (grid , subtitle = 'PF result (load case)' ,
@@ -347,10 +342,10 @@ def run_ding0(self, session, mv_grid_districts_no=None, debug=False, export_figu
347
342
filename = '5_PF_result_feedin.png' ,
348
343
line_color = 'loading' , node_color = 'voltage' , testcase = 'feedin' )
349
344
350
- # STEP 12 : Reinforce MV grid
345
+ # STEP 11 : Reinforce MV grid
351
346
self .reinforce_grid ()
352
347
353
- # STEP 13 : Close all switch disconnectors in MV grid
348
+ # STEP 12 : Close all switch disconnectors in MV grid
354
349
self .control_circuit_breakers (mode = 'close' )
355
350
356
351
if export_figures :
@@ -979,7 +974,7 @@ def import_res_generators():
979
974
generator = GeneratorFluctuatingDing0 (
980
975
id_db = id_db ,
981
976
mv_grid = mv_grid ,
982
- capacity = row ['electrical_capacity' ],
977
+ capacity = float ( row ['electrical_capacity' ]) ,
983
978
type = row ['generation_type' ],
984
979
subtype = row ['generation_subtype' ],
985
980
v_level = int (row ['voltage_level' ]),
@@ -988,7 +983,7 @@ def import_res_generators():
988
983
generator = GeneratorDing0 (
989
984
id_db = id_db ,
990
985
mv_grid = mv_grid ,
991
- capacity = row ['electrical_capacity' ],
986
+ capacity = float ( row ['electrical_capacity' ]) ,
992
987
type = row ['generation_type' ],
993
988
subtype = row ['generation_subtype' ],
994
989
v_level = int (row ['voltage_level' ]))
@@ -1349,7 +1344,7 @@ def validate_grid_districts(self):
1349
1344
for grid_district in self .mv_grid_districts ():
1350
1345
1351
1346
# there's only one node (MV station) => grid is empty
1352
- if len (grid_district .mv_grid ._graph .nodes ()) == 1 :
1347
+ if len (grid_district .mv_grid .graph .nodes ()) == 1 :
1353
1348
invalid_mv_grid_districts .append (grid_district )
1354
1349
msg_invalidity .append ('MV Grid District {} seems to be empty ' \
1355
1350
'and ' \
@@ -1412,7 +1407,7 @@ def export_mv_grid(self, session, mv_grid_districts):
1412
1407
lines = []
1413
1408
1414
1409
# get nodes from grid's graph and append to corresponding array
1415
- for node in grid_district .mv_grid ._graph .nodes ():
1410
+ for node in grid_district .mv_grid .graph .nodes ():
1416
1411
if isinstance (node , LVLoadAreaCentreDing0 ):
1417
1412
lv_load_area_centres .append ((node .geo_data .x , node .geo_data .y ))
1418
1413
elif isinstance (node , MVCableDistributorDing0 ):
@@ -1527,7 +1522,7 @@ def export_mv_grid_new(self, session, mv_grid_districts):
1527
1522
for grid_district in self .mv_grid_districts ():
1528
1523
1529
1524
# get nodes from grid's graph and create datasets
1530
- for node in grid_district .mv_grid ._graph .nodes ():
1525
+ for node in grid_district .mv_grid .graph .nodes ():
1531
1526
if hasattr (node , 'voltage_res' ):
1532
1527
node_name = '_' .join (['MV' ,
1533
1528
str (grid_district .mv_grid .id_db ),
@@ -1610,8 +1605,9 @@ def export_mv_grid_new(self, session, mv_grid_districts):
1610
1605
1611
1606
logger .info ('=====> MV Grids exported (NEW)' )
1612
1607
1613
- def to_dataframe (self ):
1608
+ def to_dataframe_old (self ):
1614
1609
"""
1610
+ Todo: remove? or replace by part of to_csv()
1615
1611
Export grid data to dataframes for statistical analysis.
1616
1612
1617
1613
The export to dataframe is similar to db tables exported by `export_mv_grid_new`.
@@ -1728,6 +1724,95 @@ def to_dataframe(self):
1728
1724
1729
1725
return nodes_df , edges_df
1730
1726
1727
+ def to_csv (self , dir = '' , only_export_mv = False ):
1728
+ '''
1729
+ Function to export network to csv. Converts network in dataframes which are adapted to pypsa format.
1730
+ Respectively saves files for network, buses, lines, transformers, loads and generators.
1731
+
1732
+ Parameters
1733
+ ----------
1734
+ dir: :obj:`str`
1735
+ Directory to which network is saved.
1736
+ only_export_mv: bool
1737
+ When True only mv topology is exported with aggregated lv grid districts
1738
+ '''
1739
+
1740
+ buses_df , generators_df , lines_df , loads_df , transformer_df = initialize_component_dataframes ()
1741
+ if (dir == '' ):
1742
+ dir = get_default_home_dir () # eventuell ändern
1743
+ # open all switch connectors
1744
+ self .control_circuit_breakers (mode = 'open' )
1745
+ # start filling component dataframes
1746
+ for grid_district in self .mv_grid_districts ():
1747
+ gd_components , network_df , _ = fill_mvgd_component_dataframes (
1748
+ grid_district , buses_df , generators_df ,
1749
+ lines_df , loads_df ,transformer_df , only_export_mv )
1750
+ # save network and components to csv
1751
+ path = os .path .join (dir , str (grid_district .id_db ))
1752
+ if not os .path .exists (path ):
1753
+ os .makedirs (path )
1754
+ network_df .to_csv (os .path .join (path , 'network.csv' ))
1755
+ gd_components ['HVMV_Transformer' ].to_csv (
1756
+ os .path .join (path , 'transformers_hvmv.csv' ))
1757
+ gd_components ['Transformer' ].to_csv (
1758
+ os .path .join (path , 'transformers.csv' ))
1759
+ gd_components ['Bus' ].to_csv (
1760
+ os .path .join (path , 'buses.csv' ))
1761
+ gd_components ['Line' ].to_csv (
1762
+ os .path .join (path , 'lines.csv' ))
1763
+ gd_components ['Load' ].to_csv (
1764
+ os .path .join (path , 'loads.csv' ))
1765
+ gd_components ['Generator' ].to_csv (
1766
+ os .path .join (path , 'generators.csv' ))
1767
+ gd_components ['Switch' ].to_csv (
1768
+ os .path .join (path , 'switches.csv' ))
1769
+
1770
+ # Merge metadata of multiple runs
1771
+ if 'metadata' not in locals ():
1772
+ metadata = self .metadata
1773
+
1774
+ else :
1775
+ if isinstance (grid_district , list ):
1776
+ metadata ['mv_grid_districts' ].extend (grid_district )
1777
+ else :
1778
+ metadata ['mv_grid_districts' ].append (grid_district )
1779
+
1780
+ # Save metadata to disk
1781
+ with open (os .path .join (path , 'Ding0_{}.meta' .format (metadata ['run_id' ])),
1782
+ 'w' ) as f :
1783
+ json .dump (metadata , f )
1784
+
1785
+
1786
+ def to_dataframe (self , only_export_mv = False ):
1787
+ '''
1788
+ Function to export network to csv. Converts network in dataframes which are adapted to pypsa format.
1789
+ Respectively saves files for network, buses, lines, transformers, loads and generators.
1790
+
1791
+ Parameters
1792
+ ----------
1793
+ only_export_mv: bool
1794
+ When True only mv topology is exported with aggregated lv grid districts
1795
+ '''
1796
+ buses_df , generators_df , lines_df , loads_df , transformer_df = initialize_component_dataframes ()
1797
+ components = {}
1798
+ networks = pd .DataFrame ()
1799
+ # open all switch connectors
1800
+ self .control_circuit_breakers (mode = 'open' )
1801
+ # start filling component dataframes
1802
+ for grid_district in self .mv_grid_districts ():
1803
+ gd_components , network_df , _ = fill_mvgd_component_dataframes (grid_district , buses_df , generators_df ,
1804
+ lines_df , loads_df , transformer_df , only_export_mv )
1805
+ if len (components ) == 0 :
1806
+ components = gd_components
1807
+ networks = network_df
1808
+ else :
1809
+ components = merge_two_dicts_of_dataframes (components , gd_components )
1810
+ networks = networks .append (network_df )
1811
+
1812
+ components ['Network' ] = network_df
1813
+ return components
1814
+
1815
+
1731
1816
def mv_routing (self , debug = False , animation = False ):
1732
1817
"""
1733
1818
Performs routing on all MV grids.
@@ -1825,21 +1910,6 @@ def mv_parametrize_grid(self, debug=False):
1825
1910
1826
1911
logger .info ('=====> MV Grids parametrized' )
1827
1912
1828
- def set_branch_ids (self ):
1829
- """
1830
- Performs generation and setting of ids
1831
- of branches for all MV and underlying LV grids.
1832
-
1833
- See Also
1834
- --------
1835
- ding0.core.network.grids.MVGridDing0.set_branch_ids
1836
- """
1837
-
1838
- for grid_district in self .mv_grid_districts ():
1839
- grid_district .mv_grid .set_branch_ids ()
1840
-
1841
- logger .info ('=====> Branch IDs set' )
1842
-
1843
1913
def set_circuit_breakers (self , debug = False ):
1844
1914
"""
1845
1915
Calculates the optimal position of the existing circuit breakers
@@ -1884,7 +1954,7 @@ def control_circuit_breakers(self, mode=None):
1884
1954
elif mode == 'close' :
1885
1955
logger .info ('=====> MV Circuit Breakers closed' )
1886
1956
1887
- def run_powerflow (self , session , method = 'onthefly' , export_pypsa = False , debug = False ):
1957
+ def run_powerflow (self , session = None , method = 'onthefly' , only_calc_mv = True , export_pypsa = False , debug = False , export_result_dir = None ):
1888
1958
"""
1889
1959
Performs power flow calculation for all MV grids
1890
1960
@@ -1915,20 +1985,22 @@ def run_powerflow(self, session, method='onthefly', export_pypsa=False, debug=Fa
1915
1985
export_pypsa_dir = repr (grid_district .mv_grid )
1916
1986
else :
1917
1987
export_pypsa_dir = None
1918
- grid_district .mv_grid .run_powerflow (session , method = 'db' ,
1988
+ grid_district .mv_grid .run_powerflow (method = 'db' ,
1919
1989
export_pypsa_dir = export_pypsa_dir ,
1920
- debug = debug )
1990
+ debug = debug ,
1991
+ export_result_dir = export_result_dir )
1921
1992
1922
1993
elif method == 'onthefly' :
1923
1994
for grid_district in self .mv_grid_districts ():
1924
1995
if export_pypsa :
1925
1996
export_pypsa_dir = repr (grid_district .mv_grid )
1926
1997
else :
1927
1998
export_pypsa_dir = None
1928
- grid_district .mv_grid .run_powerflow (session ,
1929
- method = 'onthefly' ,
1999
+ grid_district .mv_grid .run_powerflow (method = 'onthefly' ,
2000
+ only_calc_mv = only_calc_mv ,
1930
2001
export_pypsa_dir = export_pypsa_dir ,
1931
- debug = debug )
2002
+ debug = debug ,
2003
+ export_result_dir = export_result_dir )
1932
2004
1933
2005
def reinforce_grid (self ):
1934
2006
"""
0 commit comments