Skip to content

Commit

Permalink
Merge branch '413-feature-improve-connection-of-charging-points' of g…
Browse files Browse the repository at this point in the history
…ithub.com:openego/eDisGo into 413-feature-improve-connection-of-charging-points
  • Loading branch information
joda9 committed Aug 21, 2024
2 parents 5e72bcc + 62b92ea commit a324890
Show file tree
Hide file tree
Showing 25 changed files with 847 additions and 240 deletions.
1 change: 1 addition & 0 deletions doc/whatsnew/v0-3-0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ Changes
* Added a new reinforcement method that separate lv grids when the overloading is very high `#380 <https://github.com/openego/eDisGo/pull/380>`_
* Move function to assign feeder to Topology class and add methods to the Grid class to get information on the feeders `#360 <https://github.com/openego/eDisGo/pull/360>`_
* Added a storage operation strategy where the storage is charged when PV feed-in is higher than electricity demand of the household and discharged when electricity demand exceeds PV generation `#386 <https://github.com/openego/eDisGo/pull/386>`_
* Added an estimation of the voltage deviation over a cable when selecting a suitable cable to connect a new component `#411 <https://github.com/openego/eDisGo/pull/411>`_
5 changes: 5 additions & 0 deletions edisgo/config/config_grid_default.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ upper_limit_voltage_level_6 = 0.2
upper_limit_voltage_level_5 = 5.5
upper_limit_voltage_level_4 = 20.0

# from VDE-AR-N 4100 (VDE-AR-N 4100) Anwendungsregel: 2019-04, table 3
lv_max_voltage_deviation = 0.03
# from VDE-AR-N 4110 (VDE-AR-N 4110) Anwendungsregel: 2023-09, 5.3.2 Zulässige Spannungsänderung
mv_max_voltage_deviation = 0.02

[disconnecting_point]

# Positioning of disconnecting points: Can be position at location of most
Expand Down
42 changes: 22 additions & 20 deletions edisgo/config/config_timeseries_default.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -88,33 +88,33 @@ lv_load_case_hp = 1.0
# ===========================
# power factors used to generate reactive power time series for loads and generators

mv_gen = 0.9
mv_load = 0.9
mv_storage = 0.9
mv_cp = 1.0
mv_hp = 1.0
lv_gen = 0.95
lv_load = 0.95
lv_storage = 0.95
lv_cp = 1.0
lv_hp = 1.0
mv_generator = 0.9
mv_conventional_load = 0.9
mv_storage_unit = 0.9
mv_charging_point = 1.0
mv_heat_pump = 1.0
lv_generator = 0.95
lv_conventional_load = 0.95
lv_storage_unit = 0.95
lv_charging_point = 1.0
lv_heat_pump = 1.0

[reactive_power_mode]

# power factor modes
# ===========================
# power factor modes used to generate reactive power time series for loads and generators

mv_gen = inductive
mv_load = inductive
mv_storage = inductive
mv_cp = inductive
mv_hp = inductive
lv_gen = inductive
lv_load = inductive
lv_storage = inductive
lv_cp = inductive
lv_hp = inductive
mv_generator = inductive
mv_conventional_load = inductive
mv_storage_unit = inductive
mv_charging_point = inductive
mv_heat_pump = inductive
lv_generator = inductive
lv_conventional_load = inductive
lv_storage_unit = inductive
lv_charging_point = inductive
lv_heat_pump = inductive

[demandlib]

Expand All @@ -129,6 +129,8 @@ week_day = 0.8
week_night = 0.6
weekend_day = 0.6
weekend_night = 0.6
holiday_day = 0.6
holiday_night = 0.6
# tuple specifying the beginning/end of a workday (e.g. 18:00)
day_start = 6:00
day_end = 22:00
66 changes: 27 additions & 39 deletions edisgo/flex_opt/q_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,22 +92,6 @@ def fixed_cosphi(active_power, q_sign, power_factor):
return active_power * q_sign * np.tan(np.arccos(power_factor))


