0001 function [results, success, raw] = ktropf_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 use_ktropts_file = 1;
0081 verbose = mpopt(31);
0082
0083
0084 mpc = get_mpc(om);
0085 [baseMVA, bus, gen, branch, gencost] = ...
0086 deal(mpc.baseMVA, mpc.bus, mpc.gen, mpc.branch, mpc.gencost);
0087 [vv, ll, nn] = get_idx(om);
0088
0089
0090 nb = size(bus, 1);
0091 ng = size(gen, 1);
0092 nl = size(branch, 1);
0093 ny = getN(om, 'var', 'y');
0094
0095
0096 [x0, xmin, xmax] = getv(om);
0097
0098
0099 [A, l, u] = linear_constraints(om);
0100
0101
0102
0103 ieq = find( abs(u-l) <= eps );
0104 igt = find( u >= 1e10 & l > -1e10 );
0105 ilt = find( l <= -1e10 & u < 1e10 );
0106 ibx = find( (abs(u-l) > eps) & (u < 1e10) & (l > -1e10) );
0107 Af = [ A(ilt, :); -A(igt, :); A(ibx, :); -A(ibx, :) ];
0108 bf = [ u(ilt); -l(igt); u(ibx); -l(ibx)];
0109 Afeq = A(ieq, :);
0110 bfeq = u(ieq);
0111
0112
0113 [Ybus, Yf, Yt] = makeYbus(baseMVA, bus, branch);
0114
0115
0116 ll = xmin; uu = xmax;
0117 ll(xmin == -Inf) = -1e10;
0118 uu(xmax == Inf) = 1e10;
0119 x0 = (ll + uu) / 2;
0120 Varefs = bus(bus(:, BUS_TYPE) == REF, VA) * (pi/180);
0121 x0(vv.i1.Va:vv.iN.Va) = Varefs(1);
0122 if ny > 0
0123 ipwl = find(gencost(:, MODEL) == PW_LINEAR);
0124
0125
0126 c = gencost(sub2ind(size(gencost), ipwl, NCOST+2*gencost(ipwl, NCOST)));
0127 x0(vv.i1.y:vv.iN.y) = max(c) + 0.1 * abs(max(c));
0128
0129 end
0130
0131
0132 il = find(branch(:, RATE_A) ~= 0 & branch(:, RATE_A) < 1e10);
0133 nl2 = length(il);
0134
0135
0136 nA = size(A, 1);
0137 nx = length(x0);
0138 f = branch(:, F_BUS);
0139 t = branch(:, T_BUS);
0140 Cf = sparse(1:nl, f, ones(nl, 1), nl, nb);
0141 Ct = sparse(1:nl, t, ones(nl, 1), nl, nb);
0142 Cl = Cf + Ct;
0143 Cb = Cl' * Cl + speye(nb);
0144 Cl2 = Cl(il, :);
0145 Cg = sparse(gen(:, GEN_BUS), (1:ng)', 1, nb, ng);
0146 nz = nx - 2*(nb+ng);
0147 nxtra = nx - 2*nb;
0148 Js = [
0149 Cl2 Cl2 sparse(nl2, 2*ng) sparse(nl2,nz);
0150 Cl2 Cl2 sparse(nl2, 2*ng) sparse(nl2,nz);
0151 Cb Cb Cg sparse(nb,ng) sparse(nb,nz);
0152 Cb Cb sparse(nb,ng) Cg sparse(nb,nz);
0153 ];
0154 [f, df, d2f] = opf_costfcn(x0, om);
0155 Hs = d2f + [
0156 Cb Cb sparse(nb,nxtra);
0157 Cb Cb sparse(nb,nxtra);
0158 sparse(nxtra,nx);
0159 ];
0160
0161
0162 hess_fcn = @(x, lambda)opf_hessfcn(x, lambda, 1, om, Ybus, Yf(il,:), Yt(il,:), mpopt, il);
0163 fmoptions = optimset('GradObj', 'on', 'GradConstr', 'on', ...
0164 'Hessian', 'user-supplied', 'HessFcn', hess_fcn, ...
0165 'JacobPattern', Js, 'HessPattern', Hs );
0166 if use_ktropts_file
0167 if mpopt(58)
0168 opt_fname = sprintf('knitro_user_options_%d.txt', mpopt(58));
0169 else
0170
0171 ktropts.algorithm = 1;
0172 ktropts.outlev = verbose;
0173 ktropts.feastol = mpopt(16);
0174 ktropts.xtol = mpopt(17);
0175 ktropts.opttol = mpopt(18);
0176 if mpopt(19) ~= 0
0177 ktropts.maxit = mpopt(19);
0178 end
0179 ktropts.bar_directinterval = 0;
0180 opt_fname = write_ktropts(ktropts);
0181 end
0182 else
0183 fmoptions = optimset(fmoptions, 'Algorithm', 'interior-point', ...
0184 'TolCon', mpopt(16), 'TolX', mpopt(17), 'TolFun', mpopt(18) );
0185 if mpopt(19) ~= 0
0186 fmoptions = optimset(fmoptions, 'MaxIter', mpopt(19), ...
0187 'MaxFunEvals', 4 * mpopt(19));
0188 end
0189 if verbose == 0,
0190 fmoptions.Display = 'off';
0191 elseif verbose == 1
0192 fmoptions.Display = 'iter';
0193 else
0194 fmoptions.Display = 'testing';
0195 end
0196 opt_fname = [];
0197 end
0198
0199
0200 f_fcn = @(x)opf_costfcn(x, om);
0201 gh_fcn = @(x)opf_consfcn(x, om, Ybus, Yf(il,:), Yt(il,:), mpopt, il);
0202 [x, f, info, Output, Lambda] = ktrlink(f_fcn, x0, Af, bf, Afeq, bfeq, ...
0203 xmin, xmax, gh_fcn, fmoptions, opt_fname);
0204 success = (info == 0);
0205
0206
0207 if use_ktropts_file && ~mpopt(58)
0208 delete(opt_fname);
0209 end
0210
0211
0212 Va = x(vv.i1.Va:vv.iN.Va);
0213 Vm = x(vv.i1.Vm:vv.iN.Vm);
0214 Pg = x(vv.i1.Pg:vv.iN.Pg);
0215 Qg = x(vv.i1.Qg:vv.iN.Qg);
0216 V = Vm .* exp(1j*Va);
0217
0218
0219
0220 bus(:, VA) = Va * 180/pi;
0221 bus(:, VM) = Vm;
0222 gen(:, PG) = Pg * baseMVA;
0223 gen(:, QG) = Qg * baseMVA;
0224 gen(:, VG) = Vm(gen(:, GEN_BUS));
0225
0226
0227 Sf = V(branch(:, F_BUS)) .* conj(Yf * V);
0228 St = V(branch(:, T_BUS)) .* conj(Yt * V);
0229 branch(:, PF) = real(Sf) * baseMVA;
0230 branch(:, QF) = imag(Sf) * baseMVA;
0231 branch(:, PT) = real(St) * baseMVA;
0232 branch(:, QT) = imag(St) * baseMVA;
0233
0234
0235
0236 muSf = zeros(nl, 1);
0237 muSt = zeros(nl, 1);
0238 if ~isempty(il)
0239 muSf(il) = 2 * Lambda.ineqnonlin(1:nl2) .* branch(il, RATE_A) / baseMVA;
0240 muSt(il) = 2 * Lambda.ineqnonlin((1:nl2)+nl2) .* branch(il, RATE_A) / baseMVA;
0241 end
0242
0243
0244 bus(:, MU_VMAX) = Lambda.upper(vv.i1.Vm:vv.iN.Vm);
0245 bus(:, MU_VMIN) = -Lambda.lower(vv.i1.Vm:vv.iN.Vm);
0246 gen(:, MU_PMAX) = Lambda.upper(vv.i1.Pg:vv.iN.Pg) / baseMVA;
0247 gen(:, MU_PMIN) = -Lambda.lower(vv.i1.Pg:vv.iN.Pg) / baseMVA;
0248 gen(:, MU_QMAX) = Lambda.upper(vv.i1.Qg:vv.iN.Qg) / baseMVA;
0249 gen(:, MU_QMIN) = -Lambda.lower(vv.i1.Qg:vv.iN.Qg) / baseMVA;
0250 bus(:, LAM_P) = Lambda.eqnonlin(nn.i1.Pmis:nn.iN.Pmis) / baseMVA;
0251 bus(:, LAM_Q) = Lambda.eqnonlin(nn.i1.Qmis:nn.iN.Qmis) / baseMVA;
0252 branch(:, MU_SF) = muSf / baseMVA;
0253 branch(:, MU_ST) = muSt / baseMVA;
0254
0255
0256 nlnN = getN(om, 'nln');
0257 nlt = length(ilt);
0258 ngt = length(igt);
0259 nbx = length(ibx);
0260
0261
0262 kl = find(Lambda.eqnonlin < 0);
0263 ku = find(Lambda.eqnonlin > 0);
0264 nl_mu_l = zeros(nlnN, 1);
0265 nl_mu_u = [zeros(2*nb, 1); muSf; muSt];
0266 nl_mu_l(kl) = -Lambda.eqnonlin(kl);
0267 nl_mu_u(ku) = Lambda.eqnonlin(ku);
0268
0269
0270 kl = find(Lambda.eqlin < 0);
0271 ku = find(Lambda.eqlin > 0);
0272
0273 mu_l = zeros(size(u));
0274 mu_l(ieq(kl)) = -Lambda.eqlin(kl);
0275 mu_l(igt) = Lambda.ineqlin(nlt+(1:ngt));
0276 mu_l(ibx) = Lambda.ineqlin(nlt+ngt+nbx+(1:nbx));
0277
0278 mu_u = zeros(size(u));
0279 mu_u(ieq(ku)) = Lambda.eqlin(ku);
0280 mu_u(ilt) = Lambda.ineqlin(1:nlt);
0281 mu_u(ibx) = Lambda.ineqlin(nlt+ngt+(1:nbx));
0282
0283 mu = struct( ...
0284 'var', struct('l', -Lambda.lower, 'u', Lambda.upper), ...
0285 'nln', struct('l', nl_mu_l, 'u', nl_mu_u), ...
0286 'lin', struct('l', mu_l, 'u', mu_u) );
0287
0288 results = mpc;
0289 [results.bus, results.branch, results.gen, ...
0290 results.om, results.x, results.mu, results.f] = ...
0291 deal(bus, branch, gen, om, x, mu, f);
0292
0293 pimul = [ ...
0294 results.mu.nln.l - results.mu.nln.u;
0295 results.mu.lin.l - results.mu.lin.u;
0296 -ones(ny>0, 1);
0297 results.mu.var.l - results.mu.var.u;
0298 ];
0299 raw = struct('xr', x, 'pimul', pimul, 'info', info, 'output', Output);
0300
0301
0302
0303 function fname = write_ktropts(ktropts)
0304
0305
0306 fname = sprintf('ktropts_%06d.txt', fix(1e6*rand));
0307
0308
0309 [fd, msg] = fopen(fname, 'wt');
0310 if fd == -1
0311 error('could not create %d : %s', fname, msg);
0312 end
0313
0314
0315 fields = fieldnames(ktropts);
0316 for k = 1:length(fields)
0317 fprintf(fd, '%s %g\n', fields{k}, ktropts.(fields{k}));
0318 end
0319
0320
0321 if fd ~= 1
0322 fclose(fd);
0323 end