0001 function [results, success, raw] = fmincopf_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 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
0051 VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
0052 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
0053 MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
0054 QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
0055 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0056 TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
0057 ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
0058 [PW_LINEAR, POLYNOMIAL, MODEL, STARTUP, SHUTDOWN, NCOST, COST] = idx_cost;
0059
0060
0061 mpc = om.get_mpc();
0062 [baseMVA, bus, gen, branch, gencost] = ...
0063 deal(mpc.baseMVA, mpc.bus, mpc.gen, mpc.branch, mpc.gencost);
0064 [vv, ll, nne, nni] = om.get_idx();
0065
0066
0067 nb = size(bus, 1);
0068 nl = size(branch, 1);
0069 ny = om.getN('var', 'y');
0070
0071
0072 [x0, xmin, xmax] = om.params_var();
0073
0074
0075 [A, l, u] = om.params_lin_constraint();
0076
0077
0078
0079 ieq = find( abs(u-l) <= eps );
0080 igt = find( u >= 1e10 & l > -1e10 );
0081 ilt = find( l <= -1e10 & u < 1e10 );
0082 ibx = find( (abs(u-l) > eps) & (u < 1e10) & (l > -1e10) );
0083 Af = [ A(ilt, :); -A(igt, :); A(ibx, :); -A(ibx, :) ];
0084 bf = [ u(ilt); -l(igt); u(ibx); -l(ibx)];
0085 Afeq = A(ieq, :);
0086 bfeq = u(ieq);
0087
0088
0089 [Ybus, Yf, Yt] = makeYbus(baseMVA, bus, branch);
0090
0091
0092 if mpopt.opf.start < 2
0093 s = 1;
0094 lb = xmin; ub = xmax;
0095 lb(xmin == -Inf) = -1e10;
0096 ub(xmax == Inf) = 1e10;
0097 x0 = (lb + ub) / 2;
0098 k = find(xmin == -Inf & xmax < Inf);
0099 x0(k) = xmax(k) - s;
0100 k = find(xmin > -Inf & xmax == Inf);
0101 x0(k) = xmin(k) + s;
0102 Varefs = bus(bus(:, BUS_TYPE) == REF, VA) * (pi/180);
0103 Vmax = min(bus(:, VMAX), 1.5);
0104 Vmin = max(bus(:, VMIN), 0.5);
0105 Vm = (Vmax + Vmin) / 2;
0106 if mpopt.opf.v_cartesian
0107 V = Vm * exp(1j*Varefs(1));
0108 x0(vv.i1.Vr:vv.iN.Vr) = real(V);
0109 x0(vv.i1.Vi:vv.iN.Vi) = imag(V);
0110 else
0111 x0(vv.i1.Va:vv.iN.Va) = Varefs(1);
0112 x0(vv.i1.Vm:vv.iN.Vm) = Vm;
0113 if ny > 0
0114 ipwl = find(gencost(:, MODEL) == PW_LINEAR);
0115 c = gencost(sub2ind(size(gencost), ipwl, NCOST+2*gencost(ipwl, NCOST)));
0116 x0(vv.i1.y:vv.iN.y) = max(c) + 0.1 * abs(max(c));
0117 end
0118 end
0119 end
0120
0121
0122 il = find(branch(:, RATE_A) ~= 0 & branch(:, RATE_A) < 1e10);
0123 nl2 = length(il);
0124
0125
0126 fmoptions = optimset('GradObj', 'on', 'GradConstr', 'on', ...
0127 'TolCon', mpopt.opf.violation, 'TolX', mpopt.fmincon.tol_x, ...
0128 'TolFun', mpopt.fmincon.tol_f );
0129 if mpopt.fmincon.max_it ~= 0
0130 fmoptions = optimset(fmoptions, 'MaxIter', mpopt.fmincon.max_it, ...
0131 'MaxFunEvals', 4 * mpopt.fmincon.max_it);
0132 end
0133
0134 if mpopt.verbose == 0,
0135 fmoptions.Display = 'off';
0136 elseif mpopt.verbose == 1
0137 fmoptions.Display = 'iter';
0138 else
0139 fmoptions.Display = 'testing';
0140 end
0141
0142
0143 if have_fcn('fmincon_ipm')
0144 switch mpopt.fmincon.alg
0145 case 1
0146 fmoptions = optimset(fmoptions, 'Algorithm', 'active-set');
0147 Af = full(Af);
0148 Afeq = full(Afeq);
0149 case 2
0150 fmoptions = optimset(fmoptions, 'Algorithm', 'interior-point');
0151 case 3
0152 fmoptions = optimset(fmoptions, 'Algorithm', 'interior-point', 'Hessian','lbfgs');
0153 case 4
0154 fmc_hessian = @(x, lambda)opf_hessfcn(x, lambda, 1, om, Ybus, Yf(il,:), Yt(il,:), mpopt, il);
0155 fmoptions = optimset(fmoptions, 'Algorithm', 'interior-point', ...
0156 'Hessian', 'user-supplied', 'HessFcn', fmc_hessian);
0157 case 5
0158 fmoptions = optimset(fmoptions, 'Algorithm', 'interior-point', 'Hessian','fin-diff-grads', 'SubProblem', 'cg');
0159 case 6
0160 fmoptions = optimset(fmoptions, 'Algorithm', 'sqp');
0161 Af = full(Af);
0162 Afeq = full(Afeq);
0163 otherwise
0164 error('fmincopf_solver: unknown algorithm specified in ''fmincon.alg'' option');
0165 end
0166 else
0167 fmoptions = optimset(fmoptions, 'LargeScale', 'off');
0168 Af = full(Af);
0169 Afeq = full(Afeq);
0170 end
0171
0172
0173
0174
0175 f_fcn = @(x)opf_costfcn(x, om);
0176 gh_fcn = @(x)opf_consfcn(x, om, Ybus, Yf(il,:), Yt(il,:), mpopt, il);
0177 [x, f, info, Output, Lambda] = ...
0178 fmincon(f_fcn, x0, Af, bf, Afeq, bfeq, xmin, xmax, gh_fcn, fmoptions);
0179 success = (info > 0);
0180
0181
0182 if mpopt.opf.v_cartesian
0183 Vi = x(vv.i1.Vi:vv.iN.Vi);
0184 Vr = x(vv.i1.Vr:vv.iN.Vr);
0185 V = Vr + 1j*Vi;
0186 Va = angle(V);
0187 Vm = abs(V);
0188 else
0189 Va = x(vv.i1.Va:vv.iN.Va);
0190 Vm = x(vv.i1.Vm:vv.iN.Vm);
0191 V = Vm .* exp(1j*Va);
0192 end
0193 Pg = x(vv.i1.Pg:vv.iN.Pg);
0194 Qg = x(vv.i1.Qg:vv.iN.Qg);
0195
0196
0197
0198 bus(:, VA) = Va * 180/pi;
0199 bus(:, VM) = Vm;
0200 gen(:, PG) = Pg * baseMVA;
0201 gen(:, QG) = Qg * baseMVA;
0202 gen(:, VG) = Vm(gen(:, GEN_BUS));
0203
0204
0205 Sf = V(branch(:, F_BUS)) .* conj(Yf * V);
0206 St = V(branch(:, T_BUS)) .* conj(Yt * V);
0207 branch(:, PF) = real(Sf) * baseMVA;
0208 branch(:, QF) = imag(Sf) * baseMVA;
0209 branch(:, PT) = real(St) * baseMVA;
0210 branch(:, QT) = imag(St) * baseMVA;
0211
0212
0213
0214 muSf = zeros(nl, 1);
0215 muSt = zeros(nl, 1);
0216 if ~isempty(il)
0217 if upper(mpopt.opf.flow_lim(1)) == 'P'
0218 muSf(il) = Lambda.ineqnonlin(nni.i1.Sf:nni.iN.Sf);
0219 muSt(il) = Lambda.ineqnonlin(nni.i1.St:nni.iN.St);
0220 else
0221 muSf(il) = 2 * Lambda.ineqnonlin(nni.i1.Sf:nni.iN.Sf) .* branch(il, RATE_A) / baseMVA;
0222 muSt(il) = 2 * Lambda.ineqnonlin(nni.i1.St:nni.iN.St) .* branch(il, RATE_A) / baseMVA;
0223 end
0224 end
0225
0226
0227
0228 kl = find(Lambda.lower < 0 & Lambda.upper == 0);
0229 Lambda.upper(kl) = -Lambda.lower(kl);
0230 Lambda.lower(kl) = 0;
0231 ku = find(Lambda.upper < 0 & Lambda.lower == 0);
0232 Lambda.lower(ku) = -Lambda.upper(ku);
0233 Lambda.upper(ku) = 0;
0234
0235
0236 if mpopt.opf.v_cartesian
0237 if om.userdata.veq
0238 lam = Lambda.eqnonlin(nne.i1.Veq:nne.iN.Veq);
0239 mu_Vmax = zeros(size(lam));
0240 mu_Vmin = zeros(size(lam));
0241 mu_Vmax(lam > 0) = lam(lam > 0);
0242 mu_Vmin(lam < 0) = -lam(lam < 0);
0243 bus(om.userdata.veq, MU_VMAX) = mu_Vmax;
0244 bus(om.userdata.veq, MU_VMIN) = mu_Vmin;
0245 end
0246 bus(om.userdata.viq, MU_VMAX) = Lambda.ineqnonlin(nni.i1.Vmax:nni.iN.Vmax);
0247 bus(om.userdata.viq, MU_VMIN) = Lambda.ineqnonlin(nni.i1.Vmin:nni.iN.Vmin);
0248 else
0249 bus(:, MU_VMAX) = Lambda.upper(vv.i1.Vm:vv.iN.Vm);
0250 bus(:, MU_VMIN) = Lambda.lower(vv.i1.Vm:vv.iN.Vm);
0251 end
0252 gen(:, MU_PMAX) = Lambda.upper(vv.i1.Pg:vv.iN.Pg) / baseMVA;
0253 gen(:, MU_PMIN) = Lambda.lower(vv.i1.Pg:vv.iN.Pg) / baseMVA;
0254 gen(:, MU_QMAX) = Lambda.upper(vv.i1.Qg:vv.iN.Qg) / baseMVA;
0255 gen(:, MU_QMIN) = Lambda.lower(vv.i1.Qg:vv.iN.Qg) / baseMVA;
0256 if mpopt.opf.current_balance
0257
0258
0259
0260
0261
0262
0263 VV = V ./ (V .* conj(V));
0264 VVr = real(VV);
0265 VVi = imag(VV);
0266 lamM = Lambda.eqnonlin(nne.i1.rImis:nne.iN.rImis);
0267 lamN = Lambda.eqnonlin(nne.i1.iImis:nne.iN.iImis);
0268 bus(:, LAM_P) = (VVr.*lamM + VVi.*lamN) / baseMVA;
0269 bus(:, LAM_Q) = (VVi.*lamM - VVr.*lamN) / baseMVA;
0270 else
0271 bus(:, LAM_P) = Lambda.eqnonlin(nne.i1.Pmis:nne.iN.Pmis) / baseMVA;
0272 bus(:, LAM_Q) = Lambda.eqnonlin(nne.i1.Qmis:nne.iN.Qmis) / baseMVA;
0273 end
0274 branch(:, MU_SF) = muSf / baseMVA;
0275 branch(:, MU_ST) = muSt / baseMVA;
0276
0277
0278 nlnN = 2*nb + 2*nl;
0279 nlt = length(ilt);
0280 ngt = length(igt);
0281 nbx = length(ibx);
0282
0283
0284 kl = find(Lambda.eqnonlin < 0);
0285 ku = find(Lambda.eqnonlin > 0);
0286 nl_mu_l = zeros(nlnN, 1);
0287 nl_mu_u = [zeros(2*nb, 1); muSf; muSt];
0288 nl_mu_l(kl) = -Lambda.eqnonlin(kl);
0289 nl_mu_u(ku) = Lambda.eqnonlin(ku);
0290
0291
0292 kl = find(Lambda.eqlin < 0);
0293 ku = find(Lambda.eqlin > 0);
0294
0295 mu_l = zeros(size(u));
0296 mu_l(ieq(kl)) = -Lambda.eqlin(kl);
0297 mu_l(igt) = Lambda.ineqlin(nlt+(1:ngt));
0298 mu_l(ibx) = Lambda.ineqlin(nlt+ngt+nbx+(1:nbx));
0299
0300 mu_u = zeros(size(u));
0301 mu_u(ieq(ku)) = Lambda.eqlin(ku);
0302 mu_u(ilt) = Lambda.ineqlin(1:nlt);
0303 mu_u(ibx) = Lambda.ineqlin(nlt+ngt+(1:nbx));
0304
0305 mu = struct( ...
0306 'var', struct('l', Lambda.lower, 'u', Lambda.upper), ...
0307 'nln', struct('l', nl_mu_l, 'u', nl_mu_u), ...
0308 'nle', Lambda.eqnonlin, ...
0309 'nli', Lambda.ineqnonlin, ...
0310 'lin', struct('l', mu_l, 'u', mu_u) );
0311
0312 results = mpc;
0313 [results.bus, results.branch, results.gen, ...
0314 results.om, results.x, results.mu, results.f] = ...
0315 deal(bus, branch, gen, om, x, mu, f);
0316
0317 pimul = [ ...
0318 results.mu.nln.l - results.mu.nln.u;
0319 results.mu.lin.l - results.mu.lin.u;
0320 -ones(ny>0, 1);
0321 results.mu.var.l - results.mu.var.u;
0322 ];
0323 raw = struct('xr', x, 'pimul', pimul, 'info', info, 'output', Output);