Note

You can download this example as a Jupyter notebook or start it in interactive mode.

Redispatch Example with SciGRID network#

In this example, we compare a 2-stage market with an initial market clearing in two bidding zones with flow-based market coupling and a subsequent redispatch market (incl. curtailment) to an idealised nodal pricing scheme.

[1]:
import cartopy.crs as ccrs
import matplotlib.pyplot as plt

import pypsa
from pypsa.descriptors import get_switchable_as_dense as as_dense
ERROR 1: PROJ: proj_create_from_database: Open of /home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/latest/share/proj failed

Load example network#

[2]:
o = pypsa.examples.scigrid_de(from_master=True)
o.lines.s_max_pu = 0.7
o.lines.loc[["316", "527", "602"], "s_nom"] = 1715
o.set_snapshots([o.snapshots[12]])
WARNING:pypsa.io:Importing network from PyPSA version v0.17.1 while current version is v0.28.1. Read the release notes at https://pypsa.readthedocs.io/en/latest/release_notes.html to prepare your network for import.
INFO:pypsa.io:Imported network scigrid-de.nc has buses, generators, lines, loads, storage_units, transformers
[3]:
n = o.copy()  # for redispatch model
m = o.copy()  # for market model
WARNING:pypsa.io:The following StorageUnit have buses which are not defined:
Index(['100_220kV Pumped Hydro', '114 Pumped Hydro', '121 Pumped Hydro',
       '140 Pumped Hydro', '141 Pumped Hydro', '158 Pumped Hydro',
       '166 Pumped Hydro', '205 Pumped Hydro', '228 Pumped Hydro',
       '235 Pumped Hydro', '25 Pumped Hydro', '266 Pumped Hydro',
       '268 Pumped Hydro', '279_220kV Pumped Hydro', '293 Pumped Hydro',
       '320 Pumped Hydro', '32_220kV Pumped Hydro', '333 Pumped Hydro',
       '342 Pumped Hydro', '343 Pumped Hydro', '362_220kV Pumped Hydro',
       '368 Pumped Hydro', '374 Pumped Hydro', '379 Pumped Hydro',
       '389 Pumped Hydro', '397 Pumped Hydro', '423 Pumped Hydro',
       '424 Pumped Hydro', '479 Pumped Hydro', '481 Pumped Hydro',
       '493 Pumped Hydro', '51 Pumped Hydro', '63 Pumped Hydro',
       '66 Pumped Hydro', '72 Pumped Hydro', '78_220kV Pumped Hydro',
       '8 Pumped Hydro', '98 Pumped Hydro'],
      dtype='object', name='StorageUnit')
WARNING:pypsa.io:The following Transformer have buses which are not defined:
Index(['2', '5', '10', '12', '13', '15', '18', '20', '22', '24', '26', '30',
       '32', '37', '42', '46', '52', '56', '61', '68', '69', '74', '78', '86',
       '87', '94', '95', '96', '99', '100', '104', '105', '106', '107', '117',
       '120', '123', '124', '125', '128', '129', '138', '143', '156', '157',
       '159', '160', '165', '184', '191', '195', '201', '220', '231', '232',
       '233', '236', '247', '248', '250', '251', '252', '261', '263', '264',
       '267', '272', '279', '281', '282', '292', '303', '307', '308', '312',
       '315', '317', '322', '332', '334', '336', '338', '351', '353', '360',
       '362', '382', '384', '385', '391', '403', '404', '413', '421', '450',
       '458'],
      dtype='object', name='Transformer')
WARNING:pypsa.io:The following Transformer have buses which are not defined:
Index(['2', '5', '10', '12', '13', '15', '18', '20', '22', '24', '26', '30',
       '32', '37', '42', '46', '52', '56', '61', '68', '69', '74', '78', '86',
       '87', '94', '95', '96', '99', '100', '104', '105', '106', '107', '117',
       '120', '123', '124', '125', '128', '129', '138', '143', '156', '157',
       '159', '160', '165', '184', '191', '195', '201', '220', '231', '232',
       '233', '236', '247', '248', '250', '251', '252', '261', '263', '264',
       '267', '272', '279', '281', '282', '292', '303', '307', '308', '312',
       '315', '317', '322', '332', '334', '336', '338', '351', '353', '360',
       '362', '382', '384', '385', '391', '403', '404', '413', '421', '450',
       '458'],
      dtype='object', name='Transformer')
WARNING:pypsa.io:The following StorageUnit have buses which are not defined:
Index(['100_220kV Pumped Hydro', '114 Pumped Hydro', '121 Pumped Hydro',
       '140 Pumped Hydro', '141 Pumped Hydro', '158 Pumped Hydro',
       '166 Pumped Hydro', '205 Pumped Hydro', '228 Pumped Hydro',
       '235 Pumped Hydro', '25 Pumped Hydro', '266 Pumped Hydro',
       '268 Pumped Hydro', '279_220kV Pumped Hydro', '293 Pumped Hydro',
       '320 Pumped Hydro', '32_220kV Pumped Hydro', '333 Pumped Hydro',
       '342 Pumped Hydro', '343 Pumped Hydro', '362_220kV Pumped Hydro',
       '368 Pumped Hydro', '374 Pumped Hydro', '379 Pumped Hydro',
       '389 Pumped Hydro', '397 Pumped Hydro', '423 Pumped Hydro',
       '424 Pumped Hydro', '479 Pumped Hydro', '481 Pumped Hydro',
       '493 Pumped Hydro', '51 Pumped Hydro', '63 Pumped Hydro',
       '66 Pumped Hydro', '72 Pumped Hydro', '78_220kV Pumped Hydro',
       '8 Pumped Hydro', '98 Pumped Hydro'],
      dtype='object', name='StorageUnit')
WARNING:pypsa.io:The following Transformer have buses which are not defined:
Index(['2', '5', '10', '12', '13', '15', '18', '20', '22', '24', '26', '30',
       '32', '37', '42', '46', '52', '56', '61', '68', '69', '74', '78', '86',
       '87', '94', '95', '96', '99', '100', '104', '105', '106', '107', '117',
       '120', '123', '124', '125', '128', '129', '138', '143', '156', '157',
       '159', '160', '165', '184', '191', '195', '201', '220', '231', '232',
       '233', '236', '247', '248', '250', '251', '252', '261', '263', '264',
       '267', '272', '279', '281', '282', '292', '303', '307', '308', '312',
       '315', '317', '322', '332', '334', '336', '338', '351', '353', '360',
       '362', '382', '384', '385', '391', '403', '404', '413', '421', '450',
       '458'],
      dtype='object', name='Transformer')
