Home > matpower5.1 > extras > sdp_pf > insolvablepf_limitQ.m

insolvablepf_limitQ

PURPOSE ^

INSOLVABLEPF_LIMITQ A sufficient condition for power flow insolvability

SYNOPSIS ^

function [insolvable,eta,mineigratio] = insolvablepf_limitQ(mpc,mpopt)

DESCRIPTION ^

INSOLVABLEPF_LIMITQ A sufficient condition for power flow insolvability
considering generator reactive power limits

   [INSOLVABLE,VSLACK_MIN,SIGMA,ETA,MINEIGRATIO] =
       INSOLVABLEPF_LIMITQ(MPC,MPOPT)

   Evaluates a sufficient condition for insolvability of the power flow
   equations considering generator reactive power limits. This function
   uses a mixed-integer semidefinite programming formulation of the power
   flow equations with generator reactive power limits that maximizes the
   power injections in a uniform, constant power factor profile. eta
   indicates the factor by which the power injections can be increased in
   this profile. If eta < 1, no power flow solution exists that satisfies
   the generator reactive power limits. The converse does not
   necessarily hold; a power flow solution may not exist even for cases
   that this function does not indicate are insolvable. See [1] for
   further details.

   Note that this function is only suitable for small systems due to the
   computational requirements of the mixed-integer semidefinite
   programming solver in YALMIP.

   Inputs:
       MPC : A MATPOWER case specifying the desired power flow equations.
       MPOPT : A MATPOWER options struct. If not specified, it is
           assumed to be the default mpoption.

   Outputs:
       INSOLVABLE : Binary variable. A value of 1 indicates that the
           specified power flow equations are insolvable, while a value of
           0 means that the insolvability condition is indeterminant (a
           solution may or may not exist).
       ETA : Power injection margin to the power flow solvability
           boundary in the profile of a uniform, constant power factor
           change in power injections.
       MINEIGRATIO : A measure of satisfaction of the rank relaxation.
           Large values indicate satisfaction. (Note that satisfaction of
           the rank relaxation is not required for correctness of the
           insolvability condition).

   [1] D.K. Molzahn, V. Dawar, B.C. Lesieutre, and C.L. DeMarco, "Sufficient
       Conditions for Power Flow Insolvability Considering Reactive Power
       Limited Generators with Applications to Voltage Stability Margins,"
       in Bulk Power System Dynamics and Control - IX. Optimization,
       Security and Control of the Emerging Power Grid, 2013 IREP Symposium,
       25-30 August 2013.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [insolvable,eta,mineigratio] = insolvablepf_limitQ(mpc,mpopt)
