Home > matpower5.0 > scale_load.m

scale_load

PURPOSE ^

SCALE_LOAD Scales fixed and/or dispatchable loads.

SYNOPSIS ^

function [bus, gen, gencost] = scale_load(load, bus, gen, load_zone, opt, gencost)

DESCRIPTION ^

SCALE_LOAD Scales fixed and/or dispatchable loads.
   BUS = SCALE_LOAD(LOAD, BUS);
   [BUS, GEN] = SCALE_LOAD(LOAD, BUS, GEN, LOAD_ZONE, OPT)
   [BUS, GEN, GENCOST] = ...
       SCALE_LOAD(LOAD, BUS, GEN, LOAD_ZONE, OPT, GENCOST)

   Scales active (and optionally reactive) loads in each zone by a
   zone-specific ratio, i.e. R(k) for zone k. Inputs are ...

   LOAD - Each element specifies the amount of scaling for the
       corresponding load zone, either as a direct scale factor
       or as a target quantity. If there are nz load zones this
       vector has nz elements.

   BUS - standard BUS matrix with nb rows, where the fixed active
       and reactive loads available for scaling are specified in
       columns PD and QD

   GEN - (optional) standard GEN matrix with ng rows, where the
       dispatchable loads available for scaling are specified by
       columns PG, QG, PMIN, QMIN and QMAX (in rows for which
       ISLOAD(GEN) returns true). If GEN is empty, it assumes
       there are no dispatchable loads.

   LOAD_ZONE - (optional) nb element vector where the value of
       each element is either zero or the index of the load zone
       to which the corresponding bus belongs. If LOAD_ZONE(b) = k
       then the loads at bus b will be scaled according to the
       value of LOAD(k). If LOAD_ZONE(b) = 0, the loads at bus b
       will not be modified. If LOAD_ZONE is empty, the default is
       determined by the dimensions of the LOAD vector. If LOAD is
       a scalar, a single system-wide zone including all buses is
       used, i.e. LOAD_ZONE = ONES(nb, 1). If LOAD is a vector, the
       default LOAD_ZONE is defined as the areas specified in the
       BUS matrix, i.e. LOAD_ZONE = BUS(:, BUS_AREA), and LOAD
       should have dimension = MAX(BUS(:, BUS_AREA)).

   OPT - (optional) struct with three possible fields, 'scale',
       'pq' and 'which' that determine the behavior as follows:

     OPT.scale (default is 'FACTOR')
       'FACTOR'   : LOAD consists of direct scale factors, where
                    LOAD(k) = scale factor R(k) for zone k
       'QUANTITY' : LOAD consists of target quantities, where
                    LOAD(k) = desired total active load in MW for
                    zone k after scaling by an appropriate R(k)

     OPT.pq    (default is 'PQ')
       'PQ' : scale both active and reactive loads
       'P'  : scale only active loads

     OPT.which (default is 'BOTH' if GEN is provided, else 'FIXED')
       'FIXED'        : scale only fixed loads
       'DISPATCHABLE' : scale only dispatchable loads
       'BOTH'         : scale both fixed and dispatchable loads

   GENCOST - (optional) standard GENCOST matrix with ng (or 2*ng)
       rows, where the dispatchable load rows are determined by
       the GEN matrix. If included, the quantity axis of the marginal
       "cost" or benefit function of any dispatchable loads will be
       scaled with the size of the load itself (using MODCOST twice,
       once with MODTYPE equal to SCALE_F and once with SCALE_X).

   Examples:
       Scale all real and reactive fixed loads up by 10%.

       bus = scale_load(1.1, bus);

       Scale all active loads (fixed and dispatchable) at the first 10
       buses so their total equals 100 MW, and at next 10 buses so their
       total equals 50 MW.

       load_zone = zeros(nb, 1);
       load_zone(1:10) = 1;
       load_zone(11:20) = 2;
       opt = struct('pq', 'P', 'scale', 'QUANTITY');
       load = [100; 50];
       [bus, gen] = scale_load(load, bus, gen, load_zone, opt);

   See also TOTAL_LOAD.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [bus, gen, gencost] = scale_load(load, bus, gen, load_zone, opt, gencost)