WARNING:pypsa.io:The following Transformer have buses which are not defined:
Index(['2', '5', '10', '12', '13', '15', '18', '20', '22', '24', '26', '30',
       '32', '37', '42', '46', '52', '56', '61', '68', '69', '74', '78', '86',
       '87', '94', '95', '96', '99', '100', '104', '105', '106', '107', '117',
       '120', '123', '124', '125', '128', '129', '138', '143', '156', '157',
       '159', '160', '165', '184', '191', '195', '201', '220', '231', '232',
       '233', '236', '247', '248', '250', '251', '252', '261', '263', '264',
       '267', '272', '279', '281', '282', '292', '303', '307', '308', '312',
       '315', '317', '322', '332', '334', '336', '338', '351', '353', '360',
       '362', '382', '384', '385', '391', '403', '404', '413', '421', '450',
       '458'],
      dtype='object', name='Transformer')
[4]:
o.plot();
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/latest/lib/python3.12/site-packages/IPython/core/pylabtools.py:77: DeprecationWarning: backend2gui is deprecated since IPython 8.24, backends are managed in matplotlib and can be externally registered.
  warnings.warn(
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/latest/lib/python3.12/site-packages/IPython/core/pylabtools.py:77: DeprecationWarning: backend2gui is deprecated since IPython 8.24, backends are managed in matplotlib and can be externally registered.
  warnings.warn(
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/latest/lib/python3.12/site-packages/IPython/core/pylabtools.py:77: DeprecationWarning: backend2gui is deprecated since IPython 8.24, backends are managed in matplotlib and can be externally registered.
  warnings.warn(
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/latest/lib/python3.12/site-packages/cartopy/mpl/feature_artist.py:144: UserWarning: facecolor will have no effect as it has been defined as "never".
  warnings.warn('facecolor will have no effect as it has been '
../_images/examples_scigrid-redispatch_5_1.png

Solve original nodal market model o#

First, let us solve a nodal market using the original model o:

[5]:
o.optimize()
WARNING:pypsa.consistency:The following storage_units have carriers which are not defined:
Index(['100_220kV Pumped Hydro', '114 Pumped Hydro', '121 Pumped Hydro',
       '140 Pumped Hydro', '141 Pumped Hydro', '158 Pumped Hydro',
       '166 Pumped Hydro', '205 Pumped Hydro', '228 Pumped Hydro',
       '235 Pumped Hydro', '25 Pumped Hydro', '266 Pumped Hydro',
       '268 Pumped Hydro', '279_220kV Pumped Hydro', '293 Pumped Hydro',
       '320 Pumped Hydro', '32_220kV Pumped Hydro', '333 Pumped Hydro',
       '342 Pumped Hydro', '343 Pumped Hydro', '362_220kV Pumped Hydro',
       '368 Pumped Hydro', '374 Pumped Hydro', '379 Pumped Hydro',
       '389 Pumped Hydro', '397 Pumped Hydro', '423 Pumped Hydro',
       '424 Pumped Hydro', '479 Pumped Hydro', '481 Pumped Hydro',
       '493 Pumped Hydro', '51 Pumped Hydro', '63 Pumped Hydro',
       '66 Pumped Hydro', '72 Pumped Hydro', '78_220kV Pumped Hydro',
       '8 Pumped Hydro', '98 Pumped Hydro'],
      dtype='object', name='StorageUnit')
WARNING:pypsa.consistency:The following transformers have zero r, which could break the linear load flow:
Index(['2', '5', '10', '12', '13', '15', '18', '20', '22', '24', '26', '30',
       '32', '37', '42', '46', '52', '56', '61', '68', '69', '74', '78', '86',
       '87', '94', '95', '96', '99', '100', '104', '105', '106', '107', '117',
       '120', '123', '124', '125', '128', '129', '138', '143', '156', '157',
       '159', '160', '165', '184', '191', '195', '201', '220', '231', '232',
       '233', '236', '247', '248', '250', '251', '252', '261', '263', '264',
       '267', '272', '279', '281', '282', '292', '303', '307', '308', '312',
       '315', '317', '322', '332', '334', '336', '338', '351', '353', '360',
       '362', '382', '384', '385', '391', '403', '404', '413', '421', '450',
       '458'],
      dtype='object', name='Transformer')
WARNING:pypsa.consistency:The following buses have carriers which are not defined:
Index(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
       ...
       '382_220kV', '384_220kV', '385_220kV', '391_220kV', '403_220kV',
       '404_220kV', '413_220kV', '421_220kV', '450_220kV', '458_220kV'],
      dtype='object', name='Bus', length=585)
WARNING:pypsa.consistency:The following lines have carriers which are not defined:
Index(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
       ...
       '850', '851', '852', '853', '854', '855', '856', '857', '858', '859'],
      dtype='object', name='Line', length=852)
WARNING:pypsa.consistency:The following generators have carriers which are not defined:
Index(['1 Gas', '1 Hard Coal', '102 Gas', '108 Run of River', '108 Waste',
       '111 Gas', '112 Gas', '112 Run of River', '114 Hard Coal',
       '115 Brown Coal',
       ...
       '382_220kV Solar', '384_220kV Solar', '385_220kV Solar',
       '391_220kV Solar', '403_220kV Solar', '404_220kV Solar',
       '413_220kV Solar', '421_220kV Solar', '450_220kV Solar',
       '458_220kV Solar'],
      dtype='object', name='Generator', length=1423)
WARNING:pypsa.consistency:The following storage_units have carriers which are not defined:
Index(['100_220kV Pumped Hydro', '114 Pumped Hydro', '121 Pumped Hydro',
       '140 Pumped Hydro', '141 Pumped Hydro', '158 Pumped Hydro',
       '166 Pumped Hydro', '205 Pumped Hydro', '228 Pumped Hydro',
       '235 Pumped Hydro', '25 Pumped Hydro', '266 Pumped Hydro',
       '268 Pumped Hydro', '279_220kV Pumped Hydro', '293 Pumped Hydro',
       '320 Pumped Hydro', '32_220kV Pumped Hydro', '333 Pumped Hydro',
       '342 Pumped Hydro', '343 Pumped Hydro', '362_220kV Pumped Hydro',
       '368 Pumped Hydro', '374 Pumped Hydro', '379 Pumped Hydro',
       '389 Pumped Hydro', '397 Pumped Hydro', '423 Pumped Hydro',
       '424 Pumped Hydro', '479 Pumped Hydro', '481 Pumped Hydro',
       '493 Pumped Hydro', '51 Pumped Hydro', '63 Pumped Hydro',
       '66 Pumped Hydro', '72 Pumped Hydro', '78_220kV Pumped Hydro',
       '8 Pumped Hydro', '98 Pumped Hydro'],
      dtype='object', name='StorageUnit')
WARNING:pypsa.consistency:The following transformers have zero r, which could break the linear load flow:
Index(['2', '5', '10', '12', '13', '15', '18', '20', '22', '24', '26', '30',
       '32', '37', '42', '46', '52', '56', '61', '68', '69', '74', '78', '86',
       '87', '94', '95', '96', '99', '100', '104', '105', '106', '107', '117',
       '120', '123', '124', '125', '128', '129', '138', '143', '156', '157',
       '159', '160', '165', '184', '191', '195', '201', '220', '231', '232',
       '233', '236', '247', '248', '250', '251', '252', '261', '263', '264',
       '267', '272', '279', '281', '282', '292', '303', '307', '308', '312',
       '315', '317', '322', '332', '334', '336', '338', '351', '353', '360',
       '362', '382', '384', '385', '391', '403', '404', '413', '421', '450',
       '458'],
      dtype='object', name='Transformer')
WARNING:pypsa.consistency:The following buses have carriers which are not defined:
Index(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
       ...
       '382_220kV', '384_220kV', '385_220kV', '391_220kV', '403_220kV',
       '404_220kV', '413_220kV', '421_220kV', '450_220kV', '458_220kV'],
      dtype='object', name='Bus', length=585)
WARNING:pypsa.consistency:The following lines have carriers which are not defined:
Index(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
       ...
       '850', '851', '852', '853', '854', '855', '856', '857', '858', '859'],
      dtype='object', name='Line', length=852)