def _get_component_dict():
"""
Helper function to translate from component type term used in function to the one
used in the config files.
"""
comp_dict = {
"generators": "gen",
"storage_units": "storage",
"conventional_loads": "load",
"charging_points": "cp",
"heat_pumps": "hp",
}
return comp_dict


def _fixed_cosphi_default_power_factor(comp_df, component_type, configs):
"""
Gets fixed cosphi default reactive power factor for each given component.
Expand All @@ -116,15 +100,15 @@ def _fixed_cosphi_default_power_factor(comp_df, component_type, configs):
-----------
comp_df : :pandas:`pandas.DataFrame<DataFrame>`
Dataframe with component names (in the index) of all components
reactive power factor needs to be set. Only required column is
reactive power factor needs to be set for. Only required column is
column 'voltage_level', giving the voltage level the component is in (the
voltage level can be set using the function
:func:`~.tools.tools.assign_voltage_level_to_component`).
All components must have the same `component_type`.
component_type : str
The component type determines the reactive power factor and mode used.
Possible options are 'generators', 'storage_units', 'conventional_loads',
'charging_points', and 'heat_pumps'.
Possible options are 'generator', 'storage_unit', 'conventional_load',
'charging_point', and 'heat_pump'.
configs : :class:`~.tools.config.Config`
eDisGo configuration data.
Expand All @@ -136,22 +120,28 @@ def _fixed_cosphi_default_power_factor(comp_df, component_type, configs):
"""
reactive_power_factor = configs["reactive_power_factor"]
comp_dict = _get_component_dict()

if component_type in comp_dict.keys():
comp = comp_dict[component_type]
allowed_types = [
"generator",
"storage_unit",
"conventional_load",
"charging_point",
"heat_pump",
]
if component_type in allowed_types:
# write series with power factor for each component
power_factor = pd.Series(index=comp_df.index, dtype=float)
for voltage_level in comp_df.voltage_level.unique():
cols = comp_df.index[comp_df.voltage_level == voltage_level]
if len(cols) > 0:
power_factor[cols] = reactive_power_factor[f"{voltage_level}_{comp}"]
power_factor[cols] = reactive_power_factor[
f"{voltage_level}_{component_type}"
]
return power_factor
else:
raise ValueError(
"Given 'component_type' is not valid. Valid options are "
"'generators','storage_units', 'conventional_loads', 'charging_points', "
"and 'heat_pumps'."
"'generator', 'storage_unit', 'conventional_load', 'charging_point', "
"and 'heat_pump'."
)


