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 mpc = get_mpc(om);
0081 [baseMVA, bus, gen, branch, gencost] = ...
0082 deal(mpc.baseMVA, mpc.bus, mpc.gen, mpc.branch, mpc.gencost);
0083 [vv, ll, nn] = get_idx(om);
0084
0085
0086 nb = size(bus, 1);
0087 ng = size(gen, 1);
0088 nl = size(branch, 1);
0089 ny = getN(om, 'var', 'y');
0090
0091
0092 [A, l, u] = linear_constraints(om);
0093
0094
0095 [x0, xmin, xmax] = getv(om);
0096
0097
0098 [Ybus, Yf, Yt] = makeYbus(baseMVA, bus, branch);
0099
0100
0101 ll = xmin; uu = xmax;
0102 ll(xmin == -Inf) = -1e10;
0103 uu(xmax == Inf) = 1e10;
0104 x0 = (ll + uu) / 2;
0105 Varefs = bus(bus(:, BUS_TYPE) == REF, VA) * (pi/180);
0106 x0(vv.i1.Va:vv.iN.Va) = Varefs(1);
0107 if ny > 0
0108 ipwl = find(gencost(:, MODEL) == PW_LINEAR);
0109
0110
0111 c = gencost(sub2ind(size(gencost), ipwl, NCOST+2*gencost(ipwl, NCOST)));
0112 x0(vv.i1.y:vv.iN.y) = max(c) + 0.1 * abs(max(c));
0113
0114 end
0115
0116
0117 il = find(branch(:, RATE_A) ~= 0 & branch(:, RATE_A) < 1e10);
0118 nl2 = length(il);
0119
0120
0121
0122 nA = size(A, 1);
0123 nx = length(x0);
0124 f = branch(:, F_BUS);
0125 t = branch(:, T_BUS);
0126 Cf = sparse(1:nl, f, ones(nl, 1), nl, nb);
0127 Ct = sparse(1:nl, t, ones(nl, 1), nl, nb);
0128 Cl = Cf + Ct;
0129 Cb = Cl' * Cl + speye(nb);
0130 Cl2 = Cl(il, :);
0131 Cg = sparse(gen(:, GEN_BUS), (1:ng)', 1, nb, ng);
0132 nz = nx - 2*(nb+ng);
0133 nxtra = nx - 2*nb;
0134 Js = [
0135 Cb Cb Cg sparse(nb,ng) sparse(nb,nz);
0136 Cb Cb sparse(nb,ng) Cg sparse(nb,nz);
0137 Cl2 Cl2 sparse(nl2, 2*ng) sparse(nl2,nz);
0138 Cl2 Cl2 sparse(nl2, 2*ng) sparse(nl2,nz);
0139 A;
0140 ];
0141 [f, df, d2f] = opf_costfcn(x0, om);
0142 Hs = tril(d2f + [
0143 Cb Cb sparse(nb,nxtra);
0144 Cb Cb sparse(nb,nxtra);
0145 sparse(nxtra,nx);
0146 ]);
0147
0148
0149 options.ipopt = ipopt_options([], mpopt);
0150
0151
0152 options.auxdata = struct( ...
0153 'om', om, ...
0154 'Ybus', Ybus, ...
0155 'Yf', Yf(il,:), ...
0156 'Yt', Yt(il,:), ...
0157 'mpopt', mpopt, ...
0158 'il', il, ...
0159 'A', A, ...
0160 'nA', nA, ...
0161 'neqnln', 2*nb, ...
0162 'niqnln', 2*nl2, ...
0163 'Js', Js, ...
0164 'Hs', Hs );
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186 options.lb = xmin;
0187 options.ub = xmax;
0188 options.cl = [zeros(2*nb, 1); -Inf*ones(2*nl2, 1); l];
0189 options.cu = [zeros(2*nb, 1); zeros(2*nl2, 1); u];
0190
0191
0192 funcs.objective = @objective;
0193 funcs.gradient = @gradient;
0194 funcs.constraints = @constraints;
0195 funcs.jacobian = @jacobian;
0196 funcs.hessian = @hessian;
0197 funcs.jacobianstructure = @(d) Js;
0198 funcs.hessianstructure = @(d) Hs;
0199
0200
0201
0202
0203 [x, info] = ipopt(x0,funcs,options);
0204
0205 if info.status == 0 || info.status == 1
0206 success = 1;
0207 else
0208 success = 0;
0209 end
0210 if isfield(info, 'iter')
0211 output.iterations = info.iter;
0212 else
0213 output.iterations = [];
0214 end
0215 f = opf_costfcn(x, om);
0216
0217
0218 Va = x(vv.i1.Va:vv.iN.Va);
0219 Vm = x(vv.i1.Vm:vv.iN.Vm);
0220 Pg = x(vv.i1.Pg:vv.iN.Pg);
0221 Qg = x(vv.i1.Qg:vv.iN.Qg);
0222 V = Vm .* exp(1j*Va);
0223
0224
0225
0226 bus(:, VA) = Va * 180/pi;
0227 bus(:, VM) = Vm;
0228 gen(:, PG) = Pg * baseMVA;
0229 gen(:, QG) = Qg * baseMVA;
0230 gen(:, VG) = Vm(gen(:, GEN_BUS));
0231
0232
0233 Sf = V(branch(:, F_BUS)) .* conj(Yf * V);
0234 St = V(branch(:, T_BUS)) .* conj(Yt * V);
0235 branch(:, PF) = real(Sf) * baseMVA;
0236 branch(:, QF) = imag(Sf) * baseMVA;
0237 branch(:, PT) = real(St) * baseMVA;
0238 branch(:, QT) = imag(St) * baseMVA;
0239
0240
0241
0242 muSf = zeros(nl, 1);
0243 muSt = zeros(nl, 1);
0244 if ~isempty(il)
0245 muSf(il) = 2 * info.lambda(2*nb+ (1:nl2)) .* branch(il, RATE_A) / baseMVA;
0246 muSt(il) = 2 * info.lambda(2*nb+nl2+(1:nl2)) .* branch(il, RATE_A) / baseMVA;
0247 end
0248
0249
0250 bus(:, MU_VMAX) = info.zu(vv.i1.Vm:vv.iN.Vm);
0251 bus(:, MU_VMIN) = info.zl(vv.i1.Vm:vv.iN.Vm);
0252 gen(:, MU_PMAX) = info.zu(vv.i1.Pg:vv.iN.Pg) / baseMVA;
0253 gen(:, MU_PMIN) = info.zl(vv.i1.Pg:vv.iN.Pg) / baseMVA;
0254 gen(:, MU_QMAX) = info.zu(vv.i1.Qg:vv.iN.Qg) / baseMVA;
0255 gen(:, MU_QMIN) = info.zl(vv.i1.Qg:vv.iN.Qg) / baseMVA;
0256 bus(:, LAM_P) = info.lambda(nn.i1.Pmis:nn.iN.Pmis) / baseMVA;
0257 bus(:, LAM_Q) = info.lambda(nn.i1.Qmis:nn.iN.Qmis) / baseMVA;
0258 branch(:, MU_SF) = muSf / baseMVA;
0259 branch(:, MU_ST) = muSt / baseMVA;
0260
0261
0262 nlnN = getN(om, 'nln');
0263
0264
0265 kl = find(info.lambda(1:2*nb) < 0);
0266 ku = find(info.lambda(1:2*nb) > 0);
0267 nl_mu_l = zeros(nlnN, 1);
0268 nl_mu_u = [zeros(2*nb, 1); muSf; muSt];
0269 nl_mu_l(kl) = -info.lambda(kl);
0270 nl_mu_u(ku) = info.lambda(ku);
0271
0272
0273 lam_lin = info.lambda(2*nb+2*nl2+(1:nA));
0274 kl = find(lam_lin < 0);
0275 ku = find(lam_lin > 0);
0276 mu_l = zeros(nA, 1);
0277 mu_l(kl) = -lam_lin(kl);
0278 mu_u = zeros(nA, 1);
0279 mu_u(ku) = lam_lin(ku);
0280
0281 mu = struct( ...
0282 'var', struct('l', info.zl, 'u', info.zu), ...
0283 'nln', struct('l', nl_mu_l, 'u', nl_mu_u), ...
0284 'lin', struct('l', mu_l, 'u', mu_u) );
0285
0286 results = mpc;
0287 [results.bus, results.branch, results.gen, ...
0288 results.om, results.x, results.mu, results.f] = ...
0289 deal(bus, branch, gen, om, x, mu, f);
0290
0291 pimul = [ ...
0292 results.mu.nln.l - results.mu.nln.u;
0293 results.mu.lin.l - results.mu.lin.u;
0294 -ones(ny>0, 1);
0295 results.mu.var.l - results.mu.var.u;
0296 ];
0297 raw = struct('xr', x, 'pimul', pimul, 'info', info.status, 'output', output);
0298
0299
0300
0301 function f = objective(x, d)
0302 f = opf_costfcn(x, d.om);
0303
0304 function df = gradient(x, d)
0305 [f, df] = opf_costfcn(x, d.om);
0306
0307 function c = constraints(x, d)
0308 [hn, gn] = opf_consfcn(x, d.om, d.Ybus, d.Yf, d.Yt, d.mpopt, d.il);
0309 if isempty(d.A)
0310 c = [gn; hn];
0311 else
0312 c = [gn; hn; d.A*x];
0313 end
0314
0315 function J = jacobian(x, d)
0316 [hn, gn, dhn, dgn] = opf_consfcn(x, d.om, d.Ybus, d.Yf, d.Yt, d.mpopt, d.il);
0317 J = [dgn'; dhn'; d.A];
0318
0319 function H = hessian(x, sigma, lambda, d)
0320 lam.eqnonlin = lambda(1:d.neqnln);
0321 lam.ineqnonlin = lambda(d.neqnln+(1:d.niqnln));
0322 H = tril(opf_hessfcn(x, lam, sigma, d.om, d.Ybus, d.Yf, d.Yt, d.mpopt, d.il));
0323
0324
0325
0326
0327
0328