WARNING:pypsa.consistency:The following generators have carriers which are not defined:
Index(['1 Gas', '1 Hard Coal', '102 Gas', '108 Run of River', '108 Waste',
       '111 Gas', '112 Gas', '112 Run of River', '114 Hard Coal',
       '115 Brown Coal',
       ...
       '382_220kV Solar', '384_220kV Solar', '385_220kV Solar',
       '391_220kV Solar', '403_220kV Solar', '404_220kV Solar',
       '413_220kV Solar', '421_220kV Solar', '450_220kV Solar',
       '458_220kV Solar'],
      dtype='object', name='Generator', length=1423)
INFO:linopy.model: Solve problem using Highs solver
INFO:linopy.io: Writing time: 0.16s
INFO:linopy.solvers:Log file at /tmp/highs.log
INFO:linopy.constants: Optimization successful:
Status: ok
Termination condition: optimal
Solution: 2485 primals, 5957 duals
Objective: 3.01e+05
Solver model: available
Solver message: optimal

INFO:pypsa.optimization.optimize:The shadow-prices of the constraints Generator-fix-p-lower, Generator-fix-p-upper, Line-fix-s-lower, Line-fix-s-upper, Transformer-fix-s-lower, Transformer-fix-s-upper, StorageUnit-fix-p_dispatch-lower, StorageUnit-fix-p_dispatch-upper, StorageUnit-fix-p_store-lower, StorageUnit-fix-p_store-upper, StorageUnit-fix-state_of_charge-lower, StorageUnit-fix-state_of_charge-upper, Kirchhoff-Voltage-Law, StorageUnit-energy_balance were not assigned to the network.
Running HiGHS 1.7.1 (git hash: 0c240d8): Copyright (c) 2024 HiGHS under MIT licence terms
Coefficient ranges:
  Matrix [1e-02, 2e+02]
  Cost   [3e+00, 1e+02]
  Bound  [0e+00, 0e+00]
  RHS    [4e-10, 6e+03]
Presolving model
817 rows, 2282 cols, 5150 nonzeros  0s
559 rows, 2017 cols, 4767 nonzeros  0s
543 rows, 1362 cols, 4040 nonzeros  0s
524 rows, 1338 cols, 4071 nonzeros  0s
Presolve : Reductions: rows 524(-5433); columns 1338(-1147); elements 4071(-6780)
Solving the presolved LP
Using EKK dual simplex solver - serial
  Iteration        Objective     Infeasibilities num(sum)
          0    -2.3328331372e-01 Pr: 486(3.28207e+06) 0s
        641     3.0120938233e+05 Pr: 0(0) 0s
Solving the original LP from the solution after postsolve
Model   status      : Optimal
Simplex   iterations: 641
Objective value     :  3.0120938233e+05
HiGHS run time      :          0.08
[5]:
('ok', 'optimal')

Costs are 301 k€.

Build market model m with two bidding zones#

For this example, we split the German transmission network into two market zones at latitude 51 degrees.

You can build any other market zones by providing an alternative mapping from bus to zone.

[6]:
zones = (n.buses.y > 51).map(lambda x: "North" if x else "South")

Next, we assign this mapping to the market model m.

We re-assign the buses of all generators and loads, and remove all transmission lines within each bidding zone.

Here, we assume that the bidding zones are coupled through the transmission lines that connect them.

[7]:
for c in m.iterate_components(m.one_port_components):
    c.df.bus = c.df.bus.map(zones)

for c in m.iterate_components(m.branch_components):
    c.df.bus0 = c.df.bus0.map(zones)
    c.df.bus1 = c.df.bus1.map(zones)
    internal = c.df.bus0 == c.df.bus1
    m.mremove(c.name, c.df.loc[internal].index)

m.mremove("Bus", m.buses.index)
m.madd("Bus", ["North", "South"]);

Now, we can solve the coupled market with two bidding zones.