Expand All @@ -170,8 +160,8 @@ def _fixed_cosphi_default_reactive_power_sign(comp_df, component_type, configs):
All components must have the same `component_type`.
component_type : str
The component type determines the reactive power factor and mode used.
Possible options are 'generators', 'storage_units', 'conventional_loads',
'charging_points', and 'heat_pumps'.
Possible options are 'generator', 'storage_unit', 'conventional_load',
'charging_point', and 'heat_pump'.
configs : :class:`~.tools.config.Config`
eDisGo configuration data.
Expand All @@ -183,30 +173,28 @@ def _fixed_cosphi_default_reactive_power_sign(comp_df, component_type, configs):
"""
reactive_power_mode = configs["reactive_power_mode"]
comp_dict = _get_component_dict()
q_sign_dict = {
"generators": get_q_sign_generator,
"storage_units": get_q_sign_generator,
"conventional_loads": get_q_sign_load,
"charging_points": get_q_sign_load,
"heat_pumps": get_q_sign_load,
"generator": get_q_sign_generator,
"storage_unit": get_q_sign_generator,
"conventional_load": get_q_sign_load,
"charging_point": get_q_sign_load,
"heat_pump": get_q_sign_load,
}

if component_type in comp_dict.keys():
comp = comp_dict[component_type]
if component_type in q_sign_dict.keys():
get_q_sign = q_sign_dict[component_type]
# write series with power factor for each component
q_sign = pd.Series(index=comp_df.index, dtype=float)
for voltage_level in comp_df.voltage_level.unique():
cols = comp_df.index[comp_df.voltage_level == voltage_level]
if len(cols) > 0:
q_sign[cols] = get_q_sign(
reactive_power_mode[f"{voltage_level}_{comp}"]
reactive_power_mode[f"{voltage_level}_{component_type}"]
)
return q_sign
else:
raise ValueError(
"Given 'component_type' is not valid. Valid options are "
"'generators','storage_units', 'conventional_loads', 'charging_points', "
"and 'heat_pumps'."
"'generator', 'storage_unit', 'conventional_load', 'charging_point', "
"and 'heat_pump'."
)
39 changes: 18 additions & 21 deletions edisgo/io/powermodels_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ def _build_gen(edisgo_obj, psa_net, pm, flexible_storage_units, s_base):
gen.bus[gen_i],
flexible_storage_units=flexible_storage_units,
)
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "gen")
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "generator")
q = [
sign * np.tan(np.arccos(pf)) * gen.p_nom[gen_i],
sign * np.tan(np.arccos(pf)) * gen.p_nom_min[gen_i],
Expand Down Expand Up @@ -704,7 +704,7 @@ def _build_gen(edisgo_obj, psa_net, pm, flexible_storage_units, s_base):
psa_net.storage_units.bus.loc[inflexible_storage_units[stor_i]],
flexible_storage_units=flexible_storage_units,
)
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "storage")
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "storage_unit")
p_g = max(
[
psa_net.storage_units_t.p_set[inflexible_storage_units[stor_i]][0],
Expand Down Expand Up @@ -837,7 +837,7 @@ def _build_branch(edisgo_obj, psa_net, pm, flexible_storage_units, s_base):
flexible_storage_units=flexible_storage_units,
)
# retrieve power factor from config
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "storage")
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "storage_unit")

pm["branch"][str(stor_i + len(branches.index) + 1)] = {
"name": "bss_branch_" + str(stor_i + 1),
Expand Down Expand Up @@ -919,22 +919,22 @@ def _build_load(
edisgo_obj.topology.loads_df.loc[loads_df.index[load_i]].type
== "conventional_load"
):
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "load")
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "conventional_load")
elif (
edisgo_obj.topology.loads_df.loc[loads_df.index[load_i]].type == "heat_pump"
):
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "hp")
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "heat_pump")
elif (
edisgo_obj.topology.loads_df.loc[loads_df.index[load_i]].type
== "charging_point"
):
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "cp")
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "charging_point")
else:
logger.warning(
"No type specified for load {}. Power factor and sign will"
"be set for conventional load.".format(loads_df.index[load_i])
)
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "load")
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "conventional_load")
p_d = psa_net.loads_t.p_set[loads_df.index[load_i]]
q_d = psa_net.loads_t.q_set[loads_df.index[load_i]]
pm["load"][str(load_i + 1)] = {
Expand All @@ -955,7 +955,7 @@ def _build_load(
psa_net.storage_units.bus.loc[inflexible_storage_units[stor_i]],
flexible_storage_units=flexible_storage_units,
)
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "storage")
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "storage_unit")
p_d = -min(
[
psa_net.storage_units_t.p_set[inflexible_storage_units[stor_i]][0],
Expand Down Expand Up @@ -1036,7 +1036,7 @@ def _build_battery_storage(
flexible_storage_units=flexible_storage_units,
)
# retrieve power factor from config
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "storage")
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "storage_unit")
e_max = (
psa_net.storage_units.p_nom.loc[flexible_storage_units[stor_i]]
* psa_net.storage_units.max_hours.loc[flexible_storage_units[stor_i]]
Expand Down Expand Up @@ -1151,7 +1151,7 @@ def _build_electromobility(edisgo_obj, psa_net, pm, s_base, flexible_cps):
eta = edisgo_obj.electromobility.simbev_config_df.eta_cp.values[0]
except IndexError:
eta = 0.9
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "cp")
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "charging_point")
q = (
sign
* np.tan(np.arccos(pf))
Expand Down Expand Up @@ -1218,7 +1218,7 @@ def _build_heatpump(psa_net, pm, edisgo_obj, s_base, flexible_hps):
for hp_i in np.arange(len(heat_df.index)):
idx_bus = _mapping(psa_net, edisgo_obj, heat_df.bus[hp_i])
# retrieve power factor and sign from config
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "hp")
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "heat_pump")
q = sign * np.tan(np.arccos(pf)) * heat_df.p_set[hp_i]
p_d = heat_df2[heat_df.index[hp_i]]
pm["heatpumps"][str(hp_i + 1)] = {
Expand Down Expand Up @@ -1446,7 +1446,7 @@ def _build_dsm(edisgo_obj, psa_net, pm, s_base, flexible_loads):
for dsm_i in np.arange(len(dsm_df.index)):
idx_bus = _mapping(psa_net, edisgo_obj, dsm_df.bus[dsm_i])
# retrieve power factor and sign from config
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "load")
pf, sign = _get_pf(edisgo_obj, pm, idx_bus, "conventional_load")
p_max = edisgo_obj.dsm.p_max[dsm_df.index[dsm_i]]
p_min = edisgo_obj.dsm.p_min[dsm_df.index[dsm_i]]
e_min = edisgo_obj.dsm.e_min[dsm_df.index[dsm_i]]
Expand Down Expand Up @@ -2053,26 +2053,23 @@ def _get_pf(edisgo_obj, pm, idx_bus, kind):
idx_bus : int
Bus index from PowerModels bus dictionary.
kind : str
Must be one of ["gen", "load", "storage", "hp", "cp"].
Must be one of ["generator", "conventional_load", "storage_unit", "heat_pump",
"charging_point"].
Returns
-------
(float, int)
"""
grid_level = pm["bus"][str(idx_bus)]["grid_level"]
pf = edisgo_obj.config._data["reactive_power_factor"][
"{}_{}".format(grid_level, kind)
]
sign = edisgo_obj.config._data["reactive_power_mode"][
"{}_{}".format(grid_level, kind)
]
if kind in ["gen", "storage"]:
pf = edisgo_obj.config["reactive_power_factor"]["{}_{}".format(grid_level, kind)]
sign = edisgo_obj.config["reactive_power_mode"]["{}_{}".format(grid_level, kind)]
if kind in ["generator", "storage_unit"]:
if sign == "inductive":
sign = -1
else:
sign = 1
elif kind in ["load", "hp", "cp"]:
elif kind in ["conventional_load", "heat_pump", "charging_point"]:
if sign == "inductive":
sign = 1
else:
Expand Down
4 changes: 4 additions & 0 deletions edisgo/io/timeseries_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,10 @@ def load_time_series_demandlib(edisgo_obj, timeindex=None):
"day": edisgo_obj.config["demandlib"]["weekend_day"],
"night": edisgo_obj.config["demandlib"]["weekend_night"],
},
"holiday": {
"day": edisgo_obj.config["demandlib"]["holiday_day"],
"night": edisgo_obj.config["demandlib"]["holiday_night"],
},
},
)

