Problem 5.2

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