0001 function [results, success, raw] = ipoptopf_solver(om, mpopt)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
0070 VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
0071 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
0072 MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
0073 QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
0074 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0075 TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
0076 ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
0077 [PW_LINEAR, POLYNOMIAL, MODEL, STARTUP, SHUTDOWN, NCOST, COST] = idx_cost;
0078
0079
0080 verbose = mpopt(31);
0081 feastol = mpopt(81);
0082 gradtol = mpopt(82);
0083 comptol = mpopt(83);
0084 costtol = mpopt(84);
0085 max_it = mpopt(85);
0086 max_red = mpopt(86);
0087 step_control = (mpopt(11) == 565);
0088 if feastol == 0
0089 feastol = mpopt(16);
0090 end
0091 opt = struct( 'feastol', feastol, ...
0092 'gradtol', gradtol, ...
0093 'comptol', comptol, ...
0094 'costtol', costtol, ...
0095 'max_it', max_it, ...
0096 'max_red', max_red, ...
0097 'step_control', step_control, ...
0098 'cost_mult', 1e-4, ...
0099 'verbose', verbose );
0100
0101
0102 mpc = get_mpc(om);
0103 [baseMVA, bus, gen, branch, gencost] = ...
0104 deal(mpc.baseMVA, mpc.bus, mpc.gen, mpc.branch, mpc.gencost);
0105 [vv, ll, nn] = get_idx(om);
0106
0107
0108 nb = size(bus, 1);
0109 ng = size(gen, 1);
0110 nl = size(branch, 1);
0111 ny = getN(om, 'var', 'y');
0112
0113
0114 [A, l, u] = linear_constraints(om);
0115
0116
0117 [x0, xmin, xmax] = getv(om);
0118
0119
0120 [Ybus, Yf, Yt] = makeYbus(baseMVA, bus, branch);
0121
0122
0123 ll = xmin; uu = xmax;
0124 ll(xmin == -Inf) = -1e10;
0125 uu(xmax == Inf) = 1e10;
0126 x0 = (ll + uu) / 2;
0127 Varefs = bus(bus(:, BUS_TYPE) == REF, VA) * (pi/180);
0128 x0(vv.i1.Va:vv.iN.Va) = Varefs(1);
0129 if ny > 0
0130 ipwl = find(gencost(:, MODEL) == PW_LINEAR);
0131
0132
0133 c = gencost(sub2ind(size(gencost), ipwl, NCOST+2*gencost(ipwl, NCOST)));
0134 x0(vv.i1.y:vv.iN.y) = max(c) + 0.1 * abs(max(c));
0135
0136 end
0137
0138
0139 il = find(branch(:, RATE_A) ~= 0 & branch(:, RATE_A) < 1e10);
0140 nl2 = length(il);
0141
0142
0143
0144 nA = size(A, 1);
0145 nx = length(x0);
0146 f = branch(:, F_BUS);
0147 t = branch(:, T_BUS);
0148 Cf = sparse(1:nl, f, ones(nl, 1), nl, nb);
0149 Ct = sparse(1:nl, t, ones(nl, 1), nl, nb);
0150 Cl = Cf + Ct;
0151 Cb = Cl' * Cl + speye(nb);
0152 Cl2 = Cl(il, :);
0153 Cg = sparse(gen(:, GEN_BUS), (1:ng)', 1, nb, ng);
0154 nz = nx - 2*(nb+ng);
0155 nxtra = nx - 2*nb;
0156 Js = [
0157 Cb Cb Cg sparse(nb,ng) sparse(nb,nz);
0158 Cb Cb sparse(nb,ng) Cg sparse(nb,nz);
0159 Cl2 Cl2 sparse(nl2, 2*ng) sparse(nl2,nz);
0160 Cl2 Cl2 sparse(nl2, 2*ng) sparse(nl2,nz);
0161 A;
0162 ];
0163 [f, df, d2f] = opf_costfcn(x0, om);
0164 Hs = tril(d2f + [
0165 Cb Cb sparse(nb,nxtra);
0166 Cb Cb sparse(nb,nxtra);
0167 sparse(nxtra,nx);
0168 ]);
0169
0170
0171 options.ipopt = ipopt_options([], mpopt);
0172
0173
0174 options.auxdata = struct( ...
0175 'om', om, ...
0176 'Ybus', Ybus, ...
0177 'Yf', Yf(il,:), ...
0178 'Yt', Yt(il,:), ...
0179 'mpopt', mpopt, ...
0180 'il', il, ...
0181 'A', A, ...
0182 'nA', nA, ...
0183 'neqnln', 2*nb, ...
0184 'niqnln', 2*nl2, ...
0185 'Js', Js, ...
0186 'Hs', Hs );
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208 options.lb = xmin;
0209 options.ub = xmax;
0210 options.cl = [zeros(2*nb, 1); -Inf*ones(2*nl2, 1); l];
0211 options.cu = [zeros(2*nb, 1); zeros(2*nl2, 1); u];
0212
0213
0214 funcs.objective = @objective;
0215 funcs.gradient = @gradient;
0216 funcs.constraints = @constraints;
0217 funcs.jacobian = @jacobian;
0218 funcs.hessian = @hessian;
0219 funcs.jacobianstructure = @(d) Js;
0220 funcs.hessianstructure = @(d) Hs;
0221
0222
0223
0224
0225 [x, info] = ipopt(x0,funcs,options);
0226
0227 if info.status == 0 || info.status == 1
0228 success = 1;
0229 else
0230 success = 0;
0231 end
0232 if isfield(info, 'iter')
0233 output.iterations = info.iter;
0234 else
0235 output.iterations = [];
0236 end
0237 f = opf_costfcn(x, om);
0238
0239
0240 Va = x(vv.i1.Va:vv.iN.Va);
0241 Vm = x(vv.i1.Vm:vv.iN.Vm);
0242 Pg = x(vv.i1.Pg:vv.iN.Pg);
0243 Qg = x(vv.i1.Qg:vv.iN.Qg);
0244 V = Vm .* exp(1j*Va);
0245
0246
0247
0248 bus(:, VA) = Va * 180/pi;
0249 bus(:, VM) = Vm;
0250 gen(:, PG) = Pg * baseMVA;
0251 gen(:, QG) = Qg * baseMVA;
0252 gen(:, VG) = Vm(gen(:, GEN_BUS));
0253
0254
0255 Sf = V(branch(:, F_BUS)) .* conj(Yf * V);
0256 St = V(branch(:, T_BUS)) .* conj(Yt * V);
0257 branch(:, PF) = real(Sf) * baseMVA;
0258 branch(:, QF) = imag(Sf) * baseMVA;
0259 branch(:, PT) = real(St) * baseMVA;
0260 branch(:, QT) = imag(St) * baseMVA;
0261
0262
0263
0264 muSf = zeros(nl, 1);
0265 muSt = zeros(nl, 1);
0266 if ~isempty(il)
0267 muSf(il) = 2 * info.lambda(2*nb+ (1:nl2)) .* branch(il, RATE_A) / baseMVA;
0268 muSt(il) = 2 * info.lambda(2*nb+nl2+(1:nl2)) .* branch(il, RATE_A) / baseMVA;
0269 end
0270
0271
0272 bus(:, MU_VMAX) = info.zu(vv.i1.Vm:vv.iN.Vm);
0273 bus(:, MU_VMIN) = info.zl(vv.i1.Vm:vv.iN.Vm);
0274 gen(:, MU_PMAX) = info.zu(vv.i1.Pg:vv.iN.Pg) / baseMVA;
0275 gen(:, MU_PMIN) = info.zl(vv.i1.Pg:vv.iN.Pg) / baseMVA;
0276 gen(:, MU_QMAX) = info.zu(vv.i1.Qg:vv.iN.Qg) / baseMVA;
0277 gen(:, MU_QMIN) = info.zl(vv.i1.Qg:vv.iN.Qg) / baseMVA;
0278 bus(:, LAM_P) = info.lambda(nn.i1.Pmis:nn.iN.Pmis) / baseMVA;
0279 bus(:, LAM_Q) = info.lambda(nn.i1.Qmis:nn.iN.Qmis) / baseMVA;
0280 branch(:, MU_SF) = muSf / baseMVA;
0281 branch(:, MU_ST) = muSt / baseMVA;
0282
0283
0284 nlnN = getN(om, 'nln');
0285
0286
0287 kl = find(info.lambda(1:2*nb) < 0);
0288 ku = find(info.lambda(1:2*nb) > 0);
0289 nl_mu_l = zeros(nlnN, 1);
0290 nl_mu_u = [zeros(2*nb, 1); muSf; muSt];
0291 nl_mu_l(kl) = -info.lambda(kl);
0292 nl_mu_u(ku) = info.lambda(ku);
0293
0294
0295 lam_lin = info.lambda(2*nb+2*nl2+(1:nA));
0296 kl = find(lam_lin < 0);
0297 ku = find(lam_lin > 0);
0298 mu_l = zeros(nA, 1);
0299 mu_l(kl) = -lam_lin(kl);
0300 mu_u = zeros(nA, 1);
0301 mu_u(ku) = lam_lin(ku);
0302
0303 mu = struct( ...
0304 'var', struct('l', info.zl, 'u', info.zu), ...
0305 'nln', struct('l', nl_mu_l, 'u', nl_mu_u), ...
0306 'lin', struct('l', mu_l, 'u', mu_u) );
0307
0308 results = mpc;
0309 [results.bus, results.branch, results.gen, ...
0310 results.om, results.x, results.mu, results.f] = ...
0311 deal(bus, branch, gen, om, x, mu, f);
0312
0313 pimul = [ ...
0314 results.mu.nln.l - results.mu.nln.u;
0315 results.mu.lin.l - results.mu.lin.u;
0316 -ones(ny>0, 1);
0317 results.mu.var.l - results.mu.var.u;
0318 ];
0319 raw = struct('xr', x, 'pimul', pimul, 'info', info.status, 'output', output);
0320
0321
0322
0323 function f = objective(x, d)
0324 f = opf_costfcn(x, d.om);
0325
0326 function df = gradient(x, d)
0327 [f, df] = opf_costfcn(x, d.om);
0328
0329 function c = constraints(x, d)
0330 [hn, gn] = opf_consfcn(x, d.om, d.Ybus, d.Yf, d.Yt, d.mpopt, d.il);
0331 if isempty(d.A)
0332 c = [gn; hn];
0333 else
0334 c = [gn; hn; d.A*x];
0335 end
0336
0337 function J = jacobian(x, d)
0338 [hn, gn, dhn, dgn] = opf_consfcn(x, d.om, d.Ybus, d.Yf, d.Yt, d.mpopt, d.il);
0339 J = [dgn'; dhn'; d.A];
0340
0341 function H = hessian(x, sigma, lambda, d)
0342 lam.eqnonlin = lambda(1:d.neqnln);
0343 lam.ineqnonlin = lambda(d.neqnln+(1:d.niqnln));
0344 H = tril(opf_hessfcn(x, lam, sigma, d.om, d.Ybus, d.Yf, d.Yt, d.mpopt, d.il));
0345
0346
0347
0348
0349
0350