0002 %INSOLVABLEPF_LIMITQ A sufficient condition for power flow insolvability
0003 %considering generator reactive power limits
0004 %
0005 %   [INSOLVABLE,VSLACK_MIN,SIGMA,ETA,MINEIGRATIO] =
0006 %       INSOLVABLEPF_LIMITQ(MPC,MPOPT)
0007 %
0008 %   Evaluates a sufficient condition for insolvability of the power flow
0009 %   equations considering generator reactive power limits. This function
0010 %   uses a mixed-integer semidefinite programming formulation of the power
0011 %   flow equations with generator reactive power limits that maximizes the
0012 %   power injections in a uniform, constant power factor profile. eta
0013 %   indicates the factor by which the power injections can be increased in
0014 %   this profile. If eta < 1, no power flow solution exists that satisfies
0015 %   the generator reactive power limits. The converse does not
0016 %   necessarily hold; a power flow solution may not exist even for cases
0017 %   that this function does not indicate are insolvable. See [1] for
0018 %   further details.
0019 %
0020 %   Note that this function is only suitable for small systems due to the
0021 %   computational requirements of the mixed-integer semidefinite
0022 %   programming solver in YALMIP.
0023 %
0024 %   Inputs:
0025 %       MPC : A MATPOWER case specifying the desired power flow equations.
0026 %       MPOPT : A MATPOWER options struct. If not specified, it is
0027 %           assumed to be the default mpoption.
0028 %
0029 %   Outputs:
0030 %       INSOLVABLE : Binary variable. A value of 1 indicates that the
0031 %           specified power flow equations are insolvable, while a value of
0032 %           0 means that the insolvability condition is indeterminant (a
0033 %           solution may or may not exist).
0034 %       ETA : Power injection margin to the power flow solvability
0035 %           boundary in the profile of a uniform, constant power factor
0036 %           change in power injections.
0037 %       MINEIGRATIO : A measure of satisfaction of the rank relaxation.
0038 %           Large values indicate satisfaction. (Note that satisfaction of
0039 %           the rank relaxation is not required for correctness of the
0040 %           insolvability condition).
0041 %
0042 %   [1] D.K. Molzahn, V. Dawar, B.C. Lesieutre, and C.L. DeMarco, "Sufficient
0043 %       Conditions for Power Flow Insolvability Considering Reactive Power
0044 %       Limited Generators with Applications to Voltage Stability Margins,"
0045 %       in Bulk Power System Dynamics and Control - IX. Optimization,
0046 %       Security and Control of the Emerging Power Grid, 2013 IREP Symposium,
0047 %       25-30 August 2013.
0048 
0049 %   MATPOWER
0050 %   Copyright (c) 2013-2015 by Power System Engineering Research Center (PSERC)
0051 %   by Daniel Molzahn, PSERC U of Wisc, Madison
0052 %
0053 %   $Id: insolvablepf_limitQ.m 2644 2015-03-11 19:34:22Z ray $
0054 %
0055 %   This file is part of MATPOWER.
0056 %   Covered by the 3-clause BSD License (see LICENSE file for details).
0057 %   See http://www.pserc.cornell.edu/matpower/ for more info.
0058 
0059 if nargin < 2
0060     mpopt = mpoption;
0061 end
0062 
0063 mpc = loadcase(mpc);
0064 
0065 % Unpack options
0066 ignore_angle_lim    = mpopt.opf.ignore_angle_lim;
0067 verbose             = mpopt.verbose;
0068 ndisplay            = mpopt.sdp_pf.ndisplay;    %% Determine display frequency of diagonastic information
0069 
0070 maxSystemSize = 57;
0071 fixPVbusInjection = 0; % If equal to 1, don't allow changes in active power injections at PV buses.
0072 
0073 if ~have_fcn('yalmip')
0074     error('insolvablepf_limitQ: The software package YALMIP is required to run insolvablepf_limitQ. See http://users.isy.liu.se/johanl/yalmip/');
0075 end
0076 
0077 % set YALMIP options struct in SDP_PF (for details, see help sdpsettings)
0078 sdpopts = yalmip_options([], mpopt);
0079 
0080 % Change solver to YALMIP's branch-and-bound algorithm
0081 sdpopts = sdpsettings(sdpopts,'solver','bnb','bnb.solver',sdpopts.solver);
0082 
0083 if strcmp(sdpopts.solver, 'sedumi') || strcmp(sdpopts.solver,'sdpt3')
0084     sdpopts = sdpsettings(sdpopts,'solver','bnb');
0085 end
0086 
0087 %% define named indices into data matrices
0088 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
0089     VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
0090 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
0091     MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
0092     QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
0093 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0094     TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
0095     ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
0096 [PW_LINEAR, POLYNOMIAL, MODEL, STARTUP, SHUTDOWN, NCOST, COST] = idx_cost;
0097 
0098 
0099 %% Load mpc data
0100 
0101 mpc = ext2int(mpc);
0102 
0103 if toggle_dcline(mpc, 'status')
0104     error('insolvablepf_limitQ: DC lines are not implemented in insolvablepf');
0105 end
0106 
0107 nbus = size(mpc.bus,1);
0108 ngen = size(mpc.gen,1);
0109 
0110 if nbus > maxSystemSize
0111     error('insolvablepf_limitQ: System is too large (more than 57 buses) to solve with insolvablepf_limitQ');
0112 end
0113 
0114 if ~ignore_angle_lim && (any(mpc.branch(:,ANGMIN) ~= -360) || any(mpc.branch(:,ANGMAX) ~= 360))
0115     warning('insolvablepf_limitQ: Angle difference constraints are not implemented in SDP_PF. Ignoring angle difference constraints.');
0116 end
0117 
0118 % Some of the larger system (e.g., case2746wp) have generators
0119 % corresponding to buses that have bustype == PQ. Change these
0120 % to PV buses.
0121 for i=1:ngen
0122     busidx = find(mpc.bus(:,BUS_I) == mpc.gen(i,GEN_BUS));
0123     if isempty(busidx) || ~(mpc.bus(busidx,BUS_TYPE) == PV || mpc.bus(busidx,BUS_TYPE) == REF)
0124         mpc.bus(busidx,BUS_TYPE) = PV;
0125         if verbose >= 1
0126             warning('insolvablepf_limitQ: Bus %s has generator(s) but is listed as a PQ bus. Changing to a PV bus.',int2str(busidx));
0127         end
0128     end
0129 end
0130 
0131 % Buses may be listed as PV buses without associated generators. Change
0132 % these buses to PQ.
0133 for i=1:nbus
0134     if mpc.bus(i,BUS_TYPE) == PV
0135         genidx = find(mpc.gen(:,GEN_BUS) == mpc.bus(i,BUS_I), 1);
0136         if isempty(genidx)
0137             mpc.bus(i,BUS_TYPE) = PQ;
0138             if verbose >= 1
0139                 warning('insolvablepf_limitQ: PV bus %i has no associated generator! Changing these buses to PQ.',i);
0140             end
0141         end
0142     end
0143 end
0144 
0145 
0146 Sbase = mpc.baseMVA;
0147 
0148 % Create vectors of power injections and voltage magnitudes
0149 Qd = mpc.bus(:,QD) / Sbase;
0150 Qinj = -Qd;
0151 Vmag = mpc.bus(:,VM);
0152 
0153 Pd = mpc.bus(:,PD) / Sbase;
0154 Pg = zeros(nbus,1);
0155 Qmin = zeros(nbus,1);
0156 Qmax = zeros(nbus,1);
0157 for i=1:nbus
0158     genidx = find(mpc.gen(:,GEN_BUS) == i);
0159     if ~isempty(genidx)
0160         Pg(i) = sum(mpc.gen(genidx,PG)) / Sbase;
0161         Vmag(i) = mpc.gen(genidx(1),VG);
0162         Qmin(i) = sum(mpc.gen(genidx,QMIN)) / Sbase - Qd(i);
0163         Qmax(i) = sum(mpc.gen(genidx,QMAX)) / Sbase - Qd(i);
0164     end
0165 end
0166 Pinj = Pg - Pd;
0167 
0168 
0169 %% Functions to build matrices
0170 
0171 [Yk,Yk_,Mk,Ylineft,Ylinetf,Y_lineft,Y_linetf] = makesdpmat(mpc);
0172 
0173 %% Create primal SDP variables
0174 
0175 [junk1,uniqueGenIdx,junk2] = unique(mpc.gen(:,GEN_BUS));
0176 mpc.gen = mpc.gen(uniqueGenIdx,:);
0177 ngen = size(mpc.gen,1);
0178 
0179 W = sdpvar(2*nbus,2*nbus);
0180 eta = sdpvar(1,1);
0181 constraints = [];
0182 
0183 % Binary variables
0184 yL = binvar(ngen,1);
0185 yU = binvar(ngen,1);
0186 
0187 % We need a number greater than any plausible value of V^2, but too large
0188 % of a value causes numerical problems
0189 bigM = 10*max(Vmag)^2; 
0190 
0191 %% Build primal problem
0192 
0193 for k=1:nbus
0194     
0195     if ~fixPVbusInjection
0196         % PQ and PV buses have uniform active power injection changes
0197         if mpc.bus(k,BUS_TYPE) == PQ || mpc.bus(k,BUS_TYPE) == PV
0198             constraints = [constraints; 
0199                 trace(Yk(k)*W) == eta*Pinj(k)];
0200         end
0201     else
0202         % Alternatively, we can fix PV bus active power injections for a
0203         % different power injection profile.
0204         if mpc.bus(k,BUS_TYPE) == PQ 
0205             constraints = [constraints; 
0206                 trace(Yk(k)*W) == eta*Pinj(k)];
0207         end
0208         if mpc.bus(k,BUS_TYPE) == PV
0209             constraints = [constraints; 
0210                 trace(Yk(k)*W) == Pinj(k)];
0211         end    
0212     end
0213         
0214     % PQ buses have uniform reactive power injection changes
0215     if mpc.bus(k,BUS_TYPE) == PQ
0216             constraints = [constraints;
0217                 trace(Yk_(k)*W) == eta*Qinj(k)];
0218     end
0219     
0220     % Mixed integer formulation for generator reactive power limits
0221     if mpc.bus(k,BUS_TYPE) == PV || mpc.bus(k,BUS_TYPE) == REF
0222         
0223         genidx = find(mpc.gen(:,GEN_BUS) == k,1);
0224         
0225         constraints = [constraints;
0226             trace(Yk_(k)*W) <= Qmin(k)*yL(genidx) + Qmax(k)*(1-yL(genidx));
0227             trace(Yk_(k)*W) >= Qmax(k)*yU(genidx) + Qmin(k)*(1-yU(genidx))];
0228 
0229         constraints = [constraints;
0230             trace(Mk(k)*W) >= Vmag(k)^2*(1-yU(genidx));
0231             trace(Mk(k)*W) <= Vmag(k)^2*(1-yL(genidx)) + bigM*(yL(genidx))];
0232         
0233         constraints = [constraints;
0234             yU(genidx) + yL(genidx) <= 1];
0235         
0236     end
0237     
0238     if verbose >= 2 && mod(k,ndisplay) == 0
0239         fprintf('SDP creation: Bus %i of %i\n',k,nbus);
0240     end
0241     
0242 end % Loop through all buses
0243 
0244 % Force at least one bus to supply reactive power balance
0245 % genbuses = (mpc.bus(:,BUS_TYPE) == PV | mpc.bus(:,BUS_TYPE) == REF);
0246 % constraints = [constraints;
0247 %     sum(yL(genbuses)+yU(genbuses)) <= ngen - 1];
0248 constraints = [constraints;
0249     sum(yL + yU) <= ngen - 1];
0250 
0251 constraints = [constraints; W >= 0];
0252 
0253 
0254 
0255 %% Solve the SDP
0256 
0257 % Preserve warning settings
0258 S = warning;
0259 
0260 % Run sdp solver
0261 sdpinfo = solvesdp(constraints, -eta, sdpopts);
0262 warning(S);
0263 
0264 if verbose >= 2
0265     fprintf('Solver exit message: %s\n',sdpinfo.info);
0266 end
0267 
0268 
0269 %% Calculate rank characteristics of the solution
0270 
0271 evl = sort(eig(double(W)));
0272 mineigratio = abs(evl(end) / evl(end-2));
0273 
0274 
0275 %% Output results
0276 
0277 eta = double(eta);
0278 insolvable = eta < 1; % Is this right? I think it should be the other way around...

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