Home > matpower4.1 > ipoptopf_solver.m

ipoptopf_solver

PURPOSE ^

IPOPTOPF_SOLVER Solves AC optimal power flow using MIPS.

SYNOPSIS ^

function [results, success, raw] = ipoptopf_solver(om, mpopt)

DESCRIPTION ^

IPOPTOPF_SOLVER  Solves AC optimal power flow using MIPS.

   [RESULTS, SUCCESS, RAW] = IPOPTOPF_SOLVER(OM, MPOPT)

   Inputs are an OPF model object and a MATPOWER options vector.

   Outputs are a RESULTS struct, SUCCESS flag and RAW output struct.

   RESULTS is a MATPOWER case struct (mpc) with the usual baseMVA, bus
   branch, gen, gencost fields, along with the following additional
   fields:
       .order      see 'help ext2int' for details of this field
       .x          final value of optimization variables (internal order)
       .f          final objective function value
       .mu         shadow prices on ...
           .var
               .l  lower bounds on variables
               .u  upper bounds on variables
           .nln
               .l  lower bounds on nonlinear constraints
               .u  upper bounds on nonlinear constraints
           .lin
               .l  lower bounds on linear constraints
               .u  upper bounds on linear constraints

   SUCCESS     1 if solver converged successfully, 0 otherwise

   RAW         raw output in form returned by MINOS
       .xr     final value of optimization variables
       .pimul  constraint multipliers
       .info   solver specific termination code
       .output solver specific output information

   See also OPF, IPOPT.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function [results, success, raw] = ipoptopf_solver(om, mpopt)