[8]:
m.optimize()
WARNING:pypsa.consistency:The following storage_units have carriers which are not defined:
Index(['100_220kV Pumped Hydro', '114 Pumped Hydro', '121 Pumped Hydro',
       '140 Pumped Hydro', '141 Pumped Hydro', '158 Pumped Hydro',
       '166 Pumped Hydro', '205 Pumped Hydro', '228 Pumped Hydro',
       '235 Pumped Hydro', '25 Pumped Hydro', '266 Pumped Hydro',
       '268 Pumped Hydro', '279_220kV Pumped Hydro', '293 Pumped Hydro',
       '320 Pumped Hydro', '32_220kV Pumped Hydro', '333 Pumped Hydro',
       '342 Pumped Hydro', '343 Pumped Hydro', '362_220kV Pumped Hydro',
       '368 Pumped Hydro', '374 Pumped Hydro', '379 Pumped Hydro',
       '389 Pumped Hydro', '397 Pumped Hydro', '423 Pumped Hydro',
       '424 Pumped Hydro', '479 Pumped Hydro', '481 Pumped Hydro',
       '493 Pumped Hydro', '51 Pumped Hydro', '63 Pumped Hydro',
       '66 Pumped Hydro', '72 Pumped Hydro', '78_220kV Pumped Hydro',
       '8 Pumped Hydro', '98 Pumped Hydro'],
      dtype='object', name='StorageUnit')
WARNING:pypsa.consistency:The following buses have carriers which are not defined:
Index(['North', 'South'], dtype='object', name='Bus')
WARNING:pypsa.consistency:The following lines have carriers which are not defined:
Index(['29', '48', '49', '131', '164', '167', '169', '171', '186', '249',
       '378', '379', '381', '382', '429', '447', '459', '499', '508', '509',
       '510', '511', '684', '693'],
      dtype='object', name='Line')
WARNING:pypsa.consistency:The following generators have carriers which are not defined:
Index(['1 Gas', '1 Hard Coal', '102 Gas', '108 Run of River', '108 Waste',
       '111 Gas', '112 Gas', '112 Run of River', '114 Hard Coal',
       '115 Brown Coal',
       ...
       '382_220kV Solar', '384_220kV Solar', '385_220kV Solar',
       '391_220kV Solar', '403_220kV Solar', '404_220kV Solar',
       '413_220kV Solar', '421_220kV Solar', '450_220kV Solar',
       '458_220kV Solar'],
      dtype='object', name='Generator', length=1423)
WARNING:pypsa.consistency:The following storage_units have carriers which are not defined:
Index(['100_220kV Pumped Hydro', '114 Pumped Hydro', '121 Pumped Hydro',
       '140 Pumped Hydro', '141 Pumped Hydro', '158 Pumped Hydro',
       '166 Pumped Hydro', '205 Pumped Hydro', '228 Pumped Hydro',
       '235 Pumped Hydro', '25 Pumped Hydro', '266 Pumped Hydro',
       '268 Pumped Hydro', '279_220kV Pumped Hydro', '293 Pumped Hydro',
       '320 Pumped Hydro', '32_220kV Pumped Hydro', '333 Pumped Hydro',
       '342 Pumped Hydro', '343 Pumped Hydro', '362_220kV Pumped Hydro',
       '368 Pumped Hydro', '374 Pumped Hydro', '379 Pumped Hydro',
       '389 Pumped Hydro', '397 Pumped Hydro', '423 Pumped Hydro',
       '424 Pumped Hydro', '479 Pumped Hydro', '481 Pumped Hydro',
       '493 Pumped Hydro', '51 Pumped Hydro', '63 Pumped Hydro',
       '66 Pumped Hydro', '72 Pumped Hydro', '78_220kV Pumped Hydro',
       '8 Pumped Hydro', '98 Pumped Hydro'],
      dtype='object', name='StorageUnit')
WARNING:pypsa.consistency:The following buses have carriers which are not defined:
Index(['North', 'South'], dtype='object', name='Bus')
WARNING:pypsa.consistency:The following lines have carriers which are not defined:
Index(['29', '48', '49', '131', '164', '167', '169', '171', '186', '249',
       '378', '379', '381', '382', '429', '447', '459', '499', '508', '509',
       '510', '511', '684', '693'],
      dtype='object', name='Line')
WARNING:pypsa.consistency:The following generators have carriers which are not defined:
Index(['1 Gas', '1 Hard Coal', '102 Gas', '108 Run of River', '108 Waste',
       '111 Gas', '112 Gas', '112 Run of River', '114 Hard Coal',
       '115 Brown Coal',
       ...
       '382_220kV Solar', '384_220kV Solar', '385_220kV Solar',
       '391_220kV Solar', '403_220kV Solar', '404_220kV Solar',
       '413_220kV Solar', '421_220kV Solar', '450_220kV Solar',
       '458_220kV Solar'],
      dtype='object', name='Generator', length=1423)
INFO:linopy.model: Solve problem using Highs solver
INFO:linopy.io: Writing time: 0.12s
INFO:linopy.solvers:Log file at /tmp/highs.log
INFO:linopy.constants: Optimization successful:
Status: ok
Termination condition: optimal
Solution: 1561 primals, 3185 duals
Objective: 2.14e+05
Solver model: available
Solver message: optimal

INFO:pypsa.optimization.optimize:The shadow-prices of the constraints Generator-fix-p-lower, Generator-fix-p-upper, Line-fix-s-lower, Line-fix-s-upper, StorageUnit-fix-p_dispatch-lower, StorageUnit-fix-p_dispatch-upper, StorageUnit-fix-p_store-lower, StorageUnit-fix-p_store-upper, StorageUnit-fix-state_of_charge-lower, StorageUnit-fix-state_of_charge-upper, Kirchhoff-Voltage-Law, StorageUnit-energy_balance were not assigned to the network.
Running HiGHS 1.7.1 (git hash: 0c240d8): Copyright (c) 2024 HiGHS under MIT licence terms
Coefficient ranges:
  Matrix [9e-01, 3e+06]
  Cost   [3e+00, 1e+02]
  Bound  [0e+00, 0e+00]
  RHS    [4e-10, 3e+04]
