Home > matpower5.1 > opf_execute.m

opf_execute

PURPOSE ^

OPF_EXECUTE Executes the OPF specified by an OPF model object.

SYNOPSIS ^

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

DESCRIPTION ^

OPF_EXECUTE  Executes the OPF specified by an OPF model object.
   [RESULTS, SUCCESS, RAW] = OPF_EXECUTE(OM, MPOPT)

   RESULTS are returned with internal indexing, all equipment
   in-service, etc.

   See also OPF, OPF_SETUP.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [results, success, raw] = opf_execute(om, mpopt)
0002 %OPF_EXECUTE  Executes the OPF specified by an OPF model object.
0003 %   [RESULTS, SUCCESS, RAW] = OPF_EXECUTE(OM, MPOPT)
0004 %
0005 %   RESULTS are returned with internal indexing, all equipment
0006 %   in-service, etc.
0007 %
0008 %   See also OPF, OPF_SETUP.
0009 
0010 %   MATPOWER
0011 %   Copyright (c) 2009-2015 by Power System Engineering Research Center (PSERC)
0012 %   by Ray Zimmerman, PSERC Cornell
0013 %
0014 %   $Id: opf_execute.m 2644 2015-03-11 19:34:22Z ray $
0015 %
0016 %   This file is part of MATPOWER.
0017 %   Covered by the 3-clause BSD License (see LICENSE file for details).
0018 %   See http://www.pserc.cornell.edu/matpower/ for more info.
0019 
0020 %% define named indices into data matrices
0021 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
0022     VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
0023 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
0024     MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
0025     QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
0026 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0027     TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
0028     ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
0029 
0030 %%-----  setup  -----
0031 %% options
0032 dc  = strcmp(upper(mpopt.model), 'DC');
0033 alg = upper(mpopt.opf.ac.solver);
0034 sdp = strcmp(alg, 'SDPOPF');
0035 
0036 %% build user-defined costs
0037 om = build_cost_params(om);
0038 
0039 %% get indexing
0040 [vv, ll, nn] = get_idx(om);
0041 
0042 if mpopt.verbose > 0
0043     v = mpver('all');
0044     fprintf('\nMATPOWER Version %s, %s', v.Version, v.Date);
0045 end
0046 
0047 %%-----  run DC OPF solver  -----
0048 if dc
0049   if mpopt.verbose > 0
0050     fprintf(' -- DC Optimal Power Flow\n');
0051   end
0052   [results, success, raw] = dcopf_solver(om, mpopt);
0053 else
0054   %%-----  run AC OPF solver  -----
0055   if mpopt.verbose > 0
0056     fprintf(' -- AC Optimal Power Flow\n');
0057   end
0058 
0059   %% if opf.ac.solver not set, choose best available option
0060   if strcmp(alg, 'DEFAULT')
0061     if have_fcn('pdipmopf')
0062       alg = 'PDIPM';            %% PDIPM
0063     else
0064       alg = 'MIPS';             %% MIPS
0065     end
0066     mpopt = mpoption(mpopt, 'opf.ac.solver', alg);
0067   end
0068 
0069   %% run specific AC OPF solver
0070   switch alg
0071     case 'MIPS'
0072       [results, success, raw] = mipsopf_solver(om, mpopt);
0073     case 'IPOPT'
0074       if ~have_fcn('ipopt')
0075         error('opf_execute: MPOPT.opf.ac.solver = ''%s'' requires IPOPT (see http://www.coin-or.org/projects/Ipopt.xml)', alg);
0076       end
0077       [results, success, raw] = ipoptopf_solver(om, mpopt);
0078     case 'PDIPM'
0079       if mpopt.pdipm.step_control
0080         if ~have_fcn('scpdipmopf')
0081           error('opf_execute: MPOPT.opf.ac.solver = ''%s'' requires SCPDIPMOPF (see http://www.pserc.cornell.edu/tspopf/)', alg);
0082         end
0083       else
0084         if ~have_fcn('pdipmopf')
0085           error('opf_execute: MPOPT.opf.ac.solver = ''%s'' requires PDIPMOPF (see http://www.pserc.cornell.edu/tspopf/)', alg);
0086         end
0087       end
0088       [results, success, raw] = tspopf_solver(om, mpopt);
0089     case 'TRALM'
0090       if ~have_fcn('tralmopf')
0091         error('opf_execute: MPOPT.opf.ac.solver = ''%s'' requires TRALM (see http://www.pserc.cornell.edu/tspopf/)', alg);
0092       end
0093       [results, success, raw] = tspopf_solver(om, mpopt);
0094     case 'MINOPF'
0095       if ~have_fcn('minopf')
0096         error('opf_execute: MPOPT.opf.ac.solver = ''%s'' requires MINOPF (see http://www.pserc.cornell.edu/minopf/)', alg);
0097       end
0098       [results, success, raw] = mopf_solver(om, mpopt);
0099     case 'FMINCON'
0100       if ~have_fcn('fmincon')
0101         error('opf_execute: MPOPT.opf.ac.solver = ''%s'' requires FMINCON (Optimization Toolbox 2.x or later)', alg);
0102       end
0103       [results, success, raw] = fmincopf_solver(om, mpopt);
0104     case 'KNITRO'
0105       if ~have_fcn('knitro')
0106         error('opf_execute: MPOPT.opf.ac.solver = ''%s'' requires KNITRO (see http://www.ziena.com/)', alg);
0107       end
0108       [results, success, raw] = ktropf_solver(om, mpopt);
0109     case 'SDPOPF'
0110       if ~have_fcn('yalmip')
0111         error('opf_execute: MPOPT.opf.ac.solver = ''%s'' requires YALMIP (see http://users.isy.liu.se/johanl/yalmip/)', alg);
0112       end
0113       [results, success, raw] = sdpopf_solver(om, mpopt);
0114     otherwise
0115       error('opf_execute: MPOPT.opf.ac.solver = ''%s'' is not a valid AC OPF solver selection', alg);
0116   end
0117 end
0118 if ~isfield(raw, 'output') || ~isfield(raw.output, 'alg') || isempty(raw.output.alg)
0119     raw.output.alg = alg;
0120 end
0121 
0122 if success
0123   if ~dc && ~sdp
0124     %% copy bus voltages back to gen matrix
0125     results.gen(:, VG) = results.bus(results.gen(:, GEN_BUS), VM);
0126 
0127     %% gen PQ capability curve multipliers
0128     if ll.N.PQh > 0 || ll.N.PQl > 0
0129       mu_PQh = results.mu.lin.l(ll.i1.PQh:ll.iN.PQh) - results.mu.lin.u(ll.i1.PQh:ll.iN.PQh);
0130       mu_PQl = results.mu.lin.l(ll.i1.PQl:ll.iN.PQl) - results.mu.lin.u(ll.i1.PQl:ll.iN.PQl);
0131       Apqdata = userdata(om, 'Apqdata');
0132       results.gen = update_mupq(results.baseMVA, results.gen, mu_PQh, mu_PQl, Apqdata);
0133     end
0134 
0135     %% compute g, dg, f, df, d2f if requested by opf.return_raw_der = 1
0136     if mpopt.opf.return_raw_der
0137       %% move from results to raw if using v4.0 of MINOPF or TSPOPF
0138       if isfield(results, 'dg')
0139         raw.dg = results.dg;
0140         raw.g = results.g;
0141       end
0142       %% compute g, dg, unless already done by post-v4.0 MINOPF or TSPOPF
0143       if ~isfield(raw, 'dg')
0144         mpc = get_mpc(om);
0145         [Ybus, Yf, Yt] = makeYbus(mpc.baseMVA, mpc.bus, mpc.branch);
0146         [g, geq, dg, dgeq] = opf_consfcn(results.x, om, Ybus, Yf, Yt, mpopt);
0147         raw.g = [ geq; g];
0148         raw.dg = [ dgeq'; dg'];   %% true Jacobian organization
0149       end
0150       %% compute df, d2f
0151       [f, df, d2f] = opf_costfcn(results.x, om);
0152       raw.df = df;
0153       raw.d2f = d2f;
0154     end
0155   end
0156 
0157   %% delete g and dg fieldsfrom results if using v4.0 of MINOPF or TSPOPF
0158   if isfield(results, 'dg')
0159     rmfield(results, 'dg');
0160     rmfield(results, 'g');
0161   end
0162 
0163   %% angle limit constraint multipliers
0164   if ~sdp && ll.N.ang > 0
0165     iang = userdata(om, 'iang');
0166     results.branch(iang, MU_ANGMIN) = results.mu.lin.l(ll.i1.ang:ll.iN.ang) * pi/180;
0167     results.branch(iang, MU_ANGMAX) = results.mu.lin.u(ll.i1.ang:ll.iN.ang) * pi/180;
0168   end
0169 else
0170   %% assign empty g, dg, f, df, d2f if requested by opf.return_raw_der = 1
0171   if ~dc && mpopt.opf.return_raw_der
0172     raw.dg = [];
0173     raw.g = [];
0174     raw.df = [];
0175     raw.d2f = [];
0176   end
0177 end
0178 
0179 if ~sdp
0180   %% assign values and limit shadow prices for variables
0181   om_var_order = get(om, 'var', 'order');
0182   for k = 1:length(om_var_order)
0183     name = om_var_order(k).name;
0184     if getN(om, 'var', name)
0185       idx = vv.i1.(name):vv.iN.(name);
0186       results.var.val.(name) = results.x(idx);
0187       results.var.mu.l.(name) = results.mu.var.l(idx);
0188       results.var.mu.u.(name) = results.mu.var.u(idx);
0189     end
0190   end
0191 
0192   %% assign shadow prices for linear constraints
0193   om_lin_order = get(om, 'lin', 'order');
0194   for k = 1:length(om_lin_order)
0195     name = om_lin_order(k).name;
0196     if getN(om, 'lin', name)
0197       idx = ll.i1.(name):ll.iN.(name);
0198       results.lin.mu.l.(name) = results.mu.lin.l(idx);
0199       results.lin.mu.u.(name) = results.mu.lin.u(idx);
0200     end
0201   end
0202 
0203   %% assign shadow prices for nonlinear constraints
0204   if ~dc
0205     om_nln_order = get(om, 'nln', 'order');
0206     for k = 1:length(om_nln_order)
0207       name = om_nln_order(k).name;
0208       if getN(om, 'nln', name)
0209         idx = nn.i1.(name):nn.iN.(name);
0210         results.nln.mu.l.(name) = results.mu.nln.l(idx);
0211         results.nln.mu.u.(name) = results.mu.nln.u(idx);
0212       end
0213     end
0214   end
0215 
0216   %% assign values for components of user cost
0217   om_cost_order = get(om, 'cost', 'order');
0218   for k = 1:length(om_cost_order)
0219     name = om_cost_order(k).name;
0220     if getN(om, 'cost', name)
0221       results.cost.(name) = compute_cost(om, results.x, name);
0222     end
0223   end
0224 
0225   %% if single-block PWL costs were converted to POLY, insert dummy y into x
0226   %% Note: The "y" portion of x will be nonsense, but everything should at
0227   %%       least be in the expected locations.
0228   pwl1 = userdata(om, 'pwl1');
0229   if ~isempty(pwl1) && ~strcmp(alg, 'TRALM') && ~(strcmp(alg, 'PDIPM') && mpopt.pdipm.step_control)
0230     %% get indexing
0231     vv = get_idx(om);
0232     if dc
0233       nx = vv.iN.Pg;
0234     else
0235       nx = vv.iN.Qg;
0236     end
0237     y = zeros(length(pwl1), 1);
0238     raw.xr = [ raw.xr(1:nx); y; raw.xr(nx+1:end)];
0239     results.x = [ results.x(1:nx); y; results.x(nx+1:end)];
0240   end
0241 end

Generated on Fri 20-Mar-2015 18:23:34 by m2html © 2005