Validation 11 - Global Reserves


In [1]:
%matplotlib inline

In [2]:
import psst

In [3]:
from psst.case import read_matpower
from psst.network import create_network
import pandas as pd

Validation of case 1


In [4]:
case = read_matpower('./cases/case7.m')

In [5]:
case.reserve_factor = 0.5

In [6]:
case.load = pd.read_csv('./cases/case7.csv', index_col=0)

In [7]:
network = create_network(case, prog='neato')
network.draw()



In [8]:
case


Out[8]:
<psst.case.PSSTCase(name=casematpower, Generators=2, Buses=2, Branches=1)>

In [9]:
case.bus


Out[9]:
TYPE PD QD GS BS AREA VM VA BASEKV ZONE VMAX VMIN
Bus1 3 0 131.47 0 0 1 1 0 230 1 1.1 0.9
Bus2 2 100 0.00 0 0 1 1 0 230 1 1.1 0.9

In [10]:
case.branch


Out[10]:
F_BUS T_BUS BR_R BR_X BR_B RATE_A RATE_B RATE_C TAP SHIFT BR_STATUS ANGMIN ANGMAX
0 Bus1 Bus2 0.00281 0.0281 0.00712 800 800 800 0 0 1 -360 360

In [11]:
case.gen


Out[11]:
GEN_BUS PG QG QMAX QMIN VG MBASE GEN_STATUS PMAX PMIN PC1 PC2 QC1MIN QC1MAX QC2MIN QC2MAX RAMP_AGC RAMP_10 RAMP_30 RAMP_Q APF STARTUP_RAMP SHUTDOWN_RAMP MINIMUM_UP_TIME MINIMUM_DOWN_TIME
GenCo0 Bus1 200 0 30 -30 1 100 1 200 0 0 0 0 0 0 0 0 200 0 0 0 200 200 0 0
GenCo1 Bus2 500 0 30 -30 1 100 1 500 0 0 0 0 0 0 0 0 500 0 0 0 500 500 0 0

In [12]:
case.gencost


Out[12]:
MODEL STARTUP SHUTDOWN NCOST COST_1 COST_0
GenCo0 1 0 0 2 10 0
GenCo1 1 5000 1000 2 14 2000

In [13]:
import matplotlib.pyplot as plt

In [14]:
fig, axs = plt.subplots(1, 1, figsize=(8, 5))
ax = axs
case.load['Bus2'].plot.bar(ax=ax)
ax.set_ylim(0, 500);



In [15]:
from psst.model import build_model

In [16]:
model = build_model(case)

In [17]:
model


Out[17]:
<psst.model.PSSTModel(status=None)>

In [18]:
model.solve(solver='cbc', verbose=True)


Welcome to the CBC MILP Solver 
Version: 2.9.6 
Build Date: May 27 2016 

command line - /usr/local/bin/cbc -mipgap 0.01 -printingOptions all -import /var/folders/wk/lcf0vgd90bx0vq1873tn04knk_djr3/T/tmpkarPPc.pyomo.lp -import -stat=1 -solve -solu /var/folders/wk/lcf0vgd90bx0vq1873tn04knk_djr3/T/tmpkarPPc.pyomo.soln (default strategy 1)
No match for mipgap - ? for list of commands
No match for 0.01 - ? for list of commands
Option for printingOptions changed from normal to all
Current default (if $ as parameter) for import is /var/folders/wk/lcf0vgd90bx0vq1873tn04knk_djr3/T/tmpkarPPc.pyomo.lp
Presolve 262 (-637) rows, 383 (-370) columns and 901 (-1386) elements
Statistics for presolved model
Original problem has 48 integers (48 of which binary)
Presolved problem has 24 integers (24 of which binary)
==== 190 zero objective 3 different
190 variables have objective of 0
49 variables have objective of 1
144 variables have objective of 1e+06
==== absolute objective values 3 different
190 variables have objective of 0
49 variables have objective of 1
144 variables have objective of 1e+06
==== for integers 24 zero objective 1 different
24 variables have objective of 0
==== for integers absolute objective values 1 different
24 variables have objective of 0
===== end objective counts