Expand Down
16 changes: 4 additions & 12 deletions edisgo/network/grids.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,20 +90,19 @@ def graph(self):
@property
def geopandas(self):
"""
Returns components as :geopandas:`GeoDataFrame`\\ s
Returns components as :geopandas:`GeoDataFrame`\\ s.
Returns container with :geopandas:`GeoDataFrame`\\ s containing all
georeferenced components within the grid.
Returns
-------
:class:`~.tools.geopandas_helper.GeoPandasGridContainer` or \
list(:class:`~.tools.geopandas_helper.GeoPandasGridContainer`)
:class:`~.tools.geopandas_helper.GeoPandasGridContainer`
Data container with GeoDataFrames containing all georeferenced components
within the grid(s).
within the grid.
"""
return to_geopandas(self)
return to_geopandas(self, srid=self.edisgo_obj.topology.grid_district["srid"])

@property
def station(self):
Expand Down Expand Up @@ -650,10 +649,3 @@ def draw(
else:
plt.savefig(filename, dpi=150, bbox_inches="tight", pad_inches=0.1)
plt.close()

@property
def geopandas(self):
"""
TODO: Remove this as soon as LVGrids are georeferenced
"""
raise NotImplementedError("LV Grids are not georeferenced yet.")
Loading

0 comments on commit a324890

Please sign in to comment.