Problem 5.2#
Integrated Energy Grids
Problem 5.2
Assume we have one bus (Denmark) in which there is a gas power generator whose variable cost is 50 EUR/MWh and installed capacity is 50 MW, and a wind generator whose variable cost is zero and whose installed capacity is 30 MW. Using Python for Power System Analysis (PyPSA):
a) Calculate the optimal dispatch that minimizes the total system cost, the energy produced by each generator, and the electricity price assuming that power demand is 80 MW
b) Calculate the optimal dispatch that minimizes the total system cost, the energy produced by each generator, and the electricity price assuming that power demand is 20 MW
Note: This is a straightforward problem, whose objective is to showcase how to solve one-node economic dispatch problems in PyPSA. It is recommended to follow the PyPSA tutorial before trying this problem.
Note
If you have not yet set up Python on your computer, you can execute this tutorial in your browser via Google Colab. Click on the rocket in the top right corner and launch “Colab”. If that doesn’t work download the .ipynb
file and import it in Google Colab.
Then install the following packages by executing the following command in a Jupyter cell at the top of the notebook.
!pip install numpy pypsa
import numpy as np
import pypsa
We start by creating the network object and adding the bus.
network = pypsa.Network()
network.add("Bus",
"bus Denmark")
network.buses
v_nom | type | x | y | carrier | unit | location | v_mag_pu_set | v_mag_pu_min | v_mag_pu_max | control | generator | sub_network | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Bus | |||||||||||||
bus Denmark | 1.0 | 0.0 | 0.0 | AC | 1.0 | 0.0 | inf | PQ |
We add the generators
network.add("Generator",
"gas Denmark",
bus="bus Denmark",
p_nom=50,
marginal_cost=50) #EUR/MWh_elec
network.add("Generator",
"wind Denmark",
bus="bus Denmark",
p_nom=30,
marginal_cost=0)
network.generators
bus | control | type | p_nom | p_nom_mod | p_nom_extendable | p_nom_min | p_nom_max | p_min_pu | p_max_pu | ... | min_up_time | min_down_time | up_time_before | down_time_before | ramp_limit_up | ramp_limit_down | ramp_limit_start_up | ramp_limit_shut_down | weight | p_nom_opt | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Generator | |||||||||||||||||||||
gas Denmark | bus Denmark | PQ | 50.0 | 0.0 | False | 0.0 | inf | 0.0 | 1.0 | ... | 0 | 0 | 1 | 0 | NaN | NaN | 1.0 | 1.0 | 1.0 | 0.0 | |
wind Denmark | bus Denmark | PQ | 30.0 | 0.0 | False | 0.0 | inf | 0.0 | 1.0 | ... | 0 | 0 | 1 | 0 | NaN | NaN | 1.0 | 1.0 | 1.0 | 0.0 |
2 rows × 37 columns
We add the load
network.add("Load",
"load Demmark",
bus="bus Denmark",
p_set=80)
network.loads
bus | carrier | type | p_set | q_set | sign | active | |
---|---|---|---|---|---|---|---|
Load | |||||||
load Demmark | bus Denmark | 80.0 | 0.0 | -1.0 | True |
Calculate the optimal economic dispatch
network.optimize()
WARNING:pypsa.consistency:The following buses have carriers which are not defined:
Index(['bus Denmark'], dtype='object', name='Bus')
INFO:linopy.model: Solve problem using Highs solver
INFO:linopy.io: Writing time: 0.01s
INFO:linopy.constants: Optimization successful:
Status: ok
Termination condition: optimal
Solution: 2 primals, 5 duals
Objective: 2.50e+03
Solver model: available
Solver message: Optimal
INFO:pypsa.optimization.optimize:The shadow-prices of the constraints Generator-fix-p-lower, Generator-fix-p-upper were not assigned to the network.
Running HiGHS 1.10.0 (git hash: fd86653): Copyright (c) 2025 HiGHS under MIT licence terms
LP linopy-problem-u0gllsty has 5 rows; 2 cols; 6 nonzeros
Coefficient ranges:
Matrix [1e+00, 1e+00]
Cost [5e+01, 5e+01]
Bound [0e+00, 0e+00]
RHS [3e+01, 8e+01]
Presolving model
0 rows, 0 cols, 0 nonzeros 0s
0 rows, 0 cols, 0 nonzeros 0s
Presolve : Reductions: rows 0(-5); columns 0(-2); elements 0(-6) - Reduced to empty
Solving the original LP from the solution after postsolve
Model name : linopy-problem-u0gllsty
Model status : Optimal
Objective value : 2.5000000000e+03
Relative P-D gap : 0.0000000000e+00
HiGHS run time : 0.00
Writing the solution to /tmp/linopy-solve-rfksv1ea.sol
('ok', 'optimal')
Now we can show the optimal dispatch and the electricity price (marginal cost at the bus)
network.generators_t.p
Generator | gas Denmark | wind Denmark |
---|---|---|
snapshot | ||
now | 50.0 | 30.0 |
network.buses_t.marginal_price
Bus | bus Denmark |
---|---|
snapshot | |
now | 50.0 |
We update the load and calculate the economic dispatch again.
network.add("Load",
"load Demmark",
bus="bus Denmark",
p_set=20,
overwrite=True)
network.optimize()
WARNING:pypsa.consistency:The following buses have carriers which are not defined:
Index(['bus Denmark'], dtype='object', name='Bus')
INFO:linopy.model: Solve problem using Highs solver
INFO:linopy.io: Writing time: 0.01s
INFO:linopy.constants: Optimization successful:
Status: ok
Termination condition: optimal
Solution: 2 primals, 5 duals
Objective: 0.00e+00
Solver model: available
Solver message: Optimal
INFO:pypsa.optimization.optimize:The shadow-prices of the constraints Generator-fix-p-lower, Generator-fix-p-upper were not assigned to the network.
Running HiGHS 1.10.0 (git hash: fd86653): Copyright (c) 2025 HiGHS under MIT licence terms
LP linopy-problem-gnpbx7a8 has 5 rows; 2 cols; 6 nonzeros
Coefficient ranges:
Matrix [1e+00, 1e+00]
Cost [5e+01, 5e+01]
Bound [0e+00, 0e+00]
RHS [2e+01, 5e+01]
Presolving model
0 rows, 0 cols, 0 nonzeros 0s
0 rows, 0 cols, 0 nonzeros 0s
Presolve : Reductions: rows 0(-5); columns 0(-2); elements 0(-6) - Reduced to empty
Solving the original LP from the solution after postsolve
Model name : linopy-problem-gnpbx7a8
Model status : Optimal
Objective value : 0.0000000000e+00
Relative P-D gap : 0.0000000000e+00
HiGHS run time : 0.00
Writing the solution to /tmp/linopy-solve-ymdvn67b.sol
('ok', 'optimal')
network.generators_t.p
Generator | gas Denmark | wind Denmark |
---|---|---|
snapshot | ||
now | -0.0 | 20.0 |
network.buses_t.marginal_price
Bus | bus Denmark |
---|---|
snapshot | |
now | -0.0 |