Home > matpower5.1 > extras > misc > make_opf_feasible.m

make_opf_feasible

PURPOSE ^

MAKE_OPF_FEASIBLE Attempts to relax constraints to make an OPF feasible.

SYNOPSIS ^

function [r, chgs] = make_opf_feasible(mpc, mpopt)

DESCRIPTION ^

MAKE_OPF_FEASIBLE Attempts to relax constraints to make an OPF feasible.
   [RESULTS, CHGS] = MAKE_OPF_FEASIBLE(MPC, MPOPT) 

   Attempts to automate the process of finding a feasible OPF solution when
   starting with an infeasible case.

   MPC - initial (possibly infeasible) MATPOWER case struct
   MPOPT - (optional) MATPOWER options struct.

   Work-in-progress:   CHGS are currently not returned.
                       At this point, the code *is* the documentation.

   See also RUNOPF.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [r, chgs] = make_opf_feasible(mpc, mpopt)
0002 %MAKE_OPF_FEASIBLE Attempts to relax constraints to make an OPF feasible.
0003 %   [RESULTS, CHGS] = MAKE_OPF_FEASIBLE(MPC, MPOPT)
0004 %
0005 %   Attempts to automate the process of finding a feasible OPF solution when
0006 %   starting with an infeasible case.
0007 %
0008 %   MPC - initial (possibly infeasible) MATPOWER case struct
0009 %   MPOPT - (optional) MATPOWER options struct.
0010 %
0011 %   Work-in-progress:   CHGS are currently not returned.
0012 %                       At this point, the code *is* the documentation.
0013 %
0014 %   See also RUNOPF.
0015 
0016 %   MATPOWER
0017 %   Copyright (c) 2014-2015 by Power System Engineering Research Center (PSERC)
0018 %   by Ray Zimmerman, PSERC Cornell
0019 %
0020 %   $Id: make_opf_feasible.m 2644 2015-03-11 19:34:22Z ray $
0021 %
0022 %   This file is part of MATPOWER.
0023 %   Covered by the 3-clause BSD License (see LICENSE file for details).
0024 %   See http://www.pserc.cornell.edu/matpower/ for more info.
0025 
0026 %% define constants
0027 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
0028     VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
0029 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0030     TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
0031     ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
0032 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
0033     MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
0034     QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
0035 
0036 %%-----  process inputs  -----
0037 if nargin < 2
0038     mpopt = mpoption();
0039 end
0040 
0041 %% initialize
0042 msg = '';
0043 done = 0;
0044 rc = 0;     %% return code
0045 
0046 %%-----  on-line generation capacity <= fixed load  -----
0047 ig = find(~isload(mpc.gen) & mpc.gen(:, GEN_STATUS) > 0);
0048 total_Pmax = sum(mpc.gen(ig, PMAX));
0049 total_Pd   = total_load(mpc.bus, [], 'all');
0050 if total_Pmax <= total_Pd
0051     msg = sprintf('%stotal fixed load (%g MW) > total on-line generation capacity (%g MW)\n', ...
0052         msg, total_Pd, total_Pmax);
0053     r = mpc;
0054     r.success = 0;
0055     r.f = NaN;
0056     rc = -2;        %% inadequate on-line generation capacity
0057     done = 1;
0058 end
0059 
0060 %%-----  check for infeasible limits  -----
0061 if ~done
0062     %% generator P limits
0063     g = find(mpc.gen(:, PMIN) > mpc.gen(:, PMAX) & mpc.gen(:, GEN_STATUS) > 0);
0064     if ~isempty(g)
0065         for k = 1:length(g)
0066             msg = sprintf('%sPmax (%g) < Pmin (%g) for generator %d at bus %d, ', ...
0067                 msg, mpc.gen(g(k), PMAX), mpc.gen(g(k), PMIN), g(k), mpc.gen(g(k), GEN_BUS));
0068             %% decide which limit to move based on where Pg is
0069             if mpc.gen(g(k), PG) >= mpc.gen(g(k), PMIN)
0070                 mpc.gen(g(k), PMAX) = mpc.gen(g(k), PMIN);      %% move Pmax
0071                 msg = sprintf('%smove Pmax\n', msg);
0072             elseif mpc.gen(g(k), PG) <= mpc.gen(g(k), PMAX)
0073                 mpc.gen(g(k), PMAX) = mpc.gen(g(k), PMIN);      %% move Pmin
0074                 msg = sprintf('%smove Pmax\n', msg);
0075             else
0076                 tmp = mpc.gen(g(k), PMAX);                      %% swap 'em
0077                 mpc.gen(g(k), PMAX) = mpc.gen(g(k), PMIN);
0078                 mpc.gen(g(k), PMIN) = tmp;
0079                 msg = sprintf('%sswap Pmin and Pmax\n', msg);
0080             end
0081         end
0082         rc = 2;         %% fixed generation capacity limits
0083     end
0084     
0085     %% generator Q limits
0086 %     rc = 3;         %% fixed reactive generation capacity limits
0087 
0088     %% voltage angle limits
0089 %     rc = 4;         %% fixed voltage angle limits
0090 
0091     %% voltage magnitude limits
0092 %     rc = 5;         %% fixed voltage magnitude limits
0093 
0094     %% negative branch flow limits
0095 %     rc = 6;         %% fixed negative branch flow limits
0096 
0097     %% run initial (infeasible?) case
0098     r = runopf(mpc, mpopt);
0099     if r.success
0100         done = 1;
0101     end
0102 end
0103 
0104 %%-----  attempt with short term branch ratings  -----
0105 if ~done
0106     %% get branch limits
0107     rate_a = mpc.branch(:, RATE_A);
0108     rate_b = mpc.branch(:, RATE_B);
0109     rate_c = mpc.branch(:, RATE_C);
0110     rate_a(rate_a == 0) = Inf;
0111     rate_b(rate_b == 0) = Inf;
0112     rate_c(rate_c == 0) = Inf;
0113 
0114     %% set short term limits
0115     rating = max([rate_a rate_b], [], 2);
0116     rating(isinf(rating)) = 0;
0117     mpc.branch(:, RATE_A) = rating;
0118     r = runopf(mpc, mpopt);
0119     if r.success
0120         done = 1;
0121         rc = 7;         %% using short-term branch ratings
0122         msg = sprintf('%susing short-term branch ratings\n', msg);
0123     end
0124 end
0125 
0126 %%-----  attempt with emergency branch ratings  -----
0127 if ~done
0128     %% set emergency limits
0129     rating = max([rate_a rate_b rate_c], [], 2);
0130     rating(isinf(rating)) = 0;
0131     mpc.branch(:, RATE_A) = rating;
0132     r = runopf(mpc, mpopt);
0133 
0134     if r.success
0135         done = 1;
0136         rc = 8;         %% using emergency branch ratings
0137         msg = sprintf('%susing emergency branch ratings\n', msg);
0138     end
0139 end
0140 
0141 %%-----  attempt without branch flow limits  -----
0142 if ~done
0143     %% try with no line limits
0144     mpc.branch(:, RATE_A) = 0;
0145     r = runopf(mpc, mpopt);
0146                 
0147     if ~r.success
0148         done = 1;
0149         msg = sprintf('%sstill infeasible without line limits\n', msg);
0150     else
0151         %% the following lines should be eliminated when I do further
0152         %% relaxations
0153         msg = sprintf('%susing no branch limits\n', msg);
0154         rc = 9;         %% using no branch ratings
0155     end
0156 end
0157 
0158 %%-----  try again, relaxing only violated limits  -----
0159 if ~done
0160 
0161 end
0162 
0163 %% include msg in output
0164 r.msg = msg;
0165 r.rc  = rc;
0166 if mpopt.verbose
0167     fprintf('%s', r.msg);
0168 end

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