import numpy as np
import pandas as pd
[docs]
def get_q_sign_generator(reactive_power_mode):
"""
Get the sign of reactive power in generator sign convention.
In the generator sign convention the reactive power is negative in
inductive operation (`reactive_power_mode` is 'inductive') and positive
in capacitive operation (`reactive_power_mode` is 'capacitive').
Parameters
----------
reactive_power_mode : str
Possible options are 'inductive' and 'capacitive'.
Returns
--------
int
Sign of reactive power in generator sign convention.
"""
if reactive_power_mode.lower() == "inductive":
return -1
elif reactive_power_mode.lower() == "capacitive":
return 1
else:
raise ValueError(
"reactive_power_mode must either be 'capacitive' "
"or 'inductive' but is {}.".format(reactive_power_mode)
)
[docs]
def get_q_sign_load(reactive_power_mode):
"""
Get the sign of reactive power in load sign convention.
In the load sign convention the reactive power is positive in
inductive operation (`reactive_power_mode` is 'inductive') and negative
in capacitive operation (`reactive_power_mode` is 'capacitive').
Parameters
----------
reactive_power_mode : str
Possible options are 'inductive' and 'capacitive'.
Returns
--------
int
Sign of reactive power in load sign convention.
"""
if reactive_power_mode.lower() == "inductive":
return 1
elif reactive_power_mode.lower() == "capacitive":
return -1
else:
raise ValueError(
"reactive_power_mode must either be 'capacitive' "
"or 'inductive' but is {}.".format(reactive_power_mode)
)
[docs]
def fixed_cosphi(active_power, q_sign, power_factor):
"""
Calculates reactive power for a fixed cosphi operation.
Parameters
----------
active_power : :pandas:`pandas.DataFrame<DataFrame>`
Dataframe with active power time series. Columns of the dataframe are
names of the components and index of the dataframe are the time steps
reactive power is calculated for.
q_sign : :pandas:`pandas.Series<Series>` or int
`q_sign` defines whether the reactive power is positive or
negative and must either be -1 or +1. In case `q_sign` is given as a
series, the index must contain the same component names as given in
columns of parameter `active_power`.
power_factor : :pandas:`pandas.Series<Series>` or float
Ratio of real to apparent power.
In case `power_factor` is given as a series, the index must contain the
same component names as given in columns of parameter `active_power`.
Returns
-------
:pandas:`pandas.DataFrame<DataFrame>`
Dataframe with the same format as the `active_power` dataframe,
containing the reactive power.
"""
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.
Parameters
-----------
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
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'.
configs : :class:`~.tools.config.Config`
eDisGo configuration data.
Returns
--------
:pandas:`pandas.Series<Series>`
Series with default reactive power factor in case of fixed coshpi for each
component in index of `comp_df`.
"""
reactive_power_factor = configs["reactive_power_factor"]
comp_dict = _get_component_dict()
if component_type in comp_dict.keys():
comp = comp_dict[component_type]
# 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}"]
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'."
)
def _fixed_cosphi_default_reactive_power_sign(comp_df, component_type, configs):
"""
Gets fixed cosphi default value for sign of reactive power for each given component.
Parameters
-----------
comp_df : :pandas:`pandas.DataFrame<DataFrame>`
Dataframe with component names (in the index) of all components sign of
reactive power needs to be set. 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'.
configs : :class:`~.tools.config.Config`
eDisGo configuration data.
Returns
--------
:pandas:`pandas.Series<Series>`
Series with default sign of reactive power in case of fixed cosphi for each
component in index of `comp_df`.
"""
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,
}
if component_type in comp_dict.keys():
comp = comp_dict[component_type]
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}"]
)
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'."
)