Note
You can download this example as a Jupyter notebook or start it in interactive mode.
Wind Turbine combined with Heat Pump and Water Tank#
In this example the heat demand is supplied by a wind turbine in combination with a heat pump and a water tank that stores hot water with a standing loss.
[1]:
import pandas as pd
import pypsa
[2]:
network = pypsa.Network()
network.set_snapshots(pd.date_range("2016-01-01 00:00", "2016-01-01 03:00", freq="H"))
network.add("Bus", "0", carrier="AC")
network.add("Bus", "0 heat", carrier="heat")
network.add("Carrier", "wind")
network.add("Carrier", "heat")
network.add(
"Generator",
"wind turbine",
bus="0",
carrier="wind",
p_nom_extendable=True,
p_max_pu=[0.0, 0.2, 0.7, 0.4],
capital_cost=500,
)
network.add("Load", "heat demand", bus="0 heat", p_set=20.0)
# NB: Heat pump has changing efficiency (properly the Coefficient of Performance, COP)
# due to changing ambient temperature
network.add(
"Link",
"heat pump",
bus0="0",
bus1="0 heat",
efficiency=[2.5, 3.0, 3.2, 3.0],
capital_cost=1000,
p_nom_extendable=True,
)
network.add(
"Store",
"water tank",
bus="0 heat",
e_cyclic=True,
e_nom_extendable=True,
standing_loss=0.01,
)
/tmp/ipykernel_3054/743167227.py:2: FutureWarning: 'H' is deprecated and will be removed in a future version, please use 'h' instead.
network.set_snapshots(pd.date_range("2016-01-01 00:00", "2016-01-01 03:00", freq="H"))
[2]:
Index(['water tank'], dtype='object')
[3]:
network.optimize()
WARNING:pypsa.consistency:The following buses have carriers which are not defined:
Index(['0'], dtype='object', name='Bus')
WARNING:pypsa.consistency:The following links have carriers which are not defined:
Index(['heat pump'], dtype='object', name='Link')
WARNING:pypsa.consistency:The following buses have carriers which are not defined:
Index(['0'], dtype='object', name='Bus')
WARNING:pypsa.consistency:The following links have carriers which are not defined:
Index(['heat pump'], dtype='object', name='Link')
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/envs/v0.31.0/lib/python3.12/site-packages/linopy/common.py:147: UserWarning: coords for dimension(s) ['Generator'] is not aligned with the pandas object. Previously, the indexes of the pandas were ignored and overwritten in these cases. Now, the pandas object's coordinates are taken considered for alignment.
warn(
INFO:linopy.model: Solve problem using Highs solver
INFO:linopy.io: Writing time: 0.08s
INFO:linopy.solvers:Log file at /tmp/highs.log
INFO:linopy.constants: Optimization successful:
Status: ok
Termination condition: optimal
Solution: 19 primals, 40 duals
Objective: 2.35e+04
Solver model: available
Solver message: optimal
INFO:pypsa.optimization.optimize:The shadow-prices of the constraints Generator-ext-p-lower, Generator-ext-p-upper, Link-ext-p-lower, Link-ext-p-upper, Store-ext-e-lower, Store-ext-e-upper, Store-energy_balance were not assigned to the network.
Running HiGHS 1.7.2 (git hash: 184e327): Copyright (c) 2024 HiGHS under MIT licence terms
Coefficient ranges:
Matrix [2e-01, 3e+00]
Cost [5e+02, 1e+03]
Bound [0e+00, 0e+00]
RHS [2e+01, 2e+01]
Presolving model
9 rows, 8 cols, 21 nonzeros 0s
9 rows, 8 cols, 21 nonzeros 0s
Presolve : Reductions: rows 9(-31); columns 8(-11); elements 21(-49)
Solving the presolved LP
Using EKK dual simplex solver - serial
Iteration Objective Infeasibilities num(sum)
0 -1.9568483926e-04 Pr: 3(80.202) 0s
9 2.3500585825e+04 Pr: 0(0) 0s
Solving the original LP from the solution after postsolve
Model status : Optimal
Simplex iterations: 9
Objective value : 2.3500585825e+04
HiGHS run time : 0.00
Writing the solution to /tmp/linopy-solve-9k8ofcut.sol
[3]:
('ok', 'optimal')
[4]:
pd.DataFrame({attr: network.stores_t[attr]["water tank"] for attr in ["p", "e"]})
[4]:
| p | e | |
|---|---|---|
| snapshot | ||
| 2016-01-01 00:00:00 | 20.000000 | 4.376710 |
| 2016-01-01 01:00:00 | 4.332943 | -0.000000 |
| 2016-01-01 02:00:00 | -13.423055 | 13.423055 |
| 2016-01-01 03:00:00 | -11.334114 | 24.622939 |
[5]:
pd.DataFrame({attr: network.links_t[attr]["heat pump"] for attr in ["p0", "p1"]})
[5]:
| p0 | p1 | |
|---|---|---|
| snapshot | ||
| 2016-01-01 00:00:00 | -0.000000 | 0.000000 |
| 2016-01-01 01:00:00 | 5.222352 | -15.667057 |
| 2016-01-01 02:00:00 | 10.444705 | -33.423055 |
| 2016-01-01 03:00:00 | 10.444705 | -31.334114 |
[6]:
network.stores.loc[["water tank"]].T
[6]:
| Store | water tank |
|---|---|
| bus | 0 heat |
| type | |
| carrier | heat |
| e_nom | 0.0 |
| e_nom_mod | 0.0 |
| e_nom_extendable | True |
| e_nom_min | 0.0 |
| e_nom_max | inf |
| e_min_pu | 0.0 |
| e_max_pu | 1.0 |
| e_initial | 0.0 |
| e_initial_per_period | False |
| e_cyclic | True |
| e_cyclic_per_period | True |
| p_set | 0.0 |
| q_set | 0.0 |
| sign | 1.0 |
| marginal_cost | 0.0 |
| marginal_cost_quadratic | 0.0 |
| marginal_cost_storage | 0.0 |
| capital_cost | 0.0 |
| standing_loss | 0.01 |
| active | True |
| build_year | 0 |
| lifetime | inf |
| e_nom_opt | 24.622939 |
[7]:
network.generators.loc[["wind turbine"]].T
[7]:
| Generator | wind turbine |
|---|---|
| bus | 0 |
| control | PQ |
| type | |
| p_nom | 0.0 |
| p_nom_mod | 0.0 |
| p_nom_extendable | True |
| p_nom_min | 0.0 |
| p_nom_max | inf |
| p_min_pu | 0.0 |
| p_max_pu | 1.0 |
| p_set | 0.0 |
| e_sum_min | -inf |
| e_sum_max | inf |
| q_set | 0.0 |
| sign | 1.0 |
| carrier | wind |
| marginal_cost | 0.0 |
| marginal_cost_quadratic | 0.0 |
| active | True |
| build_year | 0 |
| lifetime | inf |
| capital_cost | 500.0 |
| efficiency | 1.0 |
| committable | False |
| start_up_cost | 0.0 |
| shut_down_cost | 0.0 |
| stand_by_cost | 0.0 |
| min_up_time | 0 |
| min_down_time | 0 |
| up_time_before | 1 |
| down_time_before | 0 |
| ramp_limit_up | NaN |
| ramp_limit_down | NaN |
| ramp_limit_start_up | 1.0 |
| ramp_limit_shut_down | 1.0 |
| weight | 1.0 |
| p_nom_opt | 26.111762 |