Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

384 bug voltage drop should be considered when selecting cable to connect new components #411

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
f9972bc
Update select_cable to consider voltage drop constraints
joda9 Jul 22, 2024
3dc762b
adding test for cable voltage drop
joda9 Jul 22, 2024
9d0411a
Adding default values for adding new components
joda9 Jul 22, 2024
b8a8baa
Update default voltage deviation values for new components
joda9 Jul 22, 2024
bab29bc
Update default voltage deviation values for new components
joda9 Jul 24, 2024
f31886a
Refactor calculate_voltage_drop function for clarity and readability
joda9 Jul 24, 2024
8adc372
update tests select cables
joda9 Jul 24, 2024
a37c4d5
use "difference" instead of "drop" in the variable names
joda9 Jul 24, 2024
1b2301a
source of formula added
joda9 Jul 25, 2024
a0f01fb
specified source for values
joda9 Jul 30, 2024
3a23e5e
update tools to consistency variable names and minor fixes
joda9 Jul 30, 2024
6e3cd06
adding tests for cable_selection
joda9 Jul 30, 2024
8404748
adding component type to select cable function
joda9 Aug 2, 2024
f1a02e2
adding component type to tests
joda9 Aug 2, 2024
9c9f456
defining return values
joda9 Aug 5, 2024
bd9c87e
change name voltage_diff_pu
joda9 Aug 5, 2024
803d796
adding tests for coverage
joda9 Aug 5, 2024
2115254
Refactor voltage difference calculation to use per unit (pu) instead …
joda9 Aug 5, 2024
e68b601
Refactor voltage difference calculation to use per unit (pu) instead …
joda9 Aug 5, 2024
93e3592
Rename config parameters to make wording more consistent
birgits Aug 7, 2024
59f12c8
Minor docstring fix
birgits Aug 7, 2024
ace46a9
Simplify getting config values
birgits Aug 7, 2024
aa49064
Adapt calculate_voltage_diff_pu_per_line to have q_sign and power_fac…
birgits Aug 8, 2024
0d1683d
Change function calculate_voltage_diff_pu_per_line_from_type to have …
birgits Aug 8, 2024
095e3d0
Change function select_cable to retrieve reactive power behavior from…
birgits Aug 8, 2024
2875aa7
Adapt tests to changes
birgits Aug 8, 2024
ec36c0b
Consider voltage drop when selecting suitable cable in connect functions
birgits Aug 8, 2024
a49d907
Adapt test that is now failing because voltage drop is too high to fi…
birgits Aug 8, 2024
4552729
Add changes to whatsnew
birgits Aug 8, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
40 changes: 20 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 Down
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
Loading
Loading