Note
You can download this example as a Jupyter notebook or start it in interactive mode.
Non-linear power flow after LOPF#
In this example, the dispatch of generators is optimised using the linear OPF, then a non-linear power flow is run on the resulting dispatch.
Data sources#
Grid: based on SciGRID Version 0.2 which is based on OpenStreetMap.
Load size and location: based on Landkreise (NUTS 3) GDP and population.
Load time series: from ENTSO-E hourly data, scaled up uniformly by factor 1.12 (a simplification of the methodology in Schumacher, Hirth (2015)).
Conventional power plant capacities and locations: BNetzA list.
Wind and solar capacities and locations: EEG Stammdaten, based on http://www.energymap.info/download.html, which represents capacities at the end of 2014. Units without PLZ are removed.
Wind and solar time series: REatlas, Andresen et al, “Validation of Danish wind time series from a new global renewable energy atlas for energy system analysis,” Energy 93 (2015) 1074 - 1088.
Where SciGRID nodes have been split into 220kV and 380kV substations, all load and generation is attached to the 220kV substation.
Warnings#
The data behind the notebook is no longer supported. See PyPSA/pypsa-eur for a newer model that covers the whole of Europe.
This dataset is ONLY intended to demonstrate the capabilities of PyPSA and is NOT (yet) accurate enough to be used for research purposes.
Known problems include:
Rough approximations have been made for missing grid data, e.g. 220kV-380kV transformers and connections between close sub-stations missing from OSM.
There appears to be some unexpected congestion in parts of the network, which may mean for example that the load attachment method (by Voronoi cell overlap with Landkreise) isn’t working, particularly in regions with a high density of substations.
Attaching power plants to the nearest high voltage substation may not reflect reality.
There is no proper n-1 security in the calculations - this can either be simulated with a blanket e.g. 70% reduction in thermal limits (as done here) or a proper security constrained OPF (see e.g. http://www.pypsa.org/examples/scigrid-sclopf.ipynb).
The borders and neighbouring countries are not represented.
Hydroelectric power stations are not modelled accurately.
The marginal costs are illustrative, not accurate.
Only the first day of 2011 is in the github dataset, which is not representative. The full year of 2011 can be downloaded at http://www.pypsa.org/examples/scigrid-with-load-gen-trafos-2011.zip.
The ENTSO-E total load for Germany may not be scaled correctly; it is scaled up uniformly by factor 1.12 (a simplification of the methodology in Schumacher, Hirth (2015), which suggests monthly factors).
Biomass from the EEG Stammdaten are not read in at the moment.
Power plant start up costs, ramping limits/costs, minimum loading rates are not considered.
[1]:
import pypsa
import numpy as np
import pandas as pd
import os
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
[2]:
network = pypsa.examples.scigrid_de(from_master=True)
WARNING:pypsa.io:Importing network from PyPSA version v0.17.1 while current version is v0.23.0. 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
Plot the distribution of the load and of generating tech
[3]:
fig, ax = plt.subplots(
1, 1, subplot_kw={"projection": ccrs.EqualEarth()}, figsize=(8, 8)
)
load_distribution = (
network.loads_t.p_set.loc[network.snapshots[0]].groupby(network.loads.bus).sum()
)
network.plot(bus_sizes=1e-5 * load_distribution, ax=ax, title="Load distribution");
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.23.0/lib/python3.11/site-packages/cartopy/mpl/style.py:76: UserWarning: facecolor will have no effect as it has been defined as "never".
warnings.warn('facecolor will have no effect as it has been '
[4]:
network.generators.groupby("carrier")["p_nom"].sum()
[4]:
carrier
Brown Coal 20879.500000
Gas 23913.130000
Geothermal 31.700000
Hard Coal 25312.600000
Multiple 152.700000
Nuclear 12068.000000
Oil 2710.200000
Other 3027.800000
Run of River 3999.100000
Solar 37041.524779
Storage Hydro 1445.000000
Waste 1645.900000
Wind Offshore 2973.500000
Wind Onshore 37339.895329
Name: p_nom, dtype: float64
[5]:
network.storage_units.groupby("carrier")["p_nom"].sum()
[5]:
carrier
Pumped Hydro 9179.5
Name: p_nom, dtype: float64
[6]:
techs = ["Gas", "Brown Coal", "Hard Coal", "Wind Offshore", "Wind Onshore", "Solar"]
n_graphs = len(techs)
n_cols = 3
if n_graphs % n_cols == 0:
n_rows = n_graphs // n_cols
else:
n_rows = n_graphs // n_cols + 1
fig, axes = plt.subplots(
nrows=n_rows, ncols=n_cols, subplot_kw={"projection": ccrs.EqualEarth()}
)
size = 6
fig.set_size_inches(size * n_cols, size * n_rows)
for i, tech in enumerate(techs):
i_row = i // n_cols
i_col = i % n_cols
ax = axes[i_row, i_col]
gens = network.generators[network.generators.carrier == tech]
gen_distribution = (
gens.groupby("bus").sum()["p_nom"].reindex(network.buses.index, fill_value=0.0)
)
network.plot(ax=ax, bus_sizes=2e-5 * gen_distribution)
ax.set_title(tech)
fig.tight_layout()
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.23.0/lib/python3.11/site-packages/cartopy/mpl/style.py:76: UserWarning: facecolor will have no effect as it has been defined as "never".
warnings.warn('facecolor will have no effect as it has been '
Run Linear Optimal Power Flow on the first day of 2011.
To approximate n-1 security and allow room for reactive power flows, don’t allow any line to be loaded above 70% of their thermal rating
[7]:
contingency_factor = 0.7
network.lines.s_max_pu = contingency_factor
There are some infeasibilities without small extensions
[8]:
network.lines.loc[["316", "527", "602"], "s_nom"] = 1715
We performing a linear OPF for one day, 4 snapshots at a time.
[9]:
group_size = 4
network.storage_units.state_of_charge_initial = 0.0
for i in range(int(24 / group_size)):
# set the initial state of charge based on previous round
if i:
network.storage_units.state_of_charge_initial = (
network.storage_units_t.state_of_charge.loc[
network.snapshots[group_size * i - 1]
]
)
network.optimize(
network.snapshots[group_size * i : group_size * i + group_size],
solver_name="cbc",
)
WARNING:pypsa.components: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.components: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')
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
INFO:linopy.model: Solve linear problem using Cbc solver
INFO:linopy.io:Writing objective.
Writing constraints.: 100%|██████████| 15/15 [00:00<00:00, 62.85it/s]
Writing variables.: 100%|██████████| 7/7 [00:00<00:00, 221.37it/s]
INFO:linopy.io: Writing time: 0.31s
INFO:linopy.constants: Optimization successful:
Status: ok
Termination condition: optimal
Solution: 9940 primals, 23828 duals
Objective: 1.45e+06
Solver model: not available
Solver message: Optimal - objective value 1449687.25014697
Welcome to the CBC MILP Solver
Version: 2.10.10
Build Date: Apr 19 2023
command line - cbc -printingOptions all -import /tmp/linopy-problem-ps78_0si.lp -solve -solu /tmp/linopy-solve-ock283r4.sol (default strategy 1)
Option for printingOptions changed from normal to all
Presolve 2380 (-21448) rows, 4329 (-5611) columns and 15526 (-28700) elements
Perturbing problem by 0.001% of 2240.9252 - largest nonzero change 0.00099749507 ( 0.014846054%) - largest zero change 0.00099738508
0 Obj 88144.088 Primal inf 5298659.3 (2175) Dual inf 553.3846 (4)
122 Obj 18792.774 Primal inf 3913238.1 (2148)
244 Obj 18792.774 Primal inf 3676039.4 (2091)
366 Obj 18792.774 Primal inf 3021292.7 (2032)
488 Obj 18797.516 Primal inf 2662834.2 (1978)
610 Obj 18798.21 Primal inf 4473914.7 (1977)
732 Obj 18799.54 Primal inf 3264547.1 (1945)
854 Obj 18802.341 Primal inf 3442396 (1885)
976 Obj 18803.112 Primal inf 3907815.5 (1850)
1098 Obj 18806.652 Primal inf 68739944 (1740)
1220 Obj 18808.249 Primal inf 81732895 (1672)
1342 Obj 18810.458 Primal inf 35392259 (1545)
1464 Obj 22628.294 Primal inf 34747600 (1439)
1586 Obj 22631.335 Primal inf 39131896 (1369)
1708 Obj 22634.369 Primal inf 6592748.5 (1265)
1830 Obj 22638.666 Primal inf 3108955.9 (1163)
1952 Obj 22642.233 Primal inf 4769544.2 (1090)
2074 Obj 22681.019 Primal inf 11952750 (1127)
2196 Obj 173937.66 Primal inf 12025391 (1016)
2318 Obj 218125.34 Primal inf 4431494.9 (941)
2440 Obj 440392.46 Primal inf 1964679.1 (684)
2562 Obj 789101.36 Primal inf 295127.86 (595)
2684 Obj 1127777.1 Primal inf 37967.095 (281)
2806 Obj 1311398.2 Primal inf 11391.813 (175)
2928 Obj 1422205.5 Primal inf 3118.6274 (86)
3050 Obj 1449121.7 Primal inf 168.50409 (27)
3101 Obj 1449695.5
3101 Obj 1449687.3 Dual inf 0.00089529348 (2)
3104 Obj 1449687.3
Optimal - objective value 1449687.3
After Postsolve, objective 1449687.3, infeasibilities - dual 186.92063 (6), primal 1.3870423e-06 (6)
Presolved model was optimal, full model needs cleaning up
0 Obj 1449687.3 Dual inf 12.306893 (14)
End of values pass after 0 iterations
0 Obj 1449687.3 Dual inf 12.306893 (14) w.o. free dual inf (12)
End of values pass after 8 iterations
8 Obj 1449687.3 Dual inf 10.437687 (8) w.o. free dual inf (6)
10 Obj 1449687.3
Optimal - objective value 1449687.3
Optimal objective 1449687.25 - 3114 iterations time 0.382, Presolve 0.02
Total time (CPU seconds): 0.58 (Wallclock seconds): 0.55
WARNING:pypsa.components: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.components: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')
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
INFO:linopy.model: Solve linear problem using Cbc solver
INFO:linopy.io:Writing objective.
Writing constraints.: 100%|██████████| 15/15 [00:00<00:00, 64.73it/s]
Writing variables.: 100%|██████████| 7/7 [00:00<00:00, 226.55it/s]
INFO:linopy.io: Writing time: 0.3s
INFO:linopy.constants: Optimization successful:
Status: ok
Termination condition: optimal
Solution: 9940 primals, 23828 duals
Objective: 8.74e+05
Solver model: not available
Solver message: Optimal - objective value 873763.90232907
Welcome to the CBC MILP Solver
Version: 2.10.10
Build Date: Apr 19 2023
command line - cbc -printingOptions all -import /tmp/linopy-problem-h4deea38.lp -solve -solu /tmp/linopy-solve-83ijgo5z.sol (default strategy 1)
Option for printingOptions changed from normal to all
Presolve 2403 (-21425) rows, 4362 (-5578) columns and 15744 (-28482) elements
Perturbing problem by 0.001% of 3070.478 - largest nonzero change 0.00099870555 ( 0.015179458%) - largest zero change 0.00099582028
0 Obj 81183.874 Primal inf 5108274.1 (2203) Dual inf 1043.2235 (4)
123 Obj 11832.559 Primal inf 3658988.9 (2161)
246 Obj 11832.559 Primal inf 3498053.5 (2103)
369 Obj 11833.961 Primal inf 3111221.3 (2076)
492 Obj 11834.125 Primal inf 3090398 (2006)
615 Obj 11835.057 Primal inf 3097681.1 (1940)
738 Obj 11837.729 Primal inf 2600358.1 (1878)
861 Obj 11840.049 Primal inf 2533201.7 (1821)
984 Obj 11842.114 Primal inf 22123968 (1784)
1107 Obj 11842.555 Primal inf 20665844 (1739)
1230 Obj 11845.314 Primal inf 13081951 (1656)
1353 Obj 11847.053 Primal inf 21997502 (1583)
1476 Obj 11849.762 Primal inf 24459627 (1476)
1599 Obj 11851.969 Primal inf 22285329 (1502)
1722 Obj 11855.302 Primal inf 28615222 (1437)
1845 Obj 11859.923 Primal inf 45814228 (1454)
1968 Obj 11865.676 Primal inf 15650037 (1015)
2091 Obj 26245.831 Primal inf 8519288.5 (1246)
2214 Obj 93471.772 Primal inf 7248911.4 (993)
2337 Obj 119576.58 Primal inf 1127730.5 (699)
2460 Obj 277547.31 Primal inf 2825341.6 (653)
2583 Obj 391310.18 Primal inf 13957155 (743)
2706 Obj 587466.74 Primal inf 69440.057 (310)
2829 Obj 746208.23 Primal inf 1250812.7 (445)
2952 Obj 834150.05 Primal inf 13948.832 (146)
3075 Obj 867929.52 Primal inf 1071.5131 (62)
3168 Obj 873772.41
3168 Obj 873763.9 Dual inf 0.0007078415 (1)
3169 Obj 873763.9
Optimal - objective value 873763.9
After Postsolve, objective 873763.9, infeasibilities - dual 78.034695 (3), primal 9.1550879e-07 (3)
Presolved model was optimal, full model needs cleaning up
0 Obj 873763.9 Dual inf 0.78034665 (3)
End of values pass after 3 iterations
3 Obj 873763.9
Optimal - objective value 873763.9
Optimal objective 873763.9023 - 3172 iterations time 0.392, Presolve 0.02
Total time (CPU seconds): 0.59 (Wallclock seconds): 0.56
WARNING:pypsa.components: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.components: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')
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
INFO:linopy.model: Solve linear problem using Cbc solver
INFO:linopy.io:Writing objective.
Writing constraints.: 100%|██████████| 15/15 [00:00<00:00, 63.09it/s]
Writing variables.: 100%|██████████| 7/7 [00:00<00:00, 225.13it/s]
INFO:linopy.io: Writing time: 0.31s
INFO:linopy.constants: Optimization successful:
Status: ok
Termination condition: optimal
Solution: 9940 primals, 23828 duals
Objective: 7.91e+05
Solver model: not available
Solver message: Optimal - objective value 790786.59488191
Welcome to the CBC MILP Solver
Version: 2.10.10
Build Date: Apr 19 2023
command line - cbc -printingOptions all -import /tmp/linopy-problem-6ah_fy3j.lp -solve -solu /tmp/linopy-solve-c9k12ini.sol (default strategy 1)
Option for printingOptions changed from normal to all
Presolve 2466 (-21362) rows, 4425 (-5515) columns and 15973 (-28253) elements
Perturbing problem by 0.001% of 2240.9252 - largest nonzero change 0.00099117356 ( 0.0093201145%) - largest zero change 0.00098986715
0 Obj -44.584898 Primal inf 5220251.7 (2269)
124 Obj -44.584898 Primal inf 4103124.4 (2238)
248 Obj -44.584898 Primal inf 3420602.7 (2174)
372 Obj -40.256823 Primal inf 2983360.6 (2126)
496 Obj -37.582136 Primal inf 2700106.3 (2077)
620 Obj -36.185086 Primal inf 8567154 (2067)
744 Obj -34.92718 Primal inf 5142053.5 (2039)
868 Obj -32.380491 Primal inf 5594235.8 (1921)
992 Obj -30.416509 Primal inf 7927578.8 (1851)
1116 Obj -28.638856 Primal inf 12527217 (1763)
1240 Obj -26.146098 Primal inf 4812276.2 (1650)
1364 Obj -24.434687 Primal inf 9264882.4 (1604)
1488 Obj -22.005948 Primal inf 6585190.1 (1630)
1612 Obj -18.938605 Primal inf 12208133 (1496)
1736 Obj 7644.8319 Primal inf 7418446.4 (1378)
1860 Obj 7648.4993 Primal inf 2502777.6 (1162)
1984 Obj 7652.1304 Primal inf 1605687.6 (1032)
2108 Obj 7657.2909 Primal inf 2141736.5 (975)
2232 Obj 7727.0947 Primal inf 943120.44 (794)
2356 Obj 7786.6143 Primal inf 5789342.8 (969)
2480 Obj 82108.081 Primal inf 3747810.8 (740)
2604 Obj 251407.47 Primal inf 3237928.5 (660)
2728 Obj 393492.32 Primal inf 1255745.8 (538)
2852 Obj 605162.73 Primal inf 100552.45 (258)
2976 Obj 703797.58 Primal inf 10363.57 (169)
3100 Obj 779663.59 Primal inf 1661.7557 (82)
3224 Obj 790554.19 Primal inf 10188.046 (58)
3273 Obj 790797.17
Optimal - objective value 790786.59
After Postsolve, objective 790786.59, infeasibilities - dual 7.9999999 (1), primal 4.8500652e-07 (1)
Presolved model was optimal, full model needs cleaning up
0 Obj 790786.59 Dual inf 0.0799999 (1)
End of values pass after 1 iterations
1 Obj 790786.59
Optimal - objective value 790786.59
Optimal objective 790786.5949 - 3274 iterations time 0.402, Presolve 0.02
Total time (CPU seconds): 0.59 (Wallclock seconds): 0.56
WARNING:pypsa.components: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.components: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')
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
INFO:linopy.model: Solve linear problem using Cbc solver
INFO:linopy.io:Writing objective.
Writing constraints.: 100%|██████████| 15/15 [00:00<00:00, 62.64it/s]
Writing variables.: 100%|██████████| 7/7 [00:00<00:00, 223.73it/s]
INFO:linopy.io: Writing time: 0.31s
INFO:linopy.constants: Optimization successful:
Status: ok
Termination condition: optimal
Solution: 9940 primals, 23828 duals
Objective: 1.46e+06
Solver model: not available
Solver message: Optimal - objective value 1455232.67827293
Welcome to the CBC MILP Solver
Version: 2.10.10
Build Date: Apr 19 2023
command line - cbc -printingOptions all -import /tmp/linopy-problem-mdnoq1x6.lp -solve -solu /tmp/linopy-solve-l9t_va9l.sol (default strategy 1)
Option for printingOptions changed from normal to all
Presolve 2450 (-21378) rows, 4425 (-5515) columns and 15937 (-28289) elements
Perturbing problem by 0.001% of 2240.9252 - largest nonzero change 0.00099880288 ( 0.010047233%) - largest zero change 0.0009976219
0 Obj 25308.261 Primal inf 5265409 (2267) Dual inf 247.5123 (1)
124 Obj 7970.4323 Primal inf 4163908.6 (2235)
248 Obj 7970.4323 Primal inf 3942473.4 (2187)
372 Obj 7970.4323 Primal inf 5913333.2 (2175)
496 Obj 7974.7219 Primal inf 3448768.4 (2098)
620 Obj 7978.9685 Primal inf 4425602.1 (2075)
744 Obj 7980.7471 Primal inf 3741758.5 (1998)
868 Obj 7983.9775 Primal inf 3025995.6 (1896)
992 Obj 7985.6157 Primal inf 3509923.7 (1836)
1116 Obj 7986.4856 Primal inf 2945161.6 (1764)
1240 Obj 7988.5425 Primal inf 5032595.6 (1744)
1364 Obj 7990.8858 Primal inf 4881470.3 (1654)
1488 Obj 12744.434 Primal inf 7775493.6 (1629)
1612 Obj 12746.795 Primal inf 4950056.1 (1493)
1736 Obj 23731.57 Primal inf 3495643.6 (1406)
1860 Obj 23735.001 Primal inf 36452432 (1403)
1984 Obj 23740.247 Primal inf 12407112 (1229)
2108 Obj 31295.75 Primal inf 1490729.7 (976)
2232 Obj 79549.243 Primal inf 1128898 (697)
2356 Obj 117110.24 Primal inf 5168696.9 (807)
2480 Obj 341872.75 Primal inf 1058342.1 (631)
2604 Obj 640245.65 Primal inf 1721167.3 (721)
2728 Obj 1010085.2 Primal inf 52753.257 (351)
2852 Obj 1262400.9 Primal inf 17774.604 (252)
2976 Obj 1402538.6 Primal inf 6379.0641 (139)
3100 Obj 1440540.1 Primal inf 2585.3527 (72)
3224 Obj 1455068.7 Primal inf 20.056235 (18)
3241 Obj 1455243.6
Optimal - objective value 1455232.7
After Postsolve, objective 1455232.7, infeasibilities - dual 24.259813 (1), primal 6.0436272e-07 (1)
Presolved model was optimal, full model needs cleaning up
0 Obj 1455232.7 Dual inf 0.29007703 (2)
End of values pass after 0 iterations
0 Obj 1455232.7 Dual inf 0.29007703 (2) w.o. free dual inf (1)
End of values pass after 1 iterations
1 Obj 1455232.7 Dual inf 0.047479 (1) w.o. free dual inf (0)
2 Obj 1455232.7
Optimal - objective value 1455232.7
Optimal objective 1455232.678 - 3243 iterations time 0.402, Presolve 0.02
Total time (CPU seconds): 0.60 (Wallclock seconds): 0.57
WARNING:pypsa.components: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.components: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')
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
INFO:linopy.model: Solve linear problem using Cbc solver
INFO:linopy.io:Writing objective.
Writing constraints.: 100%|██████████| 15/15 [00:00<00:00, 64.03it/s]
Writing variables.: 100%|██████████| 7/7 [00:00<00:00, 222.71it/s]
INFO:linopy.io: Writing time: 0.31s
INFO:linopy.constants: Optimization successful:
Status: ok
Termination condition: optimal
Solution: 9940 primals, 23828 duals
Objective: 2.65e+06
Solver model: not available
Solver message: Optimal - objective value 2649026.44753696
Welcome to the CBC MILP Solver
Version: 2.10.10
Build Date: Apr 19 2023
command line - cbc -printingOptions all -import /tmp/linopy-problem-dx218r9d.lp -solve -solu /tmp/linopy-solve-553vso5z.sol (default strategy 1)
Option for printingOptions changed from normal to all
Presolve 2397 (-21431) rows, 4370 (-5570) columns and 15806 (-28420) elements
Perturbing problem by 0.001% of 2240.9252 - largest nonzero change 0.00099501233 ( 0.0099550754%) - largest zero change 0.00099429059
0 Obj 97176.272 Primal inf 5267954.4 (2232) Dual inf 990.04917 (4)
122 Obj 27996.499 Primal inf 3893927.7 (2188)
244 Obj 27996.499 Primal inf 3873699.5 (2149)
366 Obj 27996.499 Primal inf 4539384.7 (2120)
488 Obj 27997.447 Primal inf 5819207.4 (2077)
610 Obj 28006.083 Primal inf 4599924.5 (2004)
732 Obj 28008.02 Primal inf 3608164.8 (1921)
854 Obj 28009.228 Primal inf 4074478.4 (1867)
976 Obj 28009.714 Primal inf 3467745.5 (1787)
1098 Obj 28011.679 Primal inf 2952120.3 (1688)
1220 Obj 28014.085 Primal inf 4444161.8 (1658)
1342 Obj 28017.186 Primal inf 5525040.9 (1584)
1464 Obj 59480.236 Primal inf 2109331.4 (1413)
1586 Obj 59484.281 Primal inf 2296653 (1324)
1708 Obj 59488.006 Primal inf 2809372.2 (1280)
1830 Obj 59492.107 Primal inf 2808077.2 (1187)
1952 Obj 59497.442 Primal inf 3086809.6 (1044)
2074 Obj 73548.109 Primal inf 42404395 (1341)
2196 Obj 142289.61 Primal inf 83607795 (1386)
2318 Obj 467314.82 Primal inf 2.3388705e+08 (1133)
2440 Obj 1022511.1 Primal inf 14507336 (737)
2562 Obj 1523292.2 Primal inf 14426946 (567)
2684 Obj 1970336.7 Primal inf 323688.32 (324)
2806 Obj 2339169 Primal inf 37809.416 (292)
2928 Obj 2516521.7 Primal inf 17725.024 (193)
3050 Obj 2617878.7 Primal inf 46547.941 (224)
3172 Obj 2643414.1 Primal inf 1604.7586 (70)
3252 Obj 2649046.2
Optimal - objective value 2649026.4
After Postsolve, objective 2649026.4, infeasibilities - dual 165.36547 (4), primal 1.0356107e-06 (4)
Presolved model was optimal, full model needs cleaning up
0 Obj 2649026.4 Dual inf 1.6536543 (4)
End of values pass after 6 iterations
6 Obj 2649026.4
Optimal - objective value 2649026.4
Optimal objective 2649026.448 - 3258 iterations time 0.392, Presolve 0.02
Total time (CPU seconds): 0.55 (Wallclock seconds): 0.55
WARNING:pypsa.components: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.components: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')
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
<__array_function__ internals>:200: RuntimeWarning: invalid value encountered in cast
INFO:linopy.model: Solve linear problem using Cbc solver
INFO:linopy.io:Writing objective.
Writing constraints.: 100%|██████████| 15/15 [00:00<00:00, 64.16it/s]
Writing variables.: 100%|██████████| 7/7 [00:00<00:00, 220.72it/s]
INFO:linopy.io: Writing time: 0.3s
INFO:linopy.constants: Optimization successful:
Status: ok
Termination condition: optimal
Solution: 9940 primals, 23828 duals
Objective: 2.14e+06
Solver model: not available
Solver message: Optimal - objective value 2142956.88872811
Welcome to the CBC MILP Solver
Version: 2.10.10
Build Date: Apr 19 2023
command line - cbc -printingOptions all -import /tmp/linopy-problem-bt4es_28.lp -solve -solu /tmp/linopy-solve-kq81zmwk.sol (default strategy 1)
Option for printingOptions changed from normal to all
Presolve 2403 (-21425) rows, 4376 (-5564) columns and 15832 (-28394) elements
Perturbing problem by 0.001% of 6880.5027 - largest nonzero change 0.00094531053 ( 0.0038408689%) - largest zero change 0.00093735584
0 Obj 92709.643 Primal inf 5294157.5 (2230) Dual inf 2421.7098 (4)
123 Obj 23358.678 Primal inf 3986691.9 (2187)
246 Obj 23358.678 Primal inf 3636007.5 (2158)
369 Obj 23358.678 Primal inf 3340400.7 (2095)
492 Obj 23359.019 Primal inf 3212825.3 (2043)
615 Obj 23359.78 Primal inf 3857273.7 (2034)
738 Obj 23361.59 Primal inf 3384191.3 (1959)
861 Obj 23363.047 Primal inf 3278099.8 (1924)
984 Obj 23364.324 Primal inf 3099244.2 (1829)
1107 Obj 23365.58 Primal inf 2832810.5 (1759)
1230 Obj 23366.8 Primal inf 5077389.2 (1718)
1353 Obj 23368.968 Primal inf 34944403 (1767)
1476 Obj 40819.856 Primal inf 39192825 (1679)
1599 Obj 40821.832 Primal inf 32531853 (1532)
1722 Obj 40824.498 Primal inf 6119840.8 (1482)
1845 Obj 40826.38 Primal inf 3320538.3 (1242)
1968 Obj 40828.583 Primal inf 6601247 (1287)
2091 Obj 41012.957 Primal inf 5889155.6 (1023)
2214 Obj 214570.46 Primal inf 5491671.7 (895)
2337 Obj 329648.53 Primal inf 39291819 (851)
2460 Obj 526049.21 Primal inf 1488711.7 (691)
2583 Obj 862846.79 Primal inf 248516.75 (399)
2706 Obj 1548968.3 Primal inf 167092.36 (302)
2829 Obj 1912777 Primal inf 11161.952 (206)
2952 Obj 2086971.7 Primal inf 2369.306 (116)
3075 Obj 2128633.5 Primal inf 656.14339 (75)
3176 Obj 2142962.1
Optimal - objective value 2142956.9
After Postsolve, objective 2142956.9, infeasibilities - dual 175.7239 (5), primal 1.1686308e-06 (5)
Presolved model was optimal, full model needs cleaning up
0 Obj 2142956.9 Dual inf 1.7572385 (5)
End of values pass after 8 iterations
8 Obj 2142956.9
Optimal - objective value 2142956.9
Optimal objective 2142956.889 - 3184 iterations time 0.372, Presolve 0.02
Total time (CPU seconds): 0.56 (Wallclock seconds): 0.53
[10]:
p_by_carrier = network.generators_t.p.groupby(network.generators.carrier, axis=1).sum()
p_by_carrier.drop(
(p_by_carrier.max()[p_by_carrier.max() < 1700.0]).index, axis=1, inplace=True
)
p_by_carrier.columns
[10]:
Index(['Brown Coal', 'Gas', 'Hard Coal', 'Nuclear', 'Run of River', 'Solar',
'Wind Offshore', 'Wind Onshore'],
dtype='object', name='carrier')
[11]:
colors = {
"Brown Coal": "brown",
"Hard Coal": "k",
"Nuclear": "r",
"Run of River": "green",
"Wind Onshore": "blue",
"Solar": "yellow",
"Wind Offshore": "cyan",
"Waste": "orange",
"Gas": "orange",
}
# reorder
cols = [
"Nuclear",
"Run of River",
"Brown Coal",
"Hard Coal",
"Gas",
"Wind Offshore",
"Wind Onshore",
"Solar",
]
p_by_carrier = p_by_carrier[cols]
[12]:
c = [colors[col] for col in p_by_carrier.columns]
fig, ax = plt.subplots(figsize=(12, 6))
(p_by_carrier / 1e3).plot(kind="area", ax=ax, linewidth=4, color=c, alpha=0.7)
ax.legend(ncol=4, loc="upper left")
ax.set_ylabel("GW")
ax.set_xlabel("")
fig.tight_layout()
[13]:
fig, ax = plt.subplots(figsize=(12, 6))
p_storage = network.storage_units_t.p.sum(axis=1)
state_of_charge = network.storage_units_t.state_of_charge.sum(axis=1)
p_storage.plot(label="Pumped hydro dispatch", ax=ax, linewidth=3)
state_of_charge.plot(label="State of charge", ax=ax, linewidth=3)
ax.legend()
ax.grid()
ax.set_ylabel("MWh")
ax.set_xlabel("")
fig.tight_layout()
[14]:
now = network.snapshots[4]
With the linear load flow, there is the following per unit loading:
[15]:
loading = network.lines_t.p0.loc[now] / network.lines.s_nom
loading.describe()
[15]:
count 852.000000
mean -0.002892
std 0.258575
min -0.700000
25% -0.129689
50% 0.003084
75% 0.122643
max 0.700000
dtype: float64
[16]:
fig, ax = plt.subplots(subplot_kw={"projection": ccrs.EqualEarth()}, figsize=(9, 9))
network.plot(
ax=ax,
line_colors=abs(loading),
line_cmap=plt.cm.jet,
title="Line loading",
bus_sizes=1e-3,
bus_alpha=0.7,
)
fig.tight_layout();
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.23.0/lib/python3.11/site-packages/cartopy/mpl/style.py:76: UserWarning: facecolor will have no effect as it has been defined as "never".
warnings.warn('facecolor will have no effect as it has been '
Let’s have a look at the marginal prices
[17]:
network.buses_t.marginal_price.loc[now].describe()
[17]:
count 585.000000
mean 15.737598
std 10.941995
min -10.397824
25% 6.992120
50% 15.841190
75% 25.048186
max 52.150120
Name: 2011-01-01 04:00:00, dtype: float64
[18]:
fig, ax = plt.subplots(subplot_kw={"projection": ccrs.PlateCarree()}, figsize=(8, 8))
plt.hexbin(
network.buses.x,
network.buses.y,
gridsize=20,
C=network.buses_t.marginal_price.loc[now],
cmap=plt.cm.jet,
zorder=3,
)
network.plot(ax=ax, line_widths=pd.Series(0.5, network.lines.index), bus_sizes=0)
cb = plt.colorbar(location="bottom")
cb.set_label("Locational Marginal Price (EUR/MWh)")
fig.tight_layout()
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.23.0/lib/python3.11/site-packages/cartopy/mpl/style.py:76: UserWarning: facecolor will have no effect as it has been defined as "never".
warnings.warn('facecolor will have no effect as it has been '
Curtailment variable#
By considering how much power is available and how much is generated, you can see what share is curtailed:
[19]:
carrier = "Wind Onshore"
capacity = network.generators.groupby("carrier").sum().at[carrier, "p_nom"]
p_available = network.generators_t.p_max_pu.multiply(network.generators["p_nom"])
p_available_by_carrier = p_available.groupby(network.generators.carrier, axis=1).sum()
p_curtailed_by_carrier = p_available_by_carrier - p_by_carrier
[20]:
p_df = pd.DataFrame(
{
carrier + " available": p_available_by_carrier[carrier],
carrier + " dispatched": p_by_carrier[carrier],
carrier + " curtailed": p_curtailed_by_carrier[carrier],
}
)
p_df[carrier + " capacity"] = capacity
[21]:
p_df["Wind Onshore curtailed"][p_df["Wind Onshore curtailed"] < 0.0] = 0.0
[22]:
fig, ax = plt.subplots(figsize=(10, 4))
p_df[[carrier + " dispatched", carrier + " curtailed"]].plot(
kind="area", ax=ax, linewidth=3
)
p_df[[carrier + " available", carrier + " capacity"]].plot(ax=ax, linewidth=3)
ax.set_xlabel("")
ax.set_ylabel("Power [MW]")
ax.set_ylim([0, 40000])
ax.legend()
fig.tight_layout()
Non-Linear Power Flow#
Now perform a full Newton-Raphson power flow on the first hour. For the PF, set the P to the optimised P.
[23]:
network.generators_t.p_set = network.generators_t.p
network.storage_units_t.p_set = network.storage_units_t.p
Set all buses to PV, since we don’t know what Q set points are
[24]:
network.generators.control = "PV"
# Need some PQ buses so that Jacobian doesn't break
f = network.generators[network.generators.bus == "492"]
network.generators.loc[f.index, "control"] = "PQ"
Now, perform the non-linear PF.
[25]:
info = network.pf();
INFO:pypsa.pf:Performing non-linear load-flow on AC sub-network SubNetwork 0 for snapshots DatetimeIndex(['2011-01-01 00:00:00', '2011-01-01 01:00:00',
'2011-01-01 02:00:00', '2011-01-01 03:00:00',
'2011-01-01 04:00:00', '2011-01-01 05:00:00',
'2011-01-01 06:00:00', '2011-01-01 07:00:00',
'2011-01-01 08:00:00', '2011-01-01 09:00:00',
'2011-01-01 10:00:00', '2011-01-01 11:00:00',
'2011-01-01 12:00:00', '2011-01-01 13:00:00',
'2011-01-01 14:00:00', '2011-01-01 15:00:00',
'2011-01-01 16:00:00', '2011-01-01 17:00:00',
'2011-01-01 18:00:00', '2011-01-01 19:00:00',
'2011-01-01 20:00:00', '2011-01-01 21:00:00',
'2011-01-01 22:00:00', '2011-01-01 23:00:00'],
dtype='datetime64[ns]', name='snapshot', freq=None)
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.047050 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.046404 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.046934 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.046306 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.046268 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.046489 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.046864 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.047729 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.046389 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.046826 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.046838 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.046469 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.046797 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.046616 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.046969 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.048192 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.046718 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.047584 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.047398 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.047128 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.047003 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.047146 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.047751 seconds
INFO:pypsa.pf:Newton-Raphson solved in 4 iterations with error of 0.000000 in 0.048307 seconds
Any failed to converge?
[26]:
(~info.converged).any().any()
[26]:
False
With the non-linear load flow, there is the following per unit loading of the full thermal rating.
[27]:
(network.lines_t.p0.loc[now] / network.lines.s_nom).describe()
[27]:
count 852.000000
mean 0.000434
std 0.260926
min -0.813358
25% -0.125478
50% 0.003032
75% 0.126695
max 0.827178
dtype: float64
Let’s inspect the voltage angle differences across the lines have (in degrees)
[28]:
df = network.lines.copy()
for b in ["bus0", "bus1"]:
df = pd.merge(
df, network.buses_t.v_ang.loc[[now]].T, how="left", left_on=b, right_index=True
)
s = df[str(now) + "_x"] - df[str(now) + "_y"]
(s * 180 / np.pi).describe()
[28]:
count 852.000000
mean -0.022840
std 2.373703
min -12.158621
25% -0.463026
50% 0.001586
75% 0.537443
max 17.959258
dtype: float64
Plot the reactive power
[29]:
fig, ax = plt.subplots(subplot_kw={"projection": ccrs.EqualEarth()}, figsize=(9, 9))
q = network.buses_t.q.loc[now]
bus_colors = pd.Series("r", network.buses.index)
bus_colors[q < 0.0] = "b"
network.plot(
bus_sizes=1e-4 * abs(q),
ax=ax,
bus_colors=bus_colors,
title="Reactive power feed-in (red=+ve, blue=-ve)",
);
/home/docs/checkouts/readthedocs.org/user_builds/pypsa/conda/v0.23.0/lib/python3.11/site-packages/cartopy/mpl/style.py:76: UserWarning: facecolor will have no effect as it has been defined as "never".
warnings.warn('facecolor will have no effect as it has been '