Presolving model
40 rows, 1510 cols, 1587 nonzeros  0s
40 rows, 135 cols, 212 nonzeros  0s
40 rows, 135 cols, 212 nonzeros  0s
Presolve : Reductions: rows 40(-3145); columns 135(-1426); elements 212(-4617)
Solving the presolved LP
Using EKK dual simplex solver - serial
  Iteration        Objective     Infeasibilities num(sum)
          0    -4.3458587374e-04 Pr: 2(51830.2) 0s
         42     2.1398868596e+05 Pr: 0(0) 0s
Solving the original LP from the solution after postsolve
Model   status      : Optimal
Simplex   iterations: 42
Objective value     :  2.1398868596e+05
HiGHS run time      :          0.01
[8]:
('ok', 'optimal')

Costs are 214 k€, which is much lower than the 301 k€ of the nodal market.

This is because network restrictions apart from the North/South division are not taken into account yet.

We can look at the market clearing prices of each zone:

[9]:
m.buses_t.marginal_price
[9]:
Bus North South
snapshot
2011-01-01 12:00:00 8.0 25.0

Build redispatch model n#

Next, based on the market outcome with two bidding zones m, we build a secondary redispatch market n that rectifies transmission constraints through curtailment and ramping up/down thermal generators.

First, we fix the dispatch of generators to the results from the market simulation. (For simplicity, this example disregards storage units.)

[10]:
p = m.generators_t.p / m.generators.p_nom
n.generators_t.p_min_pu = p
n.generators_t.p_max_pu = p

Then, we add generators bidding into redispatch market using the following assumptions:

  • All generators can reduce their dispatch to zero. This includes also curtailment of renewables.

  • All generators can increase their dispatch to their available/nominal capacity.

  • No changes to the marginal costs, i.e. reducing dispatch lowers costs.

With these settings, the 2-stage market should result in the same cost as the nodal market.

[11]:
g_up = n.generators.copy()
g_down = n.generators.copy()

g_up.index = g_up.index.map(lambda x: x + " ramp up")
g_down.index = g_down.index.map(lambda x: x + " ramp down")

up = (
    as_dense(m, "Generator", "p_max_pu") * m.generators.p_nom - m.generators_t.p
).clip(0) / m.generators.p_nom
down = -m.generators_t.p / m.generators.p_nom

up.columns = up.columns.map(lambda x: x + " ramp up")
down.columns = down.columns.map(lambda x: x + " ramp down")

n.madd("Generator", g_up.index, p_max_pu=up, **g_up.drop("p_max_pu", axis=1))

n.madd(
    "Generator",
    g_down.index,
    p_min_pu=down,
    p_max_pu=0,
    **g_down.drop(["p_max_pu", "p_min_pu"], axis=1),
);

Now, let’s solve the redispatch market:

[12]:
n.optimize()
WARNING:pypsa.consistency:The following storage_units have carriers which are not defined:
Index(['100_220kV Pumped Hydro', '114 Pumped Hydro', '121 Pumped Hydro',
       '140 Pumped Hydro', '141 Pumped Hydro', '158 Pumped Hydro',
       '166 Pumped Hydro', '205 Pumped Hydro', '228 Pumped Hydro',
       '235 Pumped Hydro', '25 Pumped Hydro', '266 Pumped Hydro',
       '268 Pumped Hydro', '279_220kV Pumped Hydro', '293 Pumped Hydro',
       '320 Pumped Hydro', '32_220kV Pumped Hydro', '333 Pumped Hydro',
       '342 Pumped Hydro', '343 Pumped Hydro', '362_220kV Pumped Hydro',
       '368 Pumped Hydro', '374 Pumped Hydro', '379 Pumped Hydro',
       '389 Pumped Hydro', '397 Pumped Hydro', '423 Pumped Hydro',
       '424 Pumped Hydro', '479 Pumped Hydro', '481 Pumped Hydro',
       '493 Pumped Hydro', '51 Pumped Hydro', '63 Pumped Hydro',
       '66 Pumped Hydro', '72 Pumped Hydro', '78_220kV Pumped Hydro',
       '8 Pumped Hydro', '98 Pumped Hydro'],
      dtype='object', name='StorageUnit')
WARNING:pypsa.consistency:The following transformers have zero r, which could break the linear load flow:
Index(['2', '5', '10', '12', '13', '15', '18', '20', '22', '24', '26', '30',
       '32', '37', '42', '46', '52', '56', '61', '68', '69', '74', '78', '86',
       '87', '94', '95', '96', '99', '100', '104', '105', '106', '107', '117',
       '120', '123', '124', '125', '128', '129', '138', '143', '156', '157',
       '159', '160', '165', '184', '191', '195', '201', '220', '231', '232',
       '233', '236', '247', '248', '250', '251', '252', '261', '263', '264',
       '267', '272', '279', '281', '282', '292', '303', '307', '308', '312',
       '315', '317', '322', '332', '334', '336', '338', '351', '353', '360',
       '362', '382', '384', '385', '391', '403', '404', '413', '421', '450',
       '458'],
      dtype='object', name='Transformer')
WARNING:pypsa.consistency:The following buses have carriers which are not defined:
Index(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
       ...
       '382_220kV', '384_220kV', '385_220kV', '391_220kV', '403_220kV',
       '404_220kV', '413_220kV', '421_220kV', '450_220kV', '458_220kV'],
      dtype='object', name='Bus', length=585)
WARNING:pypsa.consistency:The following lines have carriers which are not defined:
Index(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
       ...
       '850', '851', '852', '853', '854', '855', '856', '857', '858', '859'],
      dtype='object', name='Line', length=852)
WARNING:pypsa.consistency:The following generators have carriers which are not defined:
Index(['1 Gas', '1 Hard Coal', '102 Gas', '108 Run of River', '108 Waste',
       '111 Gas', '112 Gas', '112 Run of River', '114 Hard Coal',
       '115 Brown Coal',
       ...
       '382_220kV Solar ramp down', '384_220kV Solar ramp down',
       '385_220kV Solar ramp down', '391_220kV Solar ramp down',
       '403_220kV Solar ramp down', '404_220kV Solar ramp down',
       '413_220kV Solar ramp down', '421_220kV Solar ramp down',
       '450_220kV Solar ramp down', '458_220kV Solar ramp down'],
      dtype='object', name='Generator', length=4269)
