Skip to content

Commit

Permalink
merge features/automatic_grid_expansion into features/#21-import-conn…
Browse files Browse the repository at this point in the history
…ect-genos
  • Loading branch information
nesnoj committed Aug 30, 2017
2 parents 18eea57 + e471acd commit 5012a4f
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 57 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@
doc/_html

# exclude egg-info
eDisGo.egg-info/
eDisGo.egg-info/
/edisgo/examples/Exemplary_PyPSA_bus_results.csv
/edisgo/examples/Exemplary_PyPSA_line_results.csv
14 changes: 10 additions & 4 deletions edisgo/data/import_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,12 +271,15 @@ def _build_mv_grid(dingo_grid, network):
grid=grid,
transformers=[Transformer(
grid=grid,
id=t.grid.id_db,
id='_'.join(['LV_station',
str(_.id_db),
'transformer',
str(count)]),
geom=_.geo_data,
voltage_op=t.v_level,
type=pd.Series(dict(
s=t.s_max_a, x=t.x, r=t.r))
) for t in _.transformers()])
) for (count, t) in enumerate(_.transformers(), 1)])
for _ in dingo_grid._graph.nodes()
if isinstance(_, LVStationDing0) and _ not in aggr_stations}
grid.graph.add_nodes_from(stations.values(), type='lv_station')
Expand All @@ -287,12 +290,15 @@ def _build_mv_grid(dingo_grid, network):
geom=dingo_grid.station().geo_data,
transformers=[Transformer(
grid=grid,
id=_.grid.id_db,
id='_'.join(['MV_station',
str(dingo_grid.station().id_db),
'transformer',
str(count)]),
geom=dingo_grid.station().geo_data,
voltage_op=_.v_level,
type=pd.Series(dict(
s=_.s_max_a, x=_.x, r=_.r)))
for _ in dingo_grid.station().transformers()])
for (count, _) in enumerate(dingo_grid.station().transformers())])
grid.graph.add_node(mv_station, type='mv_station')

# Merge node above defined above to a single dict
Expand Down
1 change: 0 additions & 1 deletion edisgo/examples/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,3 @@
# ToDo: wie halten wir fest, welche Betriebsmittel erneuert wurden, um hinterher Kosten berechnen zu können?
# ToDo: Parameter bei Komponenten einführen mit dem man feststellen kann, ob die Komponente bereits in einer ersten Maßnahme verstärkt oder ausgebaut wurde
# ToDo: config mit Standardbetriebsmitteln?

1 change: 1 addition & 0 deletions edisgo/grid/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def geom(self):
@property
def grid(self):
""":class:`~.grid.grids.MVGrid` or :class:`~.grid.grids.LVGrid` : The MV or LV grid this component belongs to"""
return self._grid

def __repr__(self):
return '_'.join([self.__class__.__name__, str(self._id)])
Expand Down
105 changes: 66 additions & 39 deletions edisgo/grid_expansion/check_tech_constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def check_line_load(network, results_lines, **kwargs):
# MV
for line in list(network.mv_grid.graph.graph_edges()):
s_max_th = (3 ** 0.5 * line['line']._type['U_n'] *
line['line']._type['I_max_th']) * \
line['line']._type['I_max_th']) * \
load_factor_mv_line * line['line']._quantity
try:
# check if maximum s_0 from power flow analysis exceeds allowed
Expand All @@ -77,7 +77,7 @@ def check_line_load(network, results_lines, **kwargs):
mw2kw / s_max_th)
except:
logger.debug('No results for line {} '.format(str(line)) +
'to check overloading.')
'to check overloading.')
# LV
for lv_grid in network.mv_grid.lv_grids:
for line in list(lv_grid.graph.graph_edges()):
Expand All @@ -93,7 +93,7 @@ def check_line_load(network, results_lines, **kwargs):
mw2kw / s_max_th)
except:
logger.debug('No results for line {} '.format(str(line)) +
'to check overloading.')
'to check overloading.')

