Package pypower :: Package t :: Module t_opf_ipopt
[hide private]
[frames] | no frames]

Source Code for Module pypower.t.t_opf_ipopt

  1  # Copyright (C) 2004-2011 Power System Engineering Research Center (PSERC) 
  2  # Copyright (C) 2011 Richard Lincoln 
  3  # 
  4  # PYPOWER is free software: you can redistribute it and/or modify 
  5  # it under the terms of the GNU General Public License as published 
  6  # by the Free Software Foundation, either version 3 of the License, 
  7  # or (at your option) any later version. 
  8  # 
  9  # PYPOWER is distributed in the hope that it will be useful, 
 10  # but WITHOUT ANY WARRANTY], without even the implied warranty of 
 11  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 12  # GNU General Public License for more details. 
 13  # 
 14  # You should have received a copy of the GNU General Public License 
 15  # along with PYPOWER. If not, see <http://www.gnu.org/licenses/>. 
 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   
50 -def t_opf_ipopt(quiet=False):
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#not quiet 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 ## set up indices 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 ## get solved AC power flow case from MAT-file 83 soln9_opf = loadmat(join(tdir, 'soln9_opf.mat'), struct_as_record=True) 84 ## defines bus_soln, gen_soln, branch_soln, f_soln 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 ## run OPF 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 ## run with automatic conversion of single-block pwl to linear costs 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 ## get solved AC power flow case from MAT-file 132 soln9_opf_Plim = loadmat(join(tdir, 'soln9_opf_Plim.mat'), struct_as_record=True) 133 ## defines bus_soln, gen_soln, branch_soln, f_soln 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 ## run OPF with active power line limits 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 ##----- test OPF with quadratic gen costs moved to generalized costs ----- 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] # number of buses 174 ng = ppc['gen'].shape[0] # number of gens 175 thbas = 0; thend = thbas + nb 176 vbas = thend; vend = vbas + nb 177 pgbas = vend; pgend = pgbas + ng 178 # qgbas = pgend; qgend = qgbas + ng 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 ## run OPF with quadratic gen costs moved to generalized costs 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 ##----- run OPF with extra linear user constraints & costs ----- 207 ## single new z variable constrained to be greater than or equal to 208 ## deviation from 1 pu voltage at bus 1, linear cost on this z 209 ## get solved AC power flow case from MAT-file 210 soln9_opf_extras1 = loadmat(join(tdir, 'soln9_opf_extras1.mat'), struct_as_record=True) 211 ## defines bus_soln, gen_soln, branch_soln, f_soln 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)) ## new z variable only 224 fparm = array([[1, 0, 0, 1]]) ## w = r = z 225 H = sparse((1, 1)) ## no quadratic term 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 ##----- test OPF with capability curves ----- 248 ppc = loadcase(join(tdir, 't_case9_opfv2')) 249 ## remove angle diff limits 250 ppc['branch'][0, ANGMAX] = 360 251 ppc['branch'][8, ANGMIN] = -360 252 253 ## get solved AC power flow case from MAT-file 254 soln9_opf_PQcap = loadmat(join(tdir, 'soln9_opf_PQcap.mat'), struct_as_record=True) 255 ## defines bus_soln, gen_soln, branch_soln, f_soln 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 ## run OPF with capability curves 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 ##----- test OPF with angle difference limits ----- 280 ppc = loadcase(join(tdir, 't_case9_opfv2')) 281 ## remove capability curves 282 ppc['gen'][ix_(arange(1, 3), 283 [PC1, PC2, QC1MIN, QC1MAX, QC2MIN, QC2MAX])] = zeros((2, 6)) 284 285 ## get solved AC power flow case from MAT-file 286 soln9_opf_ang = loadmat(join(tdir, 'soln9_opf_ang.mat'), struct_as_record=True) 287 ## defines bus_soln, gen_soln, branch_soln, f_soln 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 ## run OPF with angle difference limits 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 ##----- test OPF with ignored angle difference limits ----- 313 ## get solved AC power flow case from MAT-file 314 soln9_opf = loadmat(join(tdir, 'soln9_opf.mat'), struct_as_record=True) 315 ## defines bus_soln, gen_soln, branch_soln, f_soln 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 ## run OPF with ignored angle difference limits 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 ## ang limits are not in this solution data, so let's remove them 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