WARNING:pypsa.consistency:The following storage_units have carriers which are not defined:
Index(['100_220kV Pumped Hydro', '114 Pumped Hydro', '121 Pumped Hydro',
       '140 Pumped Hydro', '141 Pumped Hydro', '158 Pumped Hydro',
       '166 Pumped Hydro', '205 Pumped Hydro', '228 Pumped Hydro',
       '235 Pumped Hydro', '25 Pumped Hydro', '266 Pumped Hydro',
       '268 Pumped Hydro', '279_220kV Pumped Hydro', '293 Pumped Hydro',
       '320 Pumped Hydro', '32_220kV Pumped Hydro', '333 Pumped Hydro',
       '342 Pumped Hydro', '343 Pumped Hydro', '362_220kV Pumped Hydro',
       '368 Pumped Hydro', '374 Pumped Hydro', '379 Pumped Hydro',
       '389 Pumped Hydro', '397 Pumped Hydro', '423 Pumped Hydro',
       '424 Pumped Hydro', '479 Pumped Hydro', '481 Pumped Hydro',
       '493 Pumped Hydro', '51 Pumped Hydro', '63 Pumped Hydro',
       '66 Pumped Hydro', '72 Pumped Hydro', '78_220kV Pumped Hydro',
       '8 Pumped Hydro', '98 Pumped Hydro'],
      dtype='object', name='StorageUnit')
WARNING:pypsa.consistency:The following transformers have zero r, which could break the linear load flow:
Index(['2', '5', '10', '12', '13', '15', '18', '20', '22', '24', '26', '30',
       '32', '37', '42', '46', '52', '56', '61', '68', '69', '74', '78', '86',
       '87', '94', '95', '96', '99', '100', '104', '105', '106', '107', '117',
       '120', '123', '124', '125', '128', '129', '138', '143', '156', '157',
       '159', '160', '165', '184', '191', '195', '201', '220', '231', '232',
       '233', '236', '247', '248', '250', '251', '252', '261', '263', '264',
       '267', '272', '279', '281', '282', '292', '303', '307', '308', '312',
       '315', '317', '322', '332', '334', '336', '338', '351', '353', '360',
       '362', '382', '384', '385', '391', '403', '404', '413', '421', '450',
       '458'],
      dtype='object', name='Transformer')
WARNING:pypsa.consistency:The following buses have carriers which are not defined:
Index(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
       ...
       '382_220kV', '384_220kV', '385_220kV', '391_220kV', '403_220kV',
       '404_220kV', '413_220kV', '421_220kV', '450_220kV', '458_220kV'],
      dtype='object', name='Bus', length=585)
WARNING:pypsa.consistency:The following lines have carriers which are not defined:
Index(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
       ...
       '850', '851', '852', '853', '854', '855', '856', '857', '858', '859'],
      dtype='object', name='Line', length=852)
WARNING:pypsa.consistency:The following generators have carriers which are not defined:
Index(['1 Gas', '1 Hard Coal', '102 Gas', '108 Run of River', '108 Waste',
       '111 Gas', '112 Gas', '112 Run of River', '114 Hard Coal',
       '115 Brown Coal',
       ...
       '382_220kV Solar ramp down', '384_220kV Solar ramp down',
       '385_220kV Solar ramp down', '391_220kV Solar ramp down',
       '403_220kV Solar ramp down', '404_220kV Solar ramp down',
       '413_220kV Solar ramp down', '421_220kV Solar ramp down',
       '450_220kV Solar ramp down', '458_220kV Solar ramp down'],
      dtype='object', name='Generator', length=4269)
INFO:linopy.model: Solve problem using Highs solver
INFO:linopy.io: Writing time: 0.21s
INFO:linopy.solvers:Log file at /tmp/highs.log
INFO:linopy.constants: Optimization successful:
Status: ok
Termination condition: optimal
Solution: 5331 primals, 11649 duals
Objective: 3.01e+05
Solver model: available
Solver message: optimal

Running HiGHS 1.7.1 (git hash: 0c240d8): Copyright (c) 2024 HiGHS under MIT licence terms
Coefficient ranges:
  Matrix [1e-02, 2e+02]
  Cost   [3e+00, 1e+02]
  Bound  [0e+00, 0e+00]
  RHS    [2e-19, 6e+03]
Presolving model
817 rows, 2285 cols, 5153 nonzeros  0s
561 rows, 2021 cols, 4779 nonzeros  0s
545 rows, 1366 cols, 4049 nonzeros  0s
530 rows, 1346 cols, 4116 nonzeros  0s
Presolve : Reductions: rows 530(-11119); columns 1346(-3985); elements 4116(-15273)
Solving the presolved LP
Using EKK dual simplex solver - serial
  Iteration        Objective     Infeasibilities num(sum)
          0     0.0000000000e+00 Ph1: 0(0) 0s
        620     3.0120938233e+05 Pr: 0(0); Du: 0(2.18714e-13) 0s
Solving the original LP from the solution after postsolve
Model   status      : Optimal
Simplex   iterations: 620
Objective value     :  3.0120938232e+05
HiGHS run time      :          0.09
INFO:pypsa.optimization.optimize:The shadow-prices of the constraints Generator-fix-p-lower, Generator-fix-p-upper, Line-fix-s-lower, Line-fix-s-upper, Transformer-fix-s-lower, Transformer-fix-s-upper, StorageUnit-fix-p_dispatch-lower, StorageUnit-fix-p_dispatch-upper, StorageUnit-fix-p_store-lower, StorageUnit-fix-p_store-upper, StorageUnit-fix-state_of_charge-lower, StorageUnit-fix-state_of_charge-upper, Kirchhoff-Voltage-Law, StorageUnit-energy_balance were not assigned to the network.
[12]:
('ok', 'optimal')

And, as expected, the costs are the same as for the nodal market: 301 k€.

Now, we can plot both the market results of the 2 bidding zone market and the redispatch results:

[13]:
fig, axs = plt.subplots(
    1, 3, figsize=(20, 10), subplot_kw={"projection": ccrs.AlbersEqualArea()}
)

market = (
    n.generators_t.p[m.generators.index]
    .T.squeeze()
    .groupby(n.generators.bus)
    .sum()
    .div(2e4)
)
n.plot(ax=axs[0], bus_sizes=market, title="2 bidding zones market simulation")

