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_3066/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 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')
WARNING:pypsa.consistency:The following buses have carriers which are not defined:
Index(['0'], dtype='object', name='Bus')
INFO:linopy.model: Solve problem using Highs solver
INFO:linopy.io: Writing time: 0.09s
INFO:linopy.constants: Optimization successful:
Status: ok
Termination condition: optimal
Solution: 19 primals, 39 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.8.1 (git hash: 4a7f24a): 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(-30); columns 8(-11); elements 21(-45)
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 name : linopy-problem-q7mpunrs
Model status : Optimal
Simplex iterations: 9
Objective value : 2.3500585825e+04
Relative P-D gap : 1.5480374975e-16
HiGHS run time : 0.00
Writing the solution to /tmp/linopy-solve-vx86net8.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 |