if crit_lines:
logger.info('==> {} lines have load issues.'.format(
Expand All @@ -109,15 +109,15 @@ def check_station_load(network, results_lines, **kwargs):
----------
network: edisgo Network object
results_lines: pandas.DataFrame
power flow analysis results (pfa_nodes) from edisgo Results object
power flow analysis results (pfa_edges) from edisgo Results object
**kwargs:
load_factor_mv_lv_transformer: float (optional)
allowed load of MV/LV transformer in uninterrupted operation
Returns
-------
Dict of critical stations (edisgo Station objects)
Format: {station_1: overloading_1, ..., station_n: overloading_n},
Format: {station_1: overloading_1, ..., station_n: overloading_n}
Notes
-----
Expand Down Expand Up @@ -171,53 +171,80 @@ def check_station_load(network, results_lines, **kwargs):
return crit_stations


def check_voltage(grid, mode):
""" Checks for voltage stability issues at all nodes for MV or LV grid
def check_voltage(network, results_nodes, **kwargs):
""" Checks for voltage stability issues at all nodes for MV and LV grid
Parameters
----------
grid: GridDing0 object
mode: String
kind of grid ('MV' or 'LV')
network: edisgo Network object
results_nodes: pandas.DataFrame
power flow analysis results (pfa_nodes) from edisgo Results object
**kwargs:
mv_max_v_deviation: float (optional)
allowed voltage deviation in MV grid
lv_max_v_deviation: float (optional)
allowed voltage deviation in LV grid
Returns
-------
List of critical nodes, sorted descending by voltage difference
Format: {grid_1: [node_1A, node_1B, ...], ..., grid_n: [node_nA, ...]}
Notes
-----
The voltage is checked against a max. allowed voltage deviation.
"""

# crit_nodes = {}
#
# if mode == 'MV':
# # load max. voltage difference for load and feedin case
# mv_max_v_level_lc_diff_normal = float(cfg_ding0.get('mv_routing_tech_constraints',
# 'mv_max_v_level_lc_diff_normal'))
# mv_max_v_level_fc_diff_normal = float(cfg_ding0.get('mv_routing_tech_constraints',
# 'mv_max_v_level_fc_diff_normal'))
#
# # check nodes' voltages
# voltage_station = grid._station.voltage_res
# for node in grid.graph_nodes_sorted():
# try:
# # compare node's voltage with max. allowed voltage difference for load and feedin case
# if (abs(voltage_station[0] - node.voltage_res[0]) > mv_max_v_level_lc_diff_normal) or\
# (abs(voltage_station[1] - node.voltage_res[1]) > mv_max_v_level_fc_diff_normal):
#
# crit_nodes[node] = {'node': node,
# 'v_diff': max([abs(v2-v1) for v1, v2 in zip(node.voltage_res, voltage_station)])}
# except:
# pass
#
# elif mode == 'LV':
# raise NotImplementedError
#
# if crit_nodes:
# logger.info('==> {} nodes have voltage issues.'.format(len(crit_nodes)))
#
# return [_['node'] for _ in sorted(crit_nodes.values(), key=lambda _: _['v_diff'], reverse=True)]
# ToDo: delta_U wird auch benötigt, deshalb crit_nodes als dict mit series
# ToDo: crit_nodes innerhalb einer Series sortieren
crit_nodes = {}

# load max. voltage deviation for load and feedin case
mv_max_v_deviation = kwargs.get('mv_max_v_deviation', 0.1)
lv_max_v_deviation = kwargs.get('lv_max_v_deviation', 0.1)

# check nodes' voltages
# MV
voltage_station = network.mv_grid.station.transformers[0]._voltage_op
for node in network.mv_grid.graph.nodes():
try:
# check if maximum deviation in v_mag_pu exceeds allowed deviation
if (max(results_nodes.loc[node, 'v_mag_pu']) >
1 + mv_max_v_deviation or
min(results_nodes.loc[
node, 'v_mag_pu']) < 1 - mv_max_v_deviation):
try:
crit_nodes[network.mv_grid].append(node)
except:
crit_nodes[network.mv_grid] = [node]
except:
logger.debug('No results for node {} '.format(str(node)) +
'to check overvoltage.')

# LV
for lv_grid in network.mv_grid.lv_grids:
for node in lv_grid.graph.nodes():
try:
# check if maximum deviation in v_mag_pu exceeds allowed
# deviation
if (max(results_nodes.loc[node, 'v_mag_pu']) >
1 + lv_max_v_deviation or
min(results_nodes.loc[
node, 'v_mag_pu']) < 1 - lv_max_v_deviation):
try:
crit_nodes[lv_grid].append(node)
except:
crit_nodes[lv_grid] = [node]
except:
logger.debug('No results for node {} '.format(str(node)) +
'in LV grid {} '.format(str(lv_grid)) +
'to check overvoltage.')

if crit_nodes:
logger.info(
'==> {} nodes have voltage issues.'.format(len(crit_nodes)))

return crit_nodes


def get_critical_voltage_at_nodes(grid):
Expand Down
7 changes: 4 additions & 3 deletions edisgo/grid_expansion/reinforce_grid.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .check_tech_constraints import check_line_load, check_station_load
#check_voltage, get_critical_line_loading, get_critical_voltage_at_nodes
from .check_tech_constraints import check_line_load, check_station_load, \
check_voltage #, get_critical_line_loading, get_critical_voltage_at_nodes
from .reinforce_measures import reinforce_branches_current, \
reinforce_branches_voltage, extend_distribution_substation
import logging
Expand Down Expand Up @@ -80,6 +80,7 @@ def reinforce_grid(network, results):
crit_lines = {overloaded_line: 2.3}

# do reinforcement
# ToDo: erst MV dann LV
reinforce_branches_current(crit_lines)

# if lines have been reinforced: run PF again and check if all
Expand All @@ -92,7 +93,7 @@ def reinforce_grid(network, results):

# STEP 3: reinforce branches due to voltage problems

# crit_nodes = check_voltage(grid, mode)
#crit_nodes = check_voltage(network, results.pfa_nodes)
# crit_nodes_count_prev_step = len(crit_nodes)

# ToDo: get nodes with overvoltage (als dict mit grid und liste von Knoten {GridXY: [NodeA, NodeB]})
Expand Down
18 changes: 9 additions & 9 deletions edisgo/grid_expansion/reinforce_measures.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ def reinforce_branches_voltage(grid, crit_nodes):
References
----------
.. [1] "Verteilnetzstudie für das Land Baden-Württemberg"
.. [2] "Technische Richtlinie Erzeugungsanlagen am Mittelspannungsnetz -
Richtlinie für Anschluss und Parallelbetrieb von
Erzeugungsanlagen am Mittelspannungsnetz, Juni 2008"
"""

# ToDo: gilt Methodik auch für die MS?
Expand Down Expand Up @@ -177,15 +181,11 @@ def reinforce_branches_voltage(grid, crit_nodes):
# if critical line is not yet a standard line check if one or
# several standard lines are needed
else:
# check if new standard line might solve the voltage
# problem
# ToDo: welche Kenngröße verwenden?
if crit_line._type['I_max_th'] < standard_line['I_max_th']:
crit_line._type = standard_line.copy()
else:
# ToDo: wie viele Standardbetriebsmittel?
crit_line._type = standard_line.copy()
crit_line._quantity = 2
# number of parallel standard lines could be calculated
# following [2] p.103, for now number of parallel standard
# lines is iterated
crit_line._type = standard_line.copy()
crit_line._quantity = 1

# if node_2_3 is not a representative, disconnect line
else:
Expand Down

0 comments on commit 5012a4f

Please sign in to comment.