redispatch_up = (
    n.generators_t.p.filter(like="ramp up")
    .T.squeeze()
    .groupby(n.generators.bus)
    .sum()
    .div(2e4)
)
n.plot(
    ax=axs[1], bus_sizes=redispatch_up, bus_colors="blue", title="Redispatch: ramp up"
)

redispatch_down = (
    n.generators_t.p.filter(like="ramp down")
    .T.squeeze()
    .groupby(n.generators.bus)
    .sum()
    .div(-2e4)
)
n.plot(
    ax=axs[2],
    bus_sizes=redispatch_down,
    bus_colors="red",
    title="Redispatch: ramp down / curtail",
);
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/latest/lib/python3.12/site-packages/cartopy/mpl/feature_artist.py:144: UserWarning: facecolor will have no effect as it has been defined as "never".
  warnings.warn('facecolor will have no effect as it has been '
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/latest/lib/python3.12/site-packages/cartopy/mpl/feature_artist.py:144: UserWarning: facecolor will have no effect as it has been defined as "never".
  warnings.warn('facecolor will have no effect as it has been '
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/latest/lib/python3.12/site-packages/cartopy/mpl/feature_artist.py:144: UserWarning: facecolor will have no effect as it has been defined as "never".
  warnings.warn('facecolor will have no effect as it has been '
../_images/examples_scigrid-redispatch_29_1.png

We can also read out the final dispatch of each generator:

[14]:
grouper = n.generators.index.str.split(" ramp", expand=True).get_level_values(0)

n.generators_t.p.groupby(grouper, axis=1).sum().squeeze()
/tmp/ipykernel_5531/2204001103.py:3: FutureWarning: DataFrame.groupby with axis=1 is deprecated. Do `frame.T.groupby(...)` without axis instead.
  n.generators_t.p.groupby(grouper, axis=1).sum().squeeze()
[14]:
1 Gas                     0.000000
1 Hard Coal               0.000000
1 Solar                  11.326192
1 Wind Onshore            1.754382
100_220kV Solar          14.913326
                           ...
98 Wind Onshore          71.451646
99_220kV Gas              0.000000
99_220kV Hard Coal        0.000000
99_220kV Solar            8.246606
99_220kV Wind Onshore     3.432939
Name: 2011-01-01 12:00:00, Length: 1423, dtype: float64

Changing bidding strategies in redispatch market#

We can also formulate other bidding strategies or compensation mechanisms for the redispatch market.

For example, that ramping up a generator is twice as expensive.

[15]:
n.generators.loc[n.generators.index.str.contains("ramp up"), "marginal_cost"] *= 2

Or that generators need to be compensated for curtailing them or ramping them down at 50% of their marginal cost.

[16]:
n.generators.loc[n.generators.index.str.contains("ramp down"), "marginal_cost"] *= -0.5

In this way, the outcome should be more expensive than the ideal nodal market:

[17]:
n.optimize()
WARNING:pypsa.consistency:The following storage_units have carriers which are not defined:
Index(['100_220kV Pumped Hydro', '114 Pumped Hydro', '121 Pumped Hydro',
       '140 Pumped Hydro', '141 Pumped Hydro', '158 Pumped Hydro',
       '166 Pumped Hydro', '205 Pumped Hydro', '228 Pumped Hydro',
       '235 Pumped Hydro', '25 Pumped Hydro', '266 Pumped Hydro',
       '268 Pumped Hydro', '279_220kV Pumped Hydro', '293 Pumped Hydro',
       '320 Pumped Hydro', '32_220kV Pumped Hydro', '333 Pumped Hydro',
       '342 Pumped Hydro', '343 Pumped Hydro', '362_220kV Pumped Hydro',
       '368 Pumped Hydro', '374 Pumped Hydro', '379 Pumped Hydro',
       '389 Pumped Hydro', '397 Pumped Hydro', '423 Pumped Hydro',
       '424 Pumped Hydro', '479 Pumped Hydro', '481 Pumped Hydro',
       '493 Pumped Hydro', '51 Pumped Hydro', '63 Pumped Hydro',
       '66 Pumped Hydro', '72 Pumped Hydro', '78_220kV Pumped Hydro',
       '8 Pumped Hydro', '98 Pumped Hydro'],
      dtype='object', name='StorageUnit')
WARNING:pypsa.consistency:The following transformers have zero r, which could break the linear load flow:
Index(['2', '5', '10', '12', '13', '15', '18', '20', '22', '24', '26', '30',
       '32', '37', '42', '46', '52', '56', '61', '68', '69', '74', '78', '86',
       '87', '94', '95', '96', '99', '100', '104', '105', '106', '107', '117',
       '120', '123', '124', '125', '128', '129', '138', '143', '156', '157',
       '159', '160', '165', '184', '191', '195', '201', '220', '231', '232',
       '233', '236', '247', '248', '250', '251', '252', '261', '263', '264',
       '267', '272', '279', '281', '282', '292', '303', '307', '308', '312',
       '315', '317', '322', '332', '334', '336', '338', '351', '353', '360',
       '362', '382', '384', '385', '391', '403', '404', '413', '421', '450',
       '458'],
      dtype='object', name='Transformer')
WARNING:pypsa.consistency:The following buses have carriers which are not defined:
Index(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
       ...
       '382_220kV', '384_220kV', '385_220kV', '391_220kV', '403_220kV',
       '404_220kV', '413_220kV', '421_220kV', '450_220kV', '458_220kV'],
      dtype='object', name='Bus', length=585)
WARNING:pypsa.consistency:The following sub_networks have carriers which are not defined:
Index(['0'], dtype='object', name='SubNetwork')
WARNING:pypsa.consistency:The following lines have carriers which are not defined:
Index(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
       ...
       '850', '851', '852', '853', '854', '855', '856', '857', '858', '859'],
      dtype='object', name='Line', length=852)
WARNING:pypsa.consistency:The following generators have carriers which are not defined:
Index(['1 Gas', '1 Hard Coal', '102 Gas', '108 Run of River', '108 Waste',
       '111 Gas', '112 Gas', '112 Run of River', '114 Hard Coal',
       '115 Brown Coal',
       ...
       '382_220kV Solar ramp down', '384_220kV Solar ramp down',
       '385_220kV Solar ramp down', '391_220kV Solar ramp down',
       '403_220kV Solar ramp down', '404_220kV Solar ramp down',
       '413_220kV Solar ramp down', '421_220kV Solar ramp down',
       '450_220kV Solar ramp down', '458_220kV Solar ramp down'],
      dtype='object', name='Generator', length=4269)
WARNING:pypsa.consistency:The following storage_units have carriers which are not defined:
Index(['100_220kV Pumped Hydro', '114 Pumped Hydro', '121 Pumped Hydro',
       '140 Pumped Hydro', '141 Pumped Hydro', '158 Pumped Hydro',
       '166 Pumped Hydro', '205 Pumped Hydro', '228 Pumped Hydro',
       '235 Pumped Hydro', '25 Pumped Hydro', '266 Pumped Hydro',
       '268 Pumped Hydro', '279_220kV Pumped Hydro', '293 Pumped Hydro',
       '320 Pumped Hydro', '32_220kV Pumped Hydro', '333 Pumped Hydro',
       '342 Pumped Hydro', '343 Pumped Hydro', '362_220kV Pumped Hydro',
       '368 Pumped Hydro', '374 Pumped Hydro', '379 Pumped Hydro',
       '389 Pumped Hydro', '397 Pumped Hydro', '423 Pumped Hydro',
       '424 Pumped Hydro', '479 Pumped Hydro', '481 Pumped Hydro',
       '493 Pumped Hydro', '51 Pumped Hydro', '63 Pumped Hydro',
       '66 Pumped Hydro', '72 Pumped Hydro', '78_220kV Pumped Hydro',
       '8 Pumped Hydro', '98 Pumped Hydro'],
      dtype='object', name='StorageUnit')
WARNING:pypsa.consistency:The following transformers have zero r, which could break the linear load flow:
Index(['2', '5', '10', '12', '13', '15', '18', '20', '22', '24', '26', '30',
       '32', '37', '42', '46', '52', '56', '61', '68', '69', '74', '78', '86',
       '87', '94', '95', '96', '99', '100', '104', '105', '106', '107', '117',
       '120', '123', '124', '125', '128', '129', '138', '143', '156', '157',
       '159', '160', '165', '184', '191', '195', '201', '220', '231', '232',
       '233', '236', '247', '248', '250', '251', '252', '261', '263', '264',
       '267', '272', '279', '281', '282', '292', '303', '307', '308', '312',
       '315', '317', '322', '332', '334', '336', '338', '351', '353', '360',
       '362', '382', '384', '385', '391', '403', '404', '413', '421', '450',
       '458'],
      dtype='object', name='Transformer')
WARNING:pypsa.consistency:The following buses have carriers which are not defined:
Index(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
       ...
       '382_220kV', '384_220kV', '385_220kV', '391_220kV', '403_220kV',
       '404_220kV', '413_220kV', '421_220kV', '450_220kV', '458_220kV'],
      dtype='object', name='Bus', length=585)
