1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 """Solves combined unit decommitment / optimal power flow.
18 """
19
20 from time import time
21
22 from copy import deepcopy
23
24 from numpy import flatnonzero as find
25
26 from opf_args import opf_args2
27 from ppoption import ppoption
28 from isload import isload
29 from totcost import totcost
30 from fairmax import fairmax
31 from opf import opf
32
33 from idx_bus import PD
34 from idx_gen import GEN_STATUS, PG, QG, PMIN, MU_PMIN
35
36
38 """Solves combined unit decommitment / optimal power flow.
39
40 Solves a combined unit decommitment and optimal power flow for a single
41 time period. Uses an algorithm similar to dynamic programming. It proceeds
42 through a sequence of stages, where stage C{N} has C{N} generators shut
43 down, starting with C{N=0}. In each stage, it forms a list of candidates
44 (gens at their C{Pmin} limits) and computes the cost with each one of them
45 shut down. It selects the least cost case as the starting point for the
46 next stage, continuing until there are no more candidates to be shut down
47 or no more improvement can be gained by shutting something down.
48 If C{verbose} in ppopt (see L{ppoption} is C{true}, it prints progress
49 info, if it is > 1 it prints the output of each individual opf.
50
51 @see: L{opf}, L{runuopf}
52
53 @author: Ray Zimmerman (PSERC Cornell)
54 @author: Richard Lincoln
55 """
56
57 t0 = time()
58
59
60 ppc, ppopt = opf_args2(*args)
61
62
63 verbose = ppopt["VERBOSE"]
64 if verbose:
65 ppopt = ppoption(ppopt, VERBOSE=verbose - 1)
66
67
68
69
70 on = find( (ppc["gen"][:, GEN_STATUS] > 0) & ~isload(ppc["gen"]) )
71 onld = find( (ppc["gen"][:, GEN_STATUS] > 0) & isload(ppc["gen"]) )
72 load_capacity = sum(ppc["bus"][:, PD]) - sum(ppc["gen"][onld, PMIN])
73 Pmin = ppc["gen"][on, PMIN]
74 while sum(Pmin) > load_capacity:
75
76 avgPmincost = totcost(ppc["gencost"][on, :], Pmin) / Pmin
77 _, i = fairmax(avgPmincost)
78 i = on[i]
79
80 if verbose:
81 print 'Shutting down generator %d so all Pmin limits can be satisfied.\n' % i
82
83
84 ppc["gen"][i, [PG, QG, GEN_STATUS]] = 0
85
86
87 on = find( (ppc["gen"][:, GEN_STATUS] > 0) & ~isload(ppc["gen"]) )
88 Pmin = ppc["gen"][on, PMIN]
89
90
91 results = opf(ppc, ppopt)
92
93
94 results1 = deepcopy(results)
95
96
97 results0 = deepcopy(results1)
98 ppc["bus"] = results0["bus"].copy()
99
100 while True:
101
102 candidates = find((results0["gen"][:, MU_PMIN] > 0) & (results0["gen"][:, PMIN] > 0))
103 if len(candidates) == 0:
104 break
105
106
107
108 done = True
109
110 for k in candidates:
111
112 ppc["gen"] = results0["gen"].copy()
113
114
115 ppc["gen"][k, [PG, QG, GEN_STATUS]] = 0
116
117
118 results = opf(ppc, ppopt)
119
120
121 if results['success'] and (results["f"] < results1["f"]):
122 results1 = deepcopy(results)
123 k1 = k
124 done = False
125
126 if done:
127
128 break
129 else:
130
131 if verbose:
132 print 'Shutting down generator %d.\n' % k1
133
134 results0 = deepcopy(results1)
135 ppc["bus"] = results0["bus"].copy()
136
137
138 et = time() - t0
139
140
141 results0['et'] = et
142
143 return results0
144