Home > matpower5.1 > 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 %   Copyright (c) 2004-2015 by Power System Engineering Research Center (PSERC)
0085 %   by Ray Zimmerman, PSERC Cornell
0086 %
0087 %   $Id: scale_load.m 2644 2015-03-11 19:34:22Z ray $
0088 %
0089 %   This file is part of MATPOWER.
0090 %   Covered by the 3-clause BSD License (see LICENSE file for details).
0091 %   See http://www.pserc.cornell.edu/matpower/ for more info.
0092 
0093 %% define constants
0094 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
0095     VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
0096 %% purposely being backward compatible with older MATPOWER
0097 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, ...
0098     PMAX, PMIN, MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN] = idx_gen;
0099 
0100 nb = size(bus, 1);          %% number of buses
0101 
0102 %%-----  process inputs  -----
0103 if nargin < 6
0104     gencost = [];
0105     if nargin < 5
0106         opt = struct;
0107         if nargin < 4
0108             load_zone = [];
0109             if nargin < 3
0110                 gen = [];
0111             end
0112         end
0113     end
0114 end
0115 
0116 %% fill out and check opt
0117 if isempty(gen)
0118     opt.which = 'FIXED';
0119 end
0120 if ~isfield(opt, 'pq')
0121     opt.pq = 'PQ';          %% 'PQ' or 'P'
0122 end
0123 if ~isfield(opt, 'which')
0124     opt.which = 'BOTH';     %% 'FIXED', 'DISPATCHABLE' or 'BOTH'
0125 end
0126 if ~isfield(opt, 'scale')
0127     opt.scale = 'FACTOR';   %% 'FACTOR' or 'QUANTITY'
0128 end
0129 if ~strcmp(opt.pq, 'P') && ~strcmp(opt.pq, 'PQ')
0130     error('scale_load: opt.pq must equal ''PQ'' or ''P''');
0131 end
0132 if opt.which(1) ~= 'F' && opt.which(1) ~= 'D' && opt.which(1) ~= 'B'
0133     error('scale_load: opt.which should be ''FIXED'', ''DISPATCHABLE'' or ''BOTH''');
0134 end
0135 if opt.scale(1) ~= 'F' && opt.scale(1) ~= 'Q'
0136     error('scale_load: opt.scale should be ''FACTOR'' or ''QUANTITY''');
0137 end
0138 if isempty(gen) && opt.which(1) ~= 'F'
0139     error('scale_load: need gen matrix to scale dispatchable loads');
0140 end
0141 if nargout < 3 && ~isempty(gencost)
0142     error('scale_load: missing gencost as output argument');
0143 end
0144 if nargout > 2 && isempty(gencost)
0145     error('scale_load: missing gencost as input argument');
0146 end
0147 
0148 %% create dispatchable load connection matrix
0149 if ~isempty(gen)
0150     ng = size(gen, 1);
0151     is_ld = isload(gen) & gen(:, GEN_STATUS) > 0;
0152     ld = find(is_ld);
0153 
0154     %% create map of external bus numbers to bus indices
0155     i2e = bus(:, BUS_I);
0156     e2i = sparse(max(i2e), 1);
0157     e2i(i2e) = (1:nb)';
0158 
0159     Cld = sparse(e2i(gen(:, GEN_BUS)), (1:ng)', is_ld, nb, ng);
0160 else
0161     ng = [];
0162     ld = [];
0163 end
0164 
0165 if isempty(load_zone)
0166     if length(load) == 1        %% make a single zone of all load buses
0167         load_zone = zeros(nb, 1);                           %% initialize
0168         load_zone(bus(:, PD) ~= 0 | bus(:, QD) ~= 0) = 1;   %% FIXED loads
0169         if ~isempty(gen)
0170             load_zone(e2i(gen(ld, GEN_BUS))) = 1;   %% DISPATCHABLE loads
0171         end
0172     else                        %% use areas defined in bus data as zones
0173         load_zone = bus(:, BUS_AREA);
0174     end
0175 end
0176 
0177 %% check load_zone to make sure it's consistent with size of load vector
0178 if max(load_zone) > length(load)
0179     error('scale_load: load vector must have a value for each load zone specified');
0180 end
0181 
0182 %%-----  compute scale factors for each zone  -----
0183 scale = load;
0184 Pdd = zeros(nb, 1);     %% dispatchable P at each bus
0185 if opt.scale(1) == 'Q'  %% 'QUANTITY'
0186     %% find load capacity from dispatchable loads
0187     if ~isempty(gen)
0188         Pdd = -Cld * gen(:, PMIN);
0189     end
0190 
0191     %% compute scale factors
0192     for k = 1:length(load)
0193         idx = find( load_zone == k );
0194         fixed = sum(bus(idx, PD));
0195         dispatchable = sum(Pdd(idx));
0196         total = fixed + dispatchable;
0197         if opt.which(1) == 'B'      %% 'BOTH'
0198             if total ~= 0
0199                 scale(k) = load(k) / total;
0200             elseif load(k) == total
0201                 scale(k) = 1;
0202             else
0203                 error('scale_load: impossible to make zone %d load equal %g by scaling non-existent loads', k, load(k));
0204             end
0205         elseif opt.which(1) == 'F'  %% 'FIXED'
0206             if fixed ~= 0
0207                 scale(k) = (load(k) - dispatchable) / fixed;
0208             elseif load(k) == dispatchable
0209                 scale(k) = 1;
0210             else
0211                 error('scale_load: impossible to make zone %d load equal %g by scaling non-existent fixed load', k, load(k));
0212             end
0213         elseif opt.which(1) == 'D'  %% 'DISPATCHABLE'
0214             if dispatchable ~= 0
0215                 scale(k) = (load(k) - fixed) / dispatchable;
0216             elseif load(k) == fixed
0217                 scale(k) = 1;
0218             else
0219                 error('scale_load: impossible to make zone %d load equal %g by scaling non-existent dispatchable load', k, load(k));
0220             end
0221         end
0222     end
0223 end
0224 
0225 %%-----  do the scaling  -----
0226 %% fixed loads
0227 if opt.which(1) ~= 'D'      %% includes 'FIXED', not 'DISPATCHABLE' only
0228     for k = 1:length(scale)
0229         idx = find( load_zone == k );
0230         bus(idx, PD) = bus(idx, PD) * scale(k);
0231         if strcmp(opt.pq, 'PQ')
0232             bus(idx, QD) = bus(idx, QD) * scale(k);
0233         end
0234     end
0235 end
0236 
0237 %% dispatchable loads
0238 if opt.which(1) ~= 'F'      %% includes 'DISPATCHABLE', not 'FIXED' only
0239     for k = 1:length(scale)
0240         idx = find( load_zone == k );
0241         [junk, i, junk2] = intersect(e2i(gen(ld, GEN_BUS)), idx);
0242         ig = ld(i);
0243 
0244         gen(ig, [PG PMIN]) = gen(ig, [PG PMIN]) * scale(k);
0245         if ~isempty(gencost)
0246             gencost(ig, :) = modcost(gencost(ig, :), scale(k), 'SCALE_F');
0247             gencost(ig, :) = modcost(gencost(ig, :), scale(k), 'SCALE_X');
0248         end
0249         if strcmp(opt.pq, 'PQ')
0250             gen(ig, [QG QMIN QMAX]) = gen(ig, [QG QMIN QMAX]) * scale(k);
0251             if ~isempty(gencost)
0252                 [pcost, qcost] = pqcost(gencost, ng);
0253                 if ~isempty(qcost)
0254                     qcost(ig, :) = modcost(qcost(ig, :), scale(k), 'SCALE_F');
0255                     qcost(ig, :) = modcost(qcost(ig, :), scale(k), 'SCALE_X');
0256                     gencost = [pcost; qcost];
0257                 end
0258             end
0259         end
0260     end
0261 end

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