1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 """Tests for PIPS-based AC optimal power flow.
18 """
19
20 from os.path import dirname, join
21
22 from numpy import array, ones, zeros, Inf, r_, ix_, argsort, arange
23
24 from scipy.io import loadmat
25 from scipy.sparse import spdiags, csr_matrix as sparse
26
27 from pypower.ppoption import ppoption
28 from pypower.runopf import runopf
29 from pypower.loadcase import loadcase
30 from pypower.opf import opf
31
32 from pypower.idx_bus import \
33 BUS_AREA, BASE_KV, VMIN, VM, VA, LAM_P, LAM_Q, MU_VMIN, MU_VMAX
34
35 from pypower.idx_gen import \
36 GEN_BUS, QMAX, QMIN, MBASE, APF, PG, QG, VG, MU_PMAX, MU_QMIN, \
37 PC1, PC2, QC1MIN, QC1MAX, QC2MIN, QC2MAX
38
39 from pypower.idx_brch import \
40 ANGMAX, PF, QT, MU_SF, MU_ST, MU_ANGMAX, MU_ANGMIN, ANGMIN
41
42 from pypower.idx_cost import NCOST
43
44 from pypower.t.t_begin import t_begin
45 from pypower.t.t_is import t_is
46 from pypower.t.t_ok import t_ok
47 from pypower.t.t_end import t_end
48
49
51 """Tests for IPOPT-based AC optimal power flow.
52
53 @author: Ray Zimmerman (PSERC Cornell)
54 @author: Richard Lincoln
55 """
56 num_tests = 101
57
58 t_begin(num_tests, quiet)
59
60 tdir = dirname(__file__)
61 casefile = join(tdir, 't_case9_opf')
62 verbose = 0
63
64 t0 = 'IPOPT : '
65 ppopt = ppoption(OPF_VIOLATION=1e-6, PDIPM_GRADTOL=1e-8,
66 PDIPM_COMPTOL=1e-8, PDIPM_COSTTOL=1e-9)
67 ppopt = ppoption(ppopt, OUT_ALL=0, VERBOSE=verbose, OPF_ALG=580)
68
69
70 ib_data = r_[arange(BUS_AREA + 1), arange(BASE_KV, VMIN + 1)]
71 ib_voltage = arange(VM, VA + 1)
72 ib_lam = arange(LAM_P, LAM_Q + 1)
73 ib_mu = arange(MU_VMAX, MU_VMIN + 1)
74 ig_data = r_[[GEN_BUS, QMAX, QMIN], arange(MBASE, APF + 1)]
75 ig_disp = array([PG, QG, VG])
76 ig_mu = arange(MU_PMAX, MU_QMIN + 1)
77 ibr_data = arange(ANGMAX + 1)
78 ibr_flow = arange(PF, QT + 1)
79 ibr_mu = array([MU_SF, MU_ST])
80 ibr_angmu = array([MU_ANGMIN, MU_ANGMAX])
81
82
83 soln9_opf = loadmat(join(tdir, 'soln9_opf.mat'), struct_as_record=True)
84
85 bus_soln = soln9_opf['bus_soln']
86 gen_soln = soln9_opf['gen_soln']
87 branch_soln = soln9_opf['branch_soln']
88 f_soln = soln9_opf['f_soln'][0]
89
90
91 t = t0
92 r = runopf(casefile, ppopt)
93 bus, gen, branch, f, success = \
94 r['bus'], r['gen'], r['branch'], r['f'], r['success']
95 t_ok(success, [t, 'success'])
96 t_is(f, f_soln, 3, [t, 'f'])
97 t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data'])
98 t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage'])
99 t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda'])
100 t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu'])
101 t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data'])
102 t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch'])
103 t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu'])
104 t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data'])
105 t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow'])
106 t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu'])
107
108
109 t = ''.join([t0, '(single-block PWL) : '])
110 ppc = loadcase(casefile)
111 ppc['gencost'][2, NCOST] = 2
112 r = runopf(ppc, ppopt)
113 bus, gen, branch, f, success = \
114 r['bus'], r['gen'], r['branch'], r['f'], r['success']
115 t_ok(success, [t, 'success'])
116 t_is(f, f_soln, 3, [t, 'f'])
117 t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data'])
118 t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage'])
119 t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda'])
120 t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu'])
121 t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data'])
122 t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch'])
123 t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu'])
124 t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data'])
125 t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow'])
126 t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu'])
127 xr = r_[r['var']['val']['Va'], r['var']['val']['Vm'], r['var']['val']['Pg'],
128 r['var']['val']['Qg'], 0, r['var']['val']['y']]
129 t_is(r['x'], xr, 8, [t, 'check on raw x returned from OPF'])
130
131
132 soln9_opf_Plim = loadmat(join(tdir, 'soln9_opf_Plim.mat'), struct_as_record=True)
133
134 bus_soln = soln9_opf_Plim['bus_soln']
135 gen_soln = soln9_opf_Plim['gen_soln']
136 branch_soln = soln9_opf_Plim['branch_soln']
137 f_soln = soln9_opf_Plim['f_soln'][0]
138
139
140 t = ''.join([t0, '(P line lim) : '])
141 ppopt1 = ppoption(ppopt, OPF_FLOW_LIM=1)
142 r = runopf(casefile, ppopt1)
143 bus, gen, branch, f, success = \
144 r['bus'], r['gen'], r['branch'], r['f'], r['success']
145 t_ok(success, [t, 'success'])
146 t_is(f, f_soln, 3, [t, 'f'])
147 t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data'])
148 t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage'])
149 t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda'])
150 t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu'])
151 t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data'])
152 t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch'])
153 t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu'])
154 t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data'])
155 t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow'])
156 t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu'])
157
158
159 ppc = loadcase(casefile)
160 ppc['gencost'] = array([
161 [2, 1500, 0, 3, 0.11, 5, 0],
162 [2, 2000, 0, 3, 0.085, 1.2, 0],
163 [2, 3000, 0, 3, 0.1225, 1, 0]
164 ])
165 r = runopf(ppc, ppopt)
166 bus_soln, gen_soln, branch_soln, f_soln, success = \
167 r['bus'], r['gen'], r['branch'], r['f'], r['success']
168 branch_soln = branch_soln[:, :MU_ST + 1]
169
170 A = None
171 l = array([])
172 u = array([])
173 nb = ppc['bus'].shape[0]
174 ng = ppc['gen'].shape[0]
175 thbas = 0; thend = thbas + nb
176 vbas = thend; vend = vbas + nb
177 pgbas = vend; pgend = pgbas + ng
178
179 nxyz = 2 * nb + 2 * ng
180 N = sparse((ppc['baseMVA'] * ones(ng), (arange(ng), arange(pgbas, pgend))), (ng, nxyz))
181 fparm = ones((ng, 1)) * array([[1, 0, 0, 1]])
182 ix = argsort(ppc['gen'][:, 0])
183 H = 2 * spdiags(ppc['gencost'][ix, 4], 0, ng, ng, 'csr')
184 Cw = ppc['gencost'][ix, 5]
185 ppc['gencost'][:, 4:7] = 0
186
187
188 t = ''.join([t0, 'w/quadratic generalized gen cost : '])
189 r = opf(ppc, A, l, u, ppopt, N, fparm, H, Cw)
190 f, bus, gen, branch, success = \
191 r['f'], r['bus'], r['gen'], r['branch'], r['success']
192 t_ok(success, [t, 'success'])
193 t_is(f, f_soln, 3, [t, 'f'])
194 t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data'])
195 t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage'])
196 t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda'])
197 t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu'])
198 t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data'])
199 t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch'])
200 t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu'])
201 t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data'])
202 t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow'])
203 t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu'])
204 t_is(r['cost']['usr'], f, 12, [t, 'user cost'])
205
206
207
208
209
210 soln9_opf_extras1 = loadmat(join(tdir, 'soln9_opf_extras1.mat'), struct_as_record=True)
211
212 bus_soln = soln9_opf_extras1['bus_soln']
213 gen_soln = soln9_opf_extras1['gen_soln']
214 branch_soln = soln9_opf_extras1['branch_soln']
215 f_soln = soln9_opf_extras1['f_soln'][0]
216
217 row = [0, 0, 1, 1]
218 col = [9, 24, 9, 24]
219 A = sparse(([-1, 1, 1, 1], (row, col)), (2, 25))
220 u = array([Inf, Inf])
221 l = array([-1, 1])
222
223 N = sparse(([1], ([0], [24])), (1, 25))
224 fparm = array([[1, 0, 0, 1]])
225 H = sparse((1, 1))
226 Cw = array([100.0])
227
228 t = ''.join([t0, 'w/extra constraints & costs 1 : '])
229 r = opf(casefile, A, l, u, ppopt, N, fparm, H, Cw)
230 f, bus, gen, branch, success = \
231 r['f'], r['bus'], r['gen'], r['branch'], r['success']
232 t_ok(success, [t, 'success'])
233 t_is(f, f_soln, 3, [t, 'f'])
234 t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data'])
235 t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage'])
236 t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda'])
237 t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu'])
238 t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data'])
239 t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch'])
240 t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu'])
241 t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data'])
242 t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow'])
243 t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu'])
244 t_is(r['var']['val']['z'], 0.025419, 6, [t, 'user variable'])
245 t_is(r['cost']['usr'], 2.5419, 4, [t, 'user cost'])
246
247
248 ppc = loadcase(join(tdir, 't_case9_opfv2'))
249
250 ppc['branch'][0, ANGMAX] = 360
251 ppc['branch'][8, ANGMIN] = -360
252
253
254 soln9_opf_PQcap = loadmat(join(tdir, 'soln9_opf_PQcap.mat'), struct_as_record=True)
255
256 bus_soln = soln9_opf_PQcap['bus_soln']
257 gen_soln = soln9_opf_PQcap['gen_soln']
258 branch_soln = soln9_opf_PQcap['branch_soln']
259 f_soln = soln9_opf_PQcap['f_soln'][0]
260
261
262 t = ''.join([t0, 'w/capability curves : '])
263 r = runopf(ppc, ppopt)
264 bus, gen, branch, f, success = \
265 r['bus'], r['gen'], r['branch'], r['f'], r['success']
266 t_ok(success, [t, 'success'])
267 t_is(f, f_soln, 3, [t, 'f'])
268 t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data'])
269 t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage'])
270 t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda'])
271 t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu'])
272 t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data'])
273 t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch'])
274 t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu'])
275 t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data'])
276 t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow'])
277 t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu'])
278
279
280 ppc = loadcase(join(tdir, 't_case9_opfv2'))
281
282 ppc['gen'][ix_(arange(1, 3),
283 [PC1, PC2, QC1MIN, QC1MAX, QC2MIN, QC2MAX])] = zeros((2, 6))
284
285
286 soln9_opf_ang = loadmat(join(tdir, 'soln9_opf_ang.mat'), struct_as_record=True)
287
288 bus_soln = soln9_opf_ang['bus_soln']
289 gen_soln = soln9_opf_ang['gen_soln']
290 branch_soln = soln9_opf_ang['branch_soln']
291 f_soln = soln9_opf_ang['f_soln'][0]
292
293
294 t = ''.join([t0, 'w/angle difference limits : '])
295 r = runopf(ppc, ppopt)
296 bus, gen, branch, f, success = \
297 r['bus'], r['gen'], r['branch'], r['f'], r['success']
298 t_ok(success, [t, 'success'])
299 t_is(f, f_soln, 3, [t, 'f'])
300 t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data'])
301 t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage'])
302 t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda'])
303 t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 1, [t, 'bus mu'])
304 t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data'])
305 t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch'])
306 t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu'])
307 t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data'])
308 t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow'])
309 t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu'])
310 t_is(branch[:, ibr_angmu ], branch_soln[:, ibr_angmu ], 2, [t, 'branch angle mu'])
311
312
313
314 soln9_opf = loadmat(join(tdir, 'soln9_opf.mat'), struct_as_record=True)
315
316 bus_soln = soln9_opf['bus_soln']
317 gen_soln = soln9_opf['gen_soln']
318 branch_soln = soln9_opf['branch_soln']
319 f_soln = soln9_opf['f_soln'][0]
320
321
322 t = ''.join([t0, 'w/ignored angle difference limits : '])
323 ppopt1 = ppoption(ppopt, OPF_IGNORE_ANG_LIM=1)
324 r = runopf(ppc, ppopt1)
325 bus, gen, branch, f, success = \
326 r['bus'], r['gen'], r['branch'], r['f'], r['success']
327
328 branch[0, ANGMAX] = 360
329 branch[8, ANGMIN] = -360
330 t_ok(success, [t, 'success'])
331 t_is(f, f_soln, 3, [t, 'f'])
332 t_is( bus[:, ib_data ], bus_soln[:, ib_data ], 10, [t, 'bus data'])
333 t_is( bus[:, ib_voltage], bus_soln[:, ib_voltage], 3, [t, 'bus voltage'])
334 t_is( bus[:, ib_lam ], bus_soln[:, ib_lam ], 3, [t, 'bus lambda'])
335 t_is( bus[:, ib_mu ], bus_soln[:, ib_mu ], 2, [t, 'bus mu'])
336 t_is( gen[:, ig_data ], gen_soln[:, ig_data ], 10, [t, 'gen data'])
337 t_is( gen[:, ig_disp ], gen_soln[:, ig_disp ], 3, [t, 'gen dispatch'])
338 t_is( gen[:, ig_mu ], gen_soln[:, ig_mu ], 3, [t, 'gen mu'])
339 t_is(branch[:, ibr_data ], branch_soln[:, ibr_data ], 10, [t, 'branch data'])
340 t_is(branch[:, ibr_flow ], branch_soln[:, ibr_flow ], 3, [t, 'branch flow'])
341 t_is(branch[:, ibr_mu ], branch_soln[:, ibr_mu ], 2, [t, 'branch mu'])
342
343 t_end()
344
345
346 if __name__ == '__main__':
347 t_opf_ipopt(quiet=False)
348