0002 %SCALE_LOAD Scales fixed and/or dispatchable loads.
0003 %   BUS = SCALE_LOAD(LOAD, BUS);
0004 %   [BUS, GEN] = SCALE_LOAD(LOAD, BUS, GEN, LOAD_ZONE, OPT)
0005 %   [BUS, GEN, GENCOST] = ...
0006 %       SCALE_LOAD(LOAD, BUS, GEN, LOAD_ZONE, OPT, GENCOST)
0007 %
0008 %   Scales active (and optionally reactive) loads in each zone by a
0009 %   zone-specific ratio, i.e. R(k) for zone k. Inputs are ...
0010 %
0011 %   LOAD - Each element specifies the amount of scaling for the
0012 %       corresponding load zone, either as a direct scale factor
0013 %       or as a target quantity. If there are nz load zones this
0014 %       vector has nz elements.
0015 %
0016 %   BUS - standard BUS matrix with nb rows, where the fixed active
0017 %       and reactive loads available for scaling are specified in
0018 %       columns PD and QD
0019 %
0020 %   GEN - (optional) standard GEN matrix with ng rows, where the
0021 %       dispatchable loads available for scaling are specified by
0022 %       columns PG, QG, PMIN, QMIN and QMAX (in rows for which
0023 %       ISLOAD(GEN) returns true). If GEN is empty, it assumes
0024 %       there are no dispatchable loads.
0025 %
0026 %   LOAD_ZONE - (optional) nb element vector where the value of
0027 %       each element is either zero or the index of the load zone
0028 %       to which the corresponding bus belongs. If LOAD_ZONE(b) = k
0029 %       then the loads at bus b will be scaled according to the
0030 %       value of LOAD(k). If LOAD_ZONE(b) = 0, the loads at bus b
0031 %       will not be modified. If LOAD_ZONE is empty, the default is
0032 %       determined by the dimensions of the LOAD vector. If LOAD is
0033 %       a scalar, a single system-wide zone including all buses is
0034 %       used, i.e. LOAD_ZONE = ONES(nb, 1). If LOAD is a vector, the
0035 %       default LOAD_ZONE is defined as the areas specified in the
0036 %       BUS matrix, i.e. LOAD_ZONE = BUS(:, BUS_AREA), and LOAD
0037 %       should have dimension = MAX(BUS(:, BUS_AREA)).
0038 %
0039 %   OPT - (optional) struct with three possible fields, 'scale',
0040 %       'pq' and 'which' that determine the behavior as follows:
0041 %
0042 %     OPT.scale (default is 'FACTOR')
0043 %       'FACTOR'   : LOAD consists of direct scale factors, where
0044 %                    LOAD(k) = scale factor R(k) for zone k
0045 %       'QUANTITY' : LOAD consists of target quantities, where
0046 %                    LOAD(k) = desired total active load in MW for
0047 %                    zone k after scaling by an appropriate R(k)
0048 %
0049 %     OPT.pq    (default is 'PQ')
0050 %       'PQ' : scale both active and reactive loads
0051 %       'P'  : scale only active loads
0052 %
0053 %     OPT.which (default is 'BOTH' if GEN is provided, else 'FIXED')
0054 %       'FIXED'        : scale only fixed loads
0055 %       'DISPATCHABLE' : scale only dispatchable loads
0056 %       'BOTH'         : scale both fixed and dispatchable loads
0057 %
0058 %   GENCOST - (optional) standard GENCOST matrix with ng (or 2*ng)
0059 %       rows, where the dispatchable load rows are determined by
0060 %       the GEN matrix. If included, the quantity axis of the marginal
0061 %       "cost" or benefit function of any dispatchable loads will be
0062 %       scaled with the size of the load itself (using MODCOST twice,
0063 %       once with MODTYPE equal to SCALE_F and once with SCALE_X).
0064 %
0065 %   Examples:
0066 %       Scale all real and reactive fixed loads up by 10%.
0067 %
0068 %       bus = scale_load(1.1, bus);
0069 %
0070 %       Scale all active loads (fixed and dispatchable) at the first 10
0071 %       buses so their total equals 100 MW, and at next 10 buses so their
0072 %       total equals 50 MW.
0073 %
0074 %       load_zone = zeros(nb, 1);
0075 %       load_zone(1:10) = 1;
0076 %       load_zone(11:20) = 2;
0077 %       opt = struct('pq', 'P', 'scale', 'QUANTITY');
0078 %       load = [100; 50];
0079 %       [bus, gen] = scale_load(load, bus, gen, load_zone, opt);
0080 %
0081 %   See also TOTAL_LOAD.
0082 
0083 %   MATPOWER
0084 %   $Id: scale_load.m 2122 2013-03-13 20:08:01Z ray $
0085 %   by Ray Zimmerman, PSERC Cornell
0086 %   Copyright (c) 2004-2010 by Power System Engineering Research Center (PSERC)
0087 %
0088 %   This file is part of MATPOWER.
0089 %   See http://www.pserc.cornell.edu/matpower/ for more info.
0090 %
0091 %   MATPOWER is free software: you can redistribute it and/or modify
0092 %   it under the terms of the GNU General Public License as published
0093 %   by the Free Software Foundation, either version 3 of the License,
0094 %   or (at your option) any later version.
0095 %
0096 %   MATPOWER is distributed in the hope that it will be useful,
0097 %   but WITHOUT ANY WARRANTY; without even the implied warranty of
0098 %   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0099 %   GNU General Public License for more details.
0100 %
0101 %   You should have received a copy of the GNU General Public License
0102 %   along with MATPOWER. If not, see <http://www.gnu.org/licenses/>.
0103 %
0104 %   Additional permission under GNU GPL version 3 section 7
0105 %
0106 %   If you modify MATPOWER, or any covered work, to interface with
0107 %   other modules (such as MATLAB code and MEX-files) available in a
0108 %   MATLAB(R) or comparable environment containing parts covered
0109 %   under other licensing terms, the licensors of MATPOWER grant
0110 %   you additional permission to convey the resulting work.
0111 
0112 %% define constants
0113 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
0114     VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
0115 %% purposely being backward compatible with older MATPOWER
0116 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, ...
0117     PMAX, PMIN, MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN] = idx_gen;
0118 
0119 nb = size(bus, 1);          %% number of buses
0120 
0121 %%-----  process inputs  -----
0122 if nargin < 6
0123     gencost = [];
0124     if nargin < 5
0125         opt = struct;
0126         if nargin < 4
0127             load_zone = [];
0128             if nargin < 3
0129                 gen = [];
0130             end
0131         end
0132     end
0133 end
0134 
0135 %% fill out and check opt
0136 if isempty(gen)
0137     opt.which = 'FIXED';
0138 end
0139 if ~isfield(opt, 'pq')
0140     opt.pq = 'PQ';          %% 'PQ' or 'P'
0141 end
0142 if ~isfield(opt, 'which')
0143     opt.which = 'BOTH';     %% 'FIXED', 'DISPATCHABLE' or 'BOTH'
0144 end
0145 if ~isfield(opt, 'scale')
0146     opt.scale = 'FACTOR';   %% 'FACTOR' or 'QUANTITY'
0147 end
0148 if ~strcmp(opt.pq, 'P') && ~strcmp(opt.pq, 'PQ')
0149     error('scale_load: opt.pq must equal ''PQ'' or ''P''');
0150 end
0151 if opt.which(1) ~= 'F' && opt.which(1) ~= 'D' && opt.which(1) ~= 'B'
0152     error('scale_load: opt.which should be ''FIXED'', ''DISPATCHABLE'' or ''BOTH''');
0153 end
0154 if opt.scale(1) ~= 'F' && opt.scale(1) ~= 'Q'
0155     error('scale_load: opt.scale should be ''FACTOR'' or ''QUANTITY''');
0156 end
0157 if isempty(gen) && opt.which(1) ~= 'F'
0158     error('scale_load: need gen matrix to scale dispatchable loads');
0159 end
0160 if nargout < 3 && ~isempty(gencost)
0161     error('scale_load: missing gencost as output argument');
0162 end
0163 if nargout > 2 && isempty(gencost)
0164     error('scale_load: missing gencost as input argument');
0165 end
0166 
0167 %% create dispatchable load connection matrix
0168 if ~isempty(gen)
0169     ng = size(gen, 1);
0170     is_ld = isload(gen) & gen(:, GEN_STATUS) > 0;
0171     ld = find(is_ld);
0172 
0173     %% create map of external bus numbers to bus indices
0174     i2e = bus(:, BUS_I);
0175     e2i = sparse(max(i2e), 1);
0176     e2i(i2e) = (1:nb)';
0177 
0178     Cld = sparse(e2i(gen(:, GEN_BUS)), (1:ng)', is_ld, nb, ng);
0179 else
0180     ng = [];
0181     ld = [];
0182 end
0183 
0184 if isempty(load_zone)
0185     if length(load) == 1        %% make a single zone of all load buses
0186         load_zone = zeros(nb, 1);                           %% initialize
0187         load_zone(bus(:, PD) ~= 0 | bus(:, QD) ~= 0) = 1;   %% FIXED loads
0188         if ~isempty(gen)
0189             load_zone(e2i(gen(ld, GEN_BUS))) = 1;   %% DISPATCHABLE loads
0190         end
0191     else                        %% use areas defined in bus data as zones
0192         load_zone = bus(:, BUS_AREA);
0193     end
0194 end
0195 
0196 %% check load_zone to make sure it's consistent with size of load vector
0197 if max(load_zone) > length(load)
0198     error('scale_load: load vector must have a value for each load zone specified');
0199 end
0200 
0201 %%-----  compute scale factors for each zone  -----
0202 scale = load;
0203 Pdd = zeros(nb, 1);     %% dispatchable P at each bus
0204 if opt.scale(1) == 'Q'  %% 'QUANTITY'
0205     %% find load capacity from dispatchable loads
0206     if ~isempty(gen)
0207         Pdd = -Cld * gen(:, PMIN);
0208     end
0209 
0210     %% compute scale factors
0211     for k = 1:length(load)
0212         idx = find( load_zone == k );
0213         fixed = sum(bus(idx, PD));
0214         dispatchable = sum(Pdd(idx));
0215         total = fixed + dispatchable;
0216         if opt.which(1) == 'B'      %% 'BOTH'
0217             if total ~= 0
0218                 scale(k) = load(k) / total;
0219             elseif load(k) == total
0220                 scale(k) = 1;
0221             else
0222                 error('scale_load: impossible to make zone %d load equal %g by scaling non-existent loads', k, load(k));
0223             end
0224         elseif opt.which(1) == 'F'  %% 'FIXED'
0225             if fixed ~= 0
0226                 scale(k) = (load(k) - dispatchable) / fixed;
0227             elseif load(k) == dispatchable
0228                 scale(k) = 1;
0229             else
0230                 error('scale_load: impossible to make zone %d load equal %g by scaling non-existent fixed load', k, load(k));
0231             end
0232         elseif opt.which(1) == 'D'  %% 'DISPATCHABLE'
0233             if dispatchable ~= 0
0234                 scale(k) = (load(k) - fixed) / dispatchable;
0235             elseif load(k) == fixed
0236                 scale(k) = 1;
0237             else
0238                 error('scale_load: impossible to make zone %d load equal %g by scaling non-existent dispatchable load', k, load(k));
0239             end
0240         end
0241     end
0242 end
0243 
0244 %%-----  do the scaling  -----
0245 %% fixed loads
0246 if opt.which(1) ~= 'D'      %% includes 'FIXED', not 'DISPATCHABLE' only
0247     for k = 1:length(scale)
0248         idx = find( load_zone == k );
0249         bus(idx, PD) = bus(idx, PD) * scale(k);
0250         if strcmp(opt.pq, 'PQ')
0251             bus(idx, QD) = bus(idx, QD) * scale(k);
0252         end
0253     end
0254 end
0255 
0256 %% dispatchable loads
0257 if opt.which(1) ~= 'F'      %% includes 'DISPATCHABLE', not 'FIXED' only
0258     for k = 1:length(scale)
0259         idx = find( load_zone == k );
0260         [junk, i, junk2] = intersect(e2i(gen(ld, GEN_BUS)), idx);
0261         ig = ld(i);
0262 
0263         gen(ig, [PG PMIN]) = gen(ig, [PG PMIN]) * scale(k);
0264         if ~isempty(gencost)
0265             gencost(ig, :) = modcost(gencost(ig, :), scale(k), 'SCALE_F');
0266             gencost(ig, :) = modcost(gencost(ig, :), scale(k), 'SCALE_X');
0267         end
0268         if strcmp(opt.pq, 'PQ')
0269             gen(ig, [QG QMIN QMAX]) = gen(ig, [QG QMIN QMAX]) * scale(k);
0270             if ~isempty(gencost)
0271                 [pcost, qcost] = pqcost(gencost, ng);
0272                 if ~isempty(qcost)
0273                     qcost(ig, :) = modcost(qcost(ig, :), scale(k), 'SCALE_F');
0274                     qcost(ig, :) = modcost(qcost(ig, :), scale(k), 'SCALE_X');
0275                     gencost = [pcost; qcost];
0276                 end
0277             end
0278         end
0279     end
0280 end

Generated on Mon 26-Jan-2015 15:21:31 by m2html © 2005