0002 %IPOPTOPF_SOLVER  Solves AC optimal power flow using MIPS.
0003 %
0004 %   [RESULTS, SUCCESS, RAW] = IPOPTOPF_SOLVER(OM, MPOPT)
0005 %
0006 %   Inputs are an OPF model object and a MATPOWER options vector.
0007 %
0008 %   Outputs are a RESULTS struct, SUCCESS flag and RAW output struct.
0009 %
0010 %   RESULTS is a MATPOWER case struct (mpc) with the usual baseMVA, bus
0011 %   branch, gen, gencost fields, along with the following additional
0012 %   fields:
0013 %       .order      see 'help ext2int' for details of this field
0014 %       .x          final value of optimization variables (internal order)
0015 %       .f          final objective function value
0016 %       .mu         shadow prices on ...
0017 %           .var
0018 %               .l  lower bounds on variables
0019 %               .u  upper bounds on variables
0020 %           .nln
0021 %               .l  lower bounds on nonlinear constraints
0022 %               .u  upper bounds on nonlinear constraints
0023 %           .lin
0024 %               .l  lower bounds on linear constraints
0025 %               .u  upper bounds on linear constraints
0026 %
0027 %   SUCCESS     1 if solver converged successfully, 0 otherwise
0028 %
0029 %   RAW         raw output in form returned by MINOS
0030 %       .xr     final value of optimization variables
0031 %       .pimul  constraint multipliers
0032 %       .info   solver specific termination code
0033 %       .output solver specific output information
0034 %
0035 %   See also OPF, IPOPT.
0036 
0037 %   MATPOWER
0038 %   $Id: ipoptopf_solver.m,v 1.6 2011/06/16 17:45:56 cvs Exp $
0039 %   by Ray Zimmerman, PSERC Cornell
0040 %   and Carlos E. Murillo-Sanchez, PSERC Cornell & Universidad Autonoma de Manizales
0041 %   Copyright (c) 2000-2011 by Power System Engineering Research Center (PSERC)
0042 %
0043 %   This file is part of MATPOWER.
0044 %   See http://www.pserc.cornell.edu/matpower/ for more info.
0045 %
0046 %   MATPOWER is free software: you can redistribute it and/or modify
0047 %   it under the terms of the GNU General Public License as published
0048 %   by the Free Software Foundation, either version 3 of the License,
0049 %   or (at your option) any later version.
0050 %
0051 %   MATPOWER is distributed in the hope that it will be useful,
0052 %   but WITHOUT ANY WARRANTY; without even the implied warranty of
0053 %   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0054 %   GNU General Public License for more details.
0055 %
0056 %   You should have received a copy of the GNU General Public License
0057 %   along with MATPOWER. If not, see <http://www.gnu.org/licenses/>.
0058 %
0059 %   Additional permission under GNU GPL version 3 section 7
0060 %
0061 %   If you modify MATPOWER, or any covered work, to interface with
0062 %   other modules (such as MATLAB code and MEX-files) available in a
0063 %   MATLAB(R) or comparable environment containing parts covered
0064 %   under other licensing terms, the licensors of MATPOWER grant
0065 %   you additional permission to convey the resulting work.
0066 
0067 %%----- initialization -----
0068 %% define named indices into data matrices
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 %% unpack data
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 %% problem dimensions
0086 nb = size(bus, 1);          %% number of buses
0087 ng = size(gen, 1);          %% number of gens
0088 nl = size(branch, 1);       %% number of branches
0089 ny = getN(om, 'var', 'y');  %% number of piece-wise linear costs
0090 
0091 %% linear constraints
0092 [A, l, u] = linear_constraints(om);
0093 
0094 %% bounds on optimization vars
0095 [x0, xmin, xmax] = getv(om);
0096 
0097 %% build admittance matrices
0098 [Ybus, Yf, Yt] = makeYbus(baseMVA, bus, branch);
0099 
0100 %% try to select an interior initial point
0101 ll = xmin; uu = xmax;
0102 ll(xmin == -Inf) = -1e10;   %% replace Inf with numerical proxies
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);  %% angles set to first reference angle
0107 if ny > 0
0108     ipwl = find(gencost(:, MODEL) == PW_LINEAR);
0109 %     PQ = [gen(:, PMAX); gen(:, QMAX)];
0110 %     c = totcost(gencost(ipwl, :), PQ(ipwl));
0111     c = gencost(sub2ind(size(gencost), ipwl, NCOST+2*gencost(ipwl, NCOST)));    %% largest y-value in CCV data
0112     x0(vv.i1.y:vv.iN.y) = max(c) + 0.1 * abs(max(c));
0113 %     x0(vv.i1.y:vv.iN.y) = c + 0.1 * abs(c);
0114 end
0115 
0116 %% find branches with flow limits
0117 il = find(branch(:, RATE_A) ~= 0 & branch(:, RATE_A) < 1e10);
0118 nl2 = length(il);           %% number of constrained lines
0119 
0120 %%-----  run opf  -----
0121 %% build Jacobian and Hessian structure
0122 nA = size(A, 1);                %% number of original linear constraints
0123 nx = length(x0);
0124 f = branch(:, F_BUS);                           %% list of "from" buses
0125 t = branch(:, T_BUS);                           %% list of "to" buses
0126 Cf = sparse(1:nl, f, ones(nl, 1), nl, nb);      %% connection matrix for line & from buses
0127 Ct = sparse(1:nl, t, ones(nl, 1), nl, nb);      %% connection matrix for line & to buses
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 %% set options struct for IPOPT
0149 options.ipopt = ipopt_options([], mpopt);
0150 
0151 %% extra data to pass to functions
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 % %% check Jacobian and Hessian structure
0167 % xr                  = rand(size(x0));
0168 % lambda              = rand(2*nb+2*nl2, 1);
0169 % options.auxdata.Js  = jacobian(xr, options.auxdata);
0170 % options.auxdata.Hs  = tril(hessian(xr, 1, lambda, options.auxdata));
0171 % Js1 = options.auxdata.Js;
0172 % options.auxdata.Js = Js;
0173 % Hs1 = options.auxdata.Hs;
0174 % [i1, j1, s] = find(Js);
0175 % [i2, j2, s] = find(Js1);
0176 % if length(i1) ~= length(i2) || norm(i1-i2) ~= 0 || norm(j1-j2) ~= 0
0177 %     error('something''s wrong with the Jacobian structure');
0178 % end
0179 % [i1, j1, s] = find(Hs);
0180 % [i2, j2, s] = find(Hs1);
0181 % if length(i1) ~= length(i2) || norm(i1-i2) ~= 0 || norm(j1-j2) ~= 0
0182 %     error('something''s wrong with the Hessian structure');
0183 % end
0184 
0185 %% define variable and constraint bounds
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 %% assign function handles
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 %funcs.jacobianstructure = @jacobianstructure;
0200 %funcs.hessianstructure  = @hessianstructure;
0201 
0202 %% run the optimization
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 %% update solution data
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 %%-----  calculate return values  -----
0225 %% update voltages & generator outputs
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 %% compute branch flows
0233 Sf = V(branch(:, F_BUS)) .* conj(Yf * V);  %% cplx pwr at "from" bus, p.u.
0234 St = V(branch(:, T_BUS)) .* conj(Yt * V);  %% cplx pwr at "to" bus, p.u.
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 %% line constraint is actually on square of limit
0241 %% so we must fix multipliers
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 %% update Lagrange multipliers
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 %% package up results
0262 nlnN = getN(om, 'nln');
0263 
0264 %% extract multipliers for nonlinear constraints
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 %% extract multipliers for linear constraints
0273 lam_lin = info.lambda(2*nb+2*nl2+(1:nA));   %% lambda for linear constraints
0274 kl = find(lam_lin < 0);                     %% lower bound binding
0275 ku = find(lam_lin > 0);                     %% upper bound binding
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 %-----  callback functions  -----
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 % function Js = jacobianstructure(d)
0325 % Js = d.Js;
0326 %
0327 % function Hs = hessianstructure(d)
0328 % Hs = d.Hs;

Generated on Mon 26-Jan-2015 15:00:13 by m2html © 2005