Problem has 262 rows, 383 columns (193 with objective) and 901 elements
There are 193 singletons with objective 
Column breakdown:
287 of type 0.0->inf, 48 of type 0.0->up, 0 of type lo->inf, 
24 of type lo->up, 0 of type free, 0 of type fixed, 
0 of type -inf->0.0, 0 of type -inf->up, 24 of type 0.0->1.0 
Row breakdown:
24 of type E 0.0, 0 of type E 1.0, 0 of type E -1.0, 
48 of type E other, 0 of type G 0.0, 0 of type G 1.0, 
0 of type G other, 119 of type L 0.0, 0 of type L 1.0, 
71 of type L other, 0 of type Range 0.0->1.0, 0 of type Range other, 
0 of type Free 
Continuous objective value is 54200 - 0.00 seconds
Cgl0003I 0 fixed, 0 tightened bounds, 23 strengthened rows, 0 substitutions
Cgl0004I processed model has 238 rows, 382 columns (24 integer (24 of which binary)) and 760 elements
Cbc0038I Initial state - 16 integers unsatisfied sum - 2.75
Cbc0038I Pass   1: suminf.    0.00000 (0) obj. 1.37505e+09 iterations 38
Cbc0038I Solution found of 1.37505e+09
Cbc0038I Relaxing continuous gives 1.37505e+09
Cbc0038I Before mini branch and bound, 8 integers at bound fixed and 240 continuous
Cbc0038I Full problem 238 rows 382 columns, reduced to 50 rows 44 columns
Cbc0038I Mini branch and bound improved solution from 1.37505e+09 to 80700 (0.03 seconds)
Cbc0038I Round again with cutoff of 78050
Cbc0038I Pass   2: suminf.    2.54996 (15) obj. 78050 iterations 30
Cbc0038I Pass   3: suminf.    1.11579 (16) obj. 78050 iterations 60
Cbc0038I Pass   4: suminf.    2.69997 (15) obj. 78050 iterations 44
Cbc0038I Pass   5: suminf.    2.49997 (14) obj. 78050 iterations 1
Cbc0038I Pass   6: suminf.    0.48125 (4) obj. 78050 iterations 43
Cbc0038I Pass   7: suminf.    0.36250 (16) obj. 78050 iterations 29
Cbc0038I Pass   8: suminf.    2.06875 (18) obj. 78050 iterations 3
Cbc0038I Pass   9: suminf.    2.06875 (18) obj. 78050 iterations 0
Cbc0038I Pass  10: suminf.    2.64997 (14) obj. 78050 iterations 43
Cbc0038I Pass  11: suminf.    2.44997 (13) obj. 78050 iterations 1
Cbc0038I Pass  12: suminf.    1.01000 (4) obj. 78050 iterations 43
Cbc0038I Pass  13: suminf.    0.53125 (3) obj. 78050 iterations 17
Cbc0038I Pass  14: suminf.    0.14999 (3) obj. 78050 iterations 4
Cbc0038I Pass  15: suminf.    1.11579 (16) obj. 78050 iterations 27
Cbc0038I Pass  16: suminf.    2.74995 (16) obj. 78050 iterations 41
Cbc0038I Pass  17: suminf.    2.54996 (15) obj. 78050 iterations 1
Cbc0038I Pass  18: suminf.    2.74999 (16) obj. 78050 iterations 12
Cbc0038I Pass  19: suminf.    2.54999 (15) obj. 78050 iterations 1
Cbc0038I Pass  20: suminf.    1.97625 (17) obj. 78050 iterations 69
Cbc0038I Pass  21: suminf.    1.97625 (17) obj. 78050 iterations 0
Cbc0038I Pass  22: suminf.    2.74995 (16) obj. 78050 iterations 44
Cbc0038I Pass  23: suminf.    2.54996 (15) obj. 78050 iterations 1
Cbc0038I Pass  24: suminf.    1.11579 (16) obj. 78050 iterations 66
Cbc0038I Pass  25: suminf.    1.11579 (16) obj. 78050 iterations 0
Cbc0038I Pass  26: suminf.    1.11579 (16) obj. 78050 iterations 0
Cbc0038I Pass  27: suminf.    1.97625 (17) obj. 78050 iterations 2
Cbc0038I Pass  28: suminf.    2.54998 (12) obj. 78050 iterations 36
Cbc0038I Pass  29: suminf.    2.34998 (11) obj. 78050 iterations 1
Cbc0038I Pass  30: suminf.    1.97625 (17) obj. 78050 iterations 48
Cbc0038I Pass  31: suminf.    2.74995 (16) obj. 78050 iterations 45
Cbc0038I No solution found this major pass
Cbc0038I Before mini branch and bound, 5 integers at bound fixed and 229 continuous
Cbc0038I Full problem 238 rows 382 columns, reduced to 18 rows 22 columns
Cbc0038I Mini branch and bound did not improve solution (0.07 seconds)
Cbc0038I After 0.07 seconds - Feasibility pump exiting with objective of 80700 - took 0.05 seconds
Cbc0012I Integer solution of 80700 found by feasibility pump after 0 iterations and 0 nodes (0.07 seconds)
Cbc0038I Full problem 238 rows 382 columns, reduced to 201 rows 338 columns - 1 fixed gives 199, 335 - still too large
Cbc0006I The LP relaxation is infeasible or too expensive
Cbc0013I At root node, 0 cuts changed objective from 54200 to 80700 in 1 passes
Cbc0014I Cut generator 0 (Probing) - 2 row cuts average 2.0 elements, 13 column cuts (13 active)  in 0.001 seconds - new frequency is 1
Cbc0014I Cut generator 1 (Gomory) - 0 row cuts average 0.0 elements, 0 column cuts (0 active)  in 0.000 seconds - new frequency is -100
Cbc0014I Cut generator 2 (Knapsack) - 0 row cuts average 0.0 elements, 0 column cuts (0 active)  in 0.000 seconds - new frequency is -100
Cbc0014I Cut generator 3 (Clique) - 0 row cuts average 0.0 elements, 0 column cuts (0 active)  in 0.000 seconds - new frequency is -100
Cbc0014I Cut generator 4 (MixedIntegerRounding2) - 0 row cuts average 0.0 elements, 0 column cuts (0 active)  in 0.000 seconds - new frequency is -100
Cbc0014I Cut generator 5 (FlowCover) - 0 row cuts average 0.0 elements, 0 column cuts (0 active)  in 0.000 seconds - new frequency is -100
Cbc0014I Cut generator 6 (TwoMirCuts) - 0 row cuts average 0.0 elements, 0 column cuts (0 active)  in 0.000 seconds - new frequency is -100
Cbc0001I Search completed - best objective 80700, took 19 iterations and 0 nodes (0.08 seconds)
Cbc0035I Maximum depth 0, 0 variables fixed on reduced cost
Cuts at root node changed objective from 54200 to 80700
Probing was tried 1 times and created 15 cuts of which 0 were active after adding rounds of cuts (0.001 seconds)
Gomory was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Knapsack was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
Clique was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
MixedIntegerRounding2 was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
FlowCover was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)
TwoMirCuts was tried 0 times and created 0 cuts of which 0 were active after adding rounds of cuts (0.000 seconds)