WARNING:pypsa.consistency:The following sub_networks have carriers which are not defined:
Index(['0'], dtype='object', name='SubNetwork')
WARNING:pypsa.consistency:The following lines have carriers which are not defined:
Index(['1', '2', '3', '4', '5', '6', '7', '8', '9', '10',
       ...
       '850', '851', '852', '853', '854', '855', '856', '857', '858', '859'],
      dtype='object', name='Line', length=852)
WARNING:pypsa.consistency:The following generators have carriers which are not defined:
Index(['1 Gas', '1 Hard Coal', '102 Gas', '108 Run of River', '108 Waste',
       '111 Gas', '112 Gas', '112 Run of River', '114 Hard Coal',
       '115 Brown Coal',
       ...
       '382_220kV Solar ramp down', '384_220kV Solar ramp down',
       '385_220kV Solar ramp down', '391_220kV Solar ramp down',
       '403_220kV Solar ramp down', '404_220kV Solar ramp down',
       '413_220kV Solar ramp down', '421_220kV Solar ramp down',
       '450_220kV Solar ramp down', '458_220kV Solar ramp down'],
      dtype='object', name='Generator', length=4269)
INFO:linopy.model: Solve problem using Highs solver
INFO:linopy.io: Writing time: 0.21s
INFO:linopy.solvers:Log file at /tmp/highs.log
INFO:linopy.constants: Optimization successful:
Status: ok
Termination condition: optimal
Solution: 5331 primals, 11649 duals
Objective: 4.99e+05
Solver model: available
Solver message: optimal

Running HiGHS 1.7.1 (git hash: 0c240d8): Copyright (c) 2024 HiGHS under MIT licence terms
Coefficient ranges:
  Matrix [1e-02, 2e+02]
  Cost   [2e+00, 2e+02]
  Bound  [0e+00, 0e+00]
  RHS    [2e-19, 6e+03]
Presolving model
817 rows, 2277 cols, 5145 nonzeros  0s
559 rows, 2005 cols, 4761 nonzeros  0s
542 rows, 1358 cols, 4038 nonzeros  0s
527 rows, 1338 cols, 4105 nonzeros  0s
Presolve : Reductions: rows 527(-11122); columns 1338(-3993); elements 4105(-15284)
Solving the presolved LP
Using EKK dual simplex solver - serial
  Iteration        Objective     Infeasibilities num(sum)
          0     0.0000000000e+00 Ph1: 0(0) 0s
        645     4.9929741194e+05 Pr: 0(0); Du: 0(3.69482e-13) 0s
Solving the original LP from the solution after postsolve
Model   status      : Optimal
Simplex   iterations: 645
Objective value     :  4.9929741194e+05
HiGHS run time      :          0.09
INFO:pypsa.optimization.optimize:The shadow-prices of the constraints Generator-fix-p-lower, Generator-fix-p-upper, Line-fix-s-lower, Line-fix-s-upper, Transformer-fix-s-lower, Transformer-fix-s-upper, StorageUnit-fix-p_dispatch-lower, StorageUnit-fix-p_dispatch-upper, StorageUnit-fix-p_store-lower, StorageUnit-fix-p_store-upper, StorageUnit-fix-state_of_charge-lower, StorageUnit-fix-state_of_charge-upper, Kirchhoff-Voltage-Law, StorageUnit-energy_balance were not assigned to the network.
[17]:
('ok', 'optimal')

Costs are now 502 k€ compared to 301 k€.