Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ repos:
rev: 23.3.0
hooks:
- id: black
- repo: https://github.com/pycqa/flake8
rev: 6.0.0
hooks:
- id: flake8
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
Expand All @@ -22,6 +18,10 @@ repos:
rev: v3.4.0
hooks:
- id: pyupgrade
- repo: https://github.com/pycqa/flake8
rev: 6.0.0
hooks:
- id: flake8
#- repo: https://github.com/pycqa/pylint
# rev: pylint-2.6.0
# hooks:
Expand Down
27 changes: 27 additions & 0 deletions edisgo/flex_opt/heat_pump_operation.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import copy
import logging

import pandas as pd
Expand Down Expand Up @@ -31,11 +32,37 @@ def operating_strategy(
if heat_pump_names is None:
heat_pump_names = edisgo_obj.heat_pump.cop_df.columns

missing = set(heat_pump_names) - set(edisgo_obj.topology.loads_df.index)
if missing:
logger.warning(
f"The following heat pumps are are in the heat pump class but not yet "

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove double "are"

f"integrated into the topology class. Therefore, their maximum capacity "
f"cannot be considered in the operating strategies. {missing=}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a note similar to "For better results, please integrate these heat pumps into the topology before running this function.".

)

if strategy == "uncontrolled":
ts = (
edisgo_obj.heat_pump.heat_demand_df.loc[:, heat_pump_names]
/ edisgo_obj.heat_pump.cop_df.loc[:, heat_pump_names]
)

ts_prev = copy.deepcopy(ts)

# clips heat pump load at maximum level
in_topology = list(set(heat_pump_names) - set(missing))

ts_clipped = ts[in_topology].clip(
upper=edisgo_obj.topology.loads_df.p_set[in_topology].values
)
ts[in_topology] = ts_clipped[in_topology]

clipped = ts.eq(ts_prev).all()[lambda x: ~x].index

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be more readable py using pandas.series.ne

logger.warning(
f"Heat pump power at {clipped} was "
f"clipped at its maximum capacity. The heat demand at this bus "
f"should be covered by additional heat sources."
)

edisgo_obj.timeseries.add_component_time_series(
"loads_active_power",
ts,
Expand Down
1 change: 1 addition & 0 deletions edisgo/io/heat_pump_import.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ def _get_central_heat_pump_or_resistive_heaters(carrier):
<= edisgo_object.config["grid_connection"]["upper_limit_voltage_level_4"],
)
df = pd.read_sql(query.statement, engine, index_col=None)
# Alternativ Code einfügen, falls Tabelle leer ist

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this temp comment

if not df.empty:
# get geom of heat bus, weather_cell_id, district_heating_id and area_id
srid_etrago_bus = db.get_srid_of_db_table(session, egon_etrago_bus.geom)
Expand Down
1 change: 0 additions & 1 deletion edisgo/network/timeseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -2120,7 +2120,6 @@ def add_component_time_series(self, df_name, ts_new):
:attr:`~.network.timeseries.TimeSeries.generators_active_power`.
ts_new : :pandas:`pandas.DataFrame<DataFrame>`
Dataframe with new time series to add to existing time series dataframe.

"""
# drop possibly already existing time series
self.drop_component_time_series(df_name, ts_new.columns)
Expand Down
2 changes: 1 addition & 1 deletion examples/edisgo_simple_example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -892,7 +892,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.5"
"version": "3.10.16"
},
"toc": {
"base_numbering": 1,
Expand Down
44 changes: 42 additions & 2 deletions examples/electromobility_example.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
"outputs": [],
"source": [
"# interactive matplotlib\n",
"%matplotlib notebook"
"%matplotlib ipympl"
]
},
{
Expand Down Expand Up @@ -407,6 +407,28 @@
" * If the power rating of the charging point is <= 4.5 MVA, it is connected to the nearest grid connection point or cable. If a cable is selected, the line is cut at the point closest to the charging station and a new branch tee is added to which the charging station is connected."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5997b187-e1dd-4a55-a13b-f665f5fa5921",
"metadata": {},
"outputs": [],
"source": [
"simbev_example_data_path = os.path.join(\n",
" os.path.expanduser(\"~\"), \".edisgo\", \"simbev_example_data\"\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "feb0cc6b-45ce-46b1-ad7e-ff1095aad480",
"metadata": {},
"outputs": [],
"source": [
"simbev_example_data_path"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down Expand Up @@ -756,6 +778,24 @@
"\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "25d6d80a-448f-4cac-a01a-d598958a7768",
"metadata": {},
"outputs": [],
"source": [
"python3 -V"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3a833dd8-7e0b-4ed2-b144-a877c3dda924",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
Expand All @@ -774,7 +814,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.18"
"version": "3.10.16"
},
"toc": {
"base_numbering": 1,
Expand Down
63 changes: 47 additions & 16 deletions tests/flex_opt/test_heat_pump_operation.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import pandas as pd
import pytest

from numpy.random import default_rng

from edisgo import EDisGo
from edisgo.flex_opt.heat_pump_operation import operating_strategy

Expand All @@ -9,23 +11,45 @@ class TestHeatPumpOperation:
@classmethod
def setup_class(self):
self.timeindex = pd.date_range("1/1/2011 12:00", periods=2, freq="H")

self.edisgo = EDisGo(
ding0_grid=pytest.ding0_test_network_path, timeindex=self.timeindex
)

# insert heat pumps into topology
rng = default_rng(1)
number_of_heat_pumps = 2
self.name = []
for i in range(number_of_heat_pumps):
self.name.append(
self.edisgo.add_component(
comp_type="load",
bus=rng.choice(self.edisgo.topology.buses_df.index, size=1)[0],
p_set=0.43,
type="heat_pump",
)
)

# add one addtional hp that is not in the topology
self.name.append("hp" + str(len(self.name) + 1))

self.cop = pd.DataFrame(
data={
"hp1": [5.0, 6.0],
"hp2": [7.0, 8.0],
self.name[0]: [5.0, 6.0],
self.name[1]: [7.0, 8.0],
self.name[2]: [7.2, 6.7],
},
index=self.timeindex,
)
self.heat_demand = pd.DataFrame(
data={
"hp1": [1.0, 2.0],
"hp2": [3.0, 4.0],
self.name[0]: [1.0, 4.0],
self.name[1]: [3.0, 4.0],
self.name[2]: [2.0, 3.0],
},
index=self.timeindex,
)
self.edisgo = EDisGo(
ding0_grid=pytest.ding0_test_network_path, timeindex=self.timeindex
)

self.edisgo.heat_pump.cop_df = self.cop
self.edisgo.heat_pump.heat_demand_df = self.heat_demand

Expand All @@ -35,8 +59,9 @@ def test_operating_strategy(self):

hp_ts = pd.DataFrame(
data={
"hp1": [0.2, 1 / 3],
"hp2": [3 / 7, 0.5],
self.name[0]: [0.2, 0.43],
self.name[1]: [3 / 7, 0.43],
self.name[2]: [2 / 7.2, 3 / 6.7],
},
index=self.timeindex,
)
Expand All @@ -46,8 +71,9 @@ def test_operating_strategy(self):
)
hp_ts = pd.DataFrame(
data={
"hp1": [0.0, 0.0],
"hp2": [0.0, 0.0],
self.name[0]: [0.0, 0.0],
self.name[1]: [0.0, 0.0],
self.name[2]: [0.0, 0.0],
},
index=self.timeindex,
)
Expand All @@ -58,13 +84,18 @@ def test_operating_strategy(self):

# test with providing heat pump names
timestep = self.timeindex[0]
self.edisgo.heat_pump.heat_demand_df.at[timestep, "hp1"] = 0.0
self.edisgo.heat_pump.heat_demand_df.at[timestep, "hp2"] = 0.0
self.edisgo.heat_pump.heat_demand_df.at[timestep, self.name[0]] = 0.0
self.edisgo.heat_pump.heat_demand_df.at[timestep, self.name[1]] = 0.0

operating_strategy(self.edisgo, heat_pump_names=["hp1"])
operating_strategy(self.edisgo, heat_pump_names=[self.name[0]])

assert self.edisgo.timeseries.loads_active_power.at[timestep, "hp1"] == 0.0
assert self.edisgo.timeseries.loads_active_power.at[timestep, "hp2"] == 3 / 7
assert (
self.edisgo.timeseries.loads_active_power.at[timestep, self.name[0]] == 0.0
)
assert (
self.edisgo.timeseries.loads_active_power.at[timestep, self.name[1]]
== 3 / 7
)

# test error raising
msg = "Heat pump operating strategy dummy is not a valid option."
Expand Down