Result - Optimal solution found

Objective value:                80700.00000000
Enumerated nodes:               0
Total iterations:               19
Time (CPU seconds):             0.09
Time (Wallclock seconds):       0.10

Total time (CPU seconds):       0.10   (Wallclock seconds):       0.12

Input data


In [19]:
import pandas as pd

In [20]:
pd.DataFrame(case.gen['PMAX'])


Out[20]:
PMAX
GenCo0 200
GenCo1 500

In [21]:
case.load


Out[21]:
Bus1 Bus2
0 0.0 100.0
1 0.0 100.0
2 0.0 100.0
3 0.0 120.0
4 0.0 120.0
5 0.0 120.0
6 0.0 150.0
7 0.0 150.0
8 0.0 150.0
9 0.0 200.0
10 0.0 200.0
11 0.0 200.0
12 0.0 300.0
13 0.0 400.0
14 0.0 300.0
15 0.0 200.0
16 0.0 200.0
17 0.0 200.0
18 0.0 150.0
19 0.0 150.0
20 0.0 150.0
21 0.0 150.0
22 0.0 100.0
23 0.0 100.0

Model Results


In [22]:
model.results.unit_commitment


Out[22]:
GenCo0 GenCo1
0 1 0
1 1 0
2 1 0
3 1 0
4 1 0
5 1 0
6 1 1
7 1 1
8 1 1
9 1 1
10 1 1
11 1 1
12 1 1
13 1 1
14 1 1
15 1 1
16 1 1
17 1 1
18 1 1
19 1 1
20 1 1
21 1 1
22 1 0
23 1 0

In [23]:
model.results.power_generated


Out[23]:
GenCo0 GenCo1
0 100 0
1 100 0
2 100 0
3 120 0
4 120 0
5 120 0
6 150 0
7 150 0
8 150 0
9 200 0
10 200 0
11 200 0
12 200 100
13 200 200
14 200 100
15 200 0
16 200 0
17 200 0
18 150 0
19 150 0
20 150 0
21 150 0
22 100 0
23 100 0

In [24]:
model.results.commitment_cost


Out[24]:
6000

In [25]:
model.results.production_cost


Out[25]:
42700

In [26]:
model.results.noload_cost


Out[26]:
32000.0

In [27]:
model.results.line_power


Out[27]:
0
0 100
1 100
2 100
3 120
4 120
5 120
6 150
7 150
8 150
9 200
10 200
11 200
12 200
13 200
14 200
15 200
16 200
17 200
18 150
19 150
20 150
21 150
22 100
23 100

In [28]:
from psst.plot import line_power, stacked_power_generation

In [32]:
ax = stacked_power_generation(model.results, legend=True)

(model.results.power_generated.sum(axis=1) + model.results.regulating_reserve_up_available.sum(axis=1)).plot(ax=ax)


Out[32]:
<matplotlib.axes._subplots.AxesSubplot at 0x10ff11a90>

In [ ]:


In [ ]:


In [ ]: