Home > matpower4.0 > ext2int.m

ext2int

PURPOSE ^

EXT2INT Converts external to internal indexing.

SYNOPSIS ^

function [i2e, bus, gen, branch, areas] = ext2int(bus, gen, branch, areas)

DESCRIPTION ^

EXT2INT   Converts external to internal indexing.

   This function performs several different tasks, depending on the
   arguments passed.

   1.  [I2E, BUS, GEN, BRANCH, AREAS] = EXT2INT(BUS, GEN, BRANCH, AREAS)
       [I2E, BUS, GEN, BRANCH] = EXT2INT(BUS, GEN, BRANCH)

   If the first argument is a matrix, it simply converts from (possibly
   non-consecutive) external bus numbers to consecutive internal bus
   numbers which start at 1. Changes are made to BUS, GEN, BRANCH and
   optionally AREAS matrices, which are returned along with a vector of
   indices I2E that can be passed to INT2EXT to perform the reverse
   conversion, where EXTERNAL_BUS_NUMBER = I2E(INTERNAL_BUS_NUMBER)

   Examples:
       [i2e, bus, gen, branch, areas] = ext2int(bus, gen, branch, areas);
       [i2e, bus, gen, branch] = ext2int(bus, gen, branch);

   2.  MPC = EXT2INT(MPC)

   If the input is a single MATPOWER case struct, then all isolated
   buses, off-line generators and branches are removed along with any
   generators, branches or areas connected to isolated buses. Then the
   buses are renumbered consecutively, beginning at 1, and the
   generators are sorted by increasing bus number. All of the related
   indexing information and the original data matrices are stored in
   an 'order' field in the struct to be used by INT2EXT to perform
   the reverse conversions. If the case is already using internal
   numbering it is returned unchanged.

   Example:
       mpc = ext2int(mpc);

   3.  VAL = EXT2INT(MPC, VAL, ORDERING)
       VAL = EXT2INT(MPC, VAL, ORDERING, DIM)
       MPC = EXT2INT(MPC, FIELD, ORDERING)
       MPC = EXT2INT(MPC, FIELD, ORDERING, DIM)

   When given a case struct that has already been converted to
   internal indexing, this function can be used to convert other data
   structures as well by passing in 2 or 3 extra parameters in
   addition to the case struct. If the value passed in the 2nd
   argument is a column vector, it will be converted according to the
   ORDERING specified by the 3rd argument (described below). If VAL
   is an n-dimensional matrix, then the optional 4th argument (DIM,
   default = 1) can be used to specify which dimension to reorder.
   The return value in this case is the value passed in, converted
   to internal indexing.

   If the 2nd argument is a string or cell array of strings, it
   specifies a field in the case struct whose value should be
   converted as described above. In this case, the converted value
   is stored back in the specified field, the original value is
   saved for later use and the updated case struct is returned.
   If FIELD is a cell array of strings, they specify nested fields.

   The 3rd argument, ORDERING, is used to indicate whether the data
   corresponds to bus-, gen- or branch-ordered data. It can be one
   of the following three strings: 'bus', 'gen' or 'branch'. For
   data structures with multiple blocks of data, ordered by bus,
   gen or branch, they can be converted with a single call by
   specifying ORDERING as a cell array of strings.

   Any extra elements, rows, columns, etc. beyond those indicated
   in ORDERING, are not disturbed.

   Examples:
       A_int = ext2int(mpc, A_ext, {'bus','bus','gen','gen'}, 2);

       Converts an A matrix for user-supplied OPF constraints from
       external to internal ordering, where the columns of the A
       matrix correspond to bus voltage angles, then voltage
       magnitudes, then generator real power injections and finally
       generator reactive power injections.

       gencost_int = ext2int(mpc, gencost_ext, {'gen','gen'}, 1);

       Converts a GENCOST matrix that has both real and reactive power
       costs (in rows 1--ng and ng+1--2*ng, respectively).

       mpc = ext2int(mpc, {'reserves', 'cost'}, 'gen');

       Reorders rows of mpc.reserves.cost to match internal generator
       ordering.

       mpc = ext2int(mpc, {'reserves', 'zones'}, 'gen', 2);

       Reorders columns of mpc.reserves.zones to match internal
       generator ordering.

   The 'order' field of MPC used to store the indexing information
   needed for subsequent internal to external conversion is structured
   as:

       order
           state       'i' | 'e'
           ext | int
               areas
               bus
               branch
               gen
               gencost
               A
               N
           bus
               e2i
               i2e
               status
                   on
                   off
           gen
               e2i
               i2e
               status
                   on
                   off
           branch
               status
                   on
                   off
           areas
               status
                   on
                   off

   See also INT2EXT.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function [i2e, bus, gen, branch, areas] = ext2int(bus, gen, branch, areas)
0002 %EXT2INT   Converts external to internal indexing.
0003 %
0004 %   This function performs several different tasks, depending on the
0005 %   arguments passed.
0006 %
0007 %   1.  [I2E, BUS, GEN, BRANCH, AREAS] = EXT2INT(BUS, GEN, BRANCH, AREAS)
0008 %       [I2E, BUS, GEN, BRANCH] = EXT2INT(BUS, GEN, BRANCH)
0009 %
0010 %   If the first argument is a matrix, it simply converts from (possibly
0011 %   non-consecutive) external bus numbers to consecutive internal bus
0012 %   numbers which start at 1. Changes are made to BUS, GEN, BRANCH and
0013 %   optionally AREAS matrices, which are returned along with a vector of
0014 %   indices I2E that can be passed to INT2EXT to perform the reverse
0015 %   conversion, where EXTERNAL_BUS_NUMBER = I2E(INTERNAL_BUS_NUMBER)
0016 %
0017 %   Examples:
0018 %       [i2e, bus, gen, branch, areas] = ext2int(bus, gen, branch, areas);
0019 %       [i2e, bus, gen, branch] = ext2int(bus, gen, branch);
0020 %
0021 %   2.  MPC = EXT2INT(MPC)
0022 %
0023 %   If the input is a single MATPOWER case struct, then all isolated
0024 %   buses, off-line generators and branches are removed along with any
0025 %   generators, branches or areas connected to isolated buses. Then the
0026 %   buses are renumbered consecutively, beginning at 1, and the
0027 %   generators are sorted by increasing bus number. All of the related
0028 %   indexing information and the original data matrices are stored in
0029 %   an 'order' field in the struct to be used by INT2EXT to perform
0030 %   the reverse conversions. If the case is already using internal
0031 %   numbering it is returned unchanged.
0032 %
0033 %   Example:
0034 %       mpc = ext2int(mpc);
0035 %
0036 %   3.  VAL = EXT2INT(MPC, VAL, ORDERING)
0037 %       VAL = EXT2INT(MPC, VAL, ORDERING, DIM)
0038 %       MPC = EXT2INT(MPC, FIELD, ORDERING)
0039 %       MPC = EXT2INT(MPC, FIELD, ORDERING, DIM)
0040 %
0041 %   When given a case struct that has already been converted to
0042 %   internal indexing, this function can be used to convert other data
0043 %   structures as well by passing in 2 or 3 extra parameters in
0044 %   addition to the case struct. If the value passed in the 2nd
0045 %   argument is a column vector, it will be converted according to the
0046 %   ORDERING specified by the 3rd argument (described below). If VAL
0047 %   is an n-dimensional matrix, then the optional 4th argument (DIM,
0048 %   default = 1) can be used to specify which dimension to reorder.
0049 %   The return value in this case is the value passed in, converted
0050 %   to internal indexing.
0051 %
0052 %   If the 2nd argument is a string or cell array of strings, it
0053 %   specifies a field in the case struct whose value should be
0054 %   converted as described above. In this case, the converted value
0055 %   is stored back in the specified field, the original value is
0056 %   saved for later use and the updated case struct is returned.
0057 %   If FIELD is a cell array of strings, they specify nested fields.
0058 %
0059 %   The 3rd argument, ORDERING, is used to indicate whether the data
0060 %   corresponds to bus-, gen- or branch-ordered data. It can be one
0061 %   of the following three strings: 'bus', 'gen' or 'branch'. For
0062 %   data structures with multiple blocks of data, ordered by bus,
0063 %   gen or branch, they can be converted with a single call by
0064 %   specifying ORDERING as a cell array of strings.
0065 %
0066 %   Any extra elements, rows, columns, etc. beyond those indicated
0067 %   in ORDERING, are not disturbed.
0068 %
0069 %   Examples:
0070 %       A_int = ext2int(mpc, A_ext, {'bus','bus','gen','gen'}, 2);
0071 %
0072 %       Converts an A matrix for user-supplied OPF constraints from
0073 %       external to internal ordering, where the columns of the A
0074 %       matrix correspond to bus voltage angles, then voltage
0075 %       magnitudes, then generator real power injections and finally
0076 %       generator reactive power injections.
0077 %
0078 %       gencost_int = ext2int(mpc, gencost_ext, {'gen','gen'}, 1);
0079 %
0080 %       Converts a GENCOST matrix that has both real and reactive power
0081 %       costs (in rows 1--ng and ng+1--2*ng, respectively).
0082 %
0083 %       mpc = ext2int(mpc, {'reserves', 'cost'}, 'gen');
0084 %
0085 %       Reorders rows of mpc.reserves.cost to match internal generator
0086 %       ordering.
0087 %
0088 %       mpc = ext2int(mpc, {'reserves', 'zones'}, 'gen', 2);
0089 %
0090 %       Reorders columns of mpc.reserves.zones to match internal
0091 %       generator ordering.
0092 %
0093 %   The 'order' field of MPC used to store the indexing information
0094 %   needed for subsequent internal to external conversion is structured
0095 %   as:
0096 %
0097 %       order
0098 %           state       'i' | 'e'
0099 %           ext | int
0100 %               areas
0101 %               bus
0102 %               branch
0103 %               gen
0104 %               gencost
0105 %               A
0106 %               N
0107 %           bus
0108 %               e2i
0109 %               i2e
0110 %               status
0111 %                   on
0112 %                   off
0113 %           gen
0114 %               e2i
0115 %               i2e
0116 %               status
0117 %                   on
0118 %                   off
0119 %           branch
0120 %               status
0121 %                   on
0122 %                   off
0123 %           areas
0124 %               status
0125 %                   on
0126 %                   off
0127 %
0128 %   See also INT2EXT.
0129 
0130 %   MATPOWER
0131 %   $Id: ext2int.m,v 1.19 2010/04/26 19:45:25 ray Exp $
0132 %   by Ray Zimmerman, PSERC Cornell
0133 %   Copyright (c) 1996-2010 by Power System Engineering Research Center (PSERC)
0134 %
0135 %   This file is part of MATPOWER.
0136 %   See http://www.pserc.cornell.edu/matpower/ for more info.
0137 %
0138 %   MATPOWER is free software: you can redistribute it and/or modify
0139 %   it under the terms of the GNU General Public License as published
0140 %   by the Free Software Foundation, either version 3 of the License,
0141 %   or (at your option) any later version.
0142 %
0143 %   MATPOWER is distributed in the hope that it will be useful,
0144 %   but WITHOUT ANY WARRANTY; without even the implied warranty of
0145 %   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0146 %   GNU General Public License for more details.
0147 %
0148 %   You should have received a copy of the GNU General Public License
0149 %   along with MATPOWER. If not, see <http://www.gnu.org/licenses/>.
0150 %
0151 %   Additional permission under GNU GPL version 3 section 7
0152 %
0153 %   If you modify MATPOWER, or any covered work, to interface with
0154 %   other modules (such as MATLAB code and MEX-files) available in a
0155 %   MATLAB(R) or comparable environment containing parts covered
0156 %   under other licensing terms, the licensors of MATPOWER grant
0157 %   you additional permission to convey the resulting work.
0158 
0159 if isstruct(bus)
0160     mpc = bus;
0161     if nargin == 1
0162         first = ~isfield(mpc, 'order');
0163         if first || mpc.order.state == 'e'
0164             %% define names for columns to data matrices
0165             [PQ, PV, REF, NONE, BUS_I, BUS_TYPE] = idx_bus;
0166             [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS] = idx_gen;
0167             [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0168                 TAP, SHIFT, BR_STATUS] = idx_brch;
0169             [AREA_I, PRICE_REF_BUS] = idx_area;
0170 
0171             %% initialize order
0172             if first
0173                 status = struct('on',   [], ...
0174                                 'off',  []  );
0175                 tmp = struct( ...
0176                         'e2i',      [], ...
0177                         'i2e',      [], ...
0178                         'status',   status ...
0179                     );
0180                 o = struct( ...
0181                         'ext',      struct( ...
0182                                 'bus',      [], ...
0183                                 'branch',   [], ...
0184                                 'gen',      [] ...
0185                             ), ...
0186                         'bus',      tmp, ...
0187                         'gen',      tmp, ...
0188                         'branch',   struct('status', status) ...
0189                     );
0190             else
0191                 o = mpc.order;
0192             end
0193 
0194             %% sizes
0195             nb = size(mpc.bus, 1);
0196             ng = size(mpc.gen, 1);
0197             ng0 = ng;
0198             if isfield(mpc, 'A') && size(mpc.A, 2) < 2*nb + 2*ng
0199                 dc = 1;
0200             elseif isfield(mpc, 'N') && size(mpc.N, 2) < 2*nb + 2*ng
0201                 dc = 1;
0202             else
0203                 dc = 0;
0204             end
0205 
0206             %% save data matrices with external ordering
0207             o.ext.bus    = mpc.bus;
0208             o.ext.branch = mpc.branch;
0209             o.ext.gen    = mpc.gen;
0210             if isfield(mpc, 'areas')
0211                 if isempty(mpc.areas)           %% if areas field is empty
0212                     mpc = rmfield(mpc, 'areas');    %% delete it (so it gets ignored)
0213                 else                            %% otherwise
0214                     o.ext.areas = mpc.areas;        %% save it
0215                 end
0216             end
0217 
0218             %% check that all buses have a valid BUS_TYPE
0219             bt = mpc.bus(:, BUS_TYPE);
0220             err = find(~(bt == PQ | bt == PV | bt == REF | bt == NONE));
0221             if ~isempty(err)
0222                 error('ext2int: bus %d has an invalid BUS_TYPE', err);
0223             end
0224 
0225             %% determine which buses, branches, gens are connected & in-service
0226             n2i = sparse(mpc.bus(:, BUS_I), ones(nb, 1), 1:nb, max(mpc.bus(:, BUS_I)), 1);
0227             bs = (bt ~= NONE);                      %% bus status
0228             o.bus.status.on     = find(  bs );      %% connected
0229             o.bus.status.off    = find( ~bs );      %% isolated
0230             gs = ( mpc.gen(:, GEN_STATUS) > 0 & ... %% gen status
0231                     bs(n2i(mpc.gen(:, GEN_BUS))) );
0232             o.gen.status.on     = find(  gs );      %% on and connected
0233             o.gen.status.off    = find( ~gs );      %% off or isolated
0234             brs = ( mpc.branch(:, BR_STATUS) & ...  %% branch status
0235                     bs(n2i(mpc.branch(:, F_BUS))) & ...
0236                     bs(n2i(mpc.branch(:, T_BUS))) );
0237             o.branch.status.on  = find(  brs );     %% on and connected
0238             o.branch.status.off = find( ~brs );
0239             if isfield(mpc, 'areas')
0240                 as = bs(n2i(mpc.areas(:, PRICE_REF_BUS)));
0241                 o.areas.status.on   = find(  as );
0242                 o.areas.status.off  = find( ~as );
0243             end
0244 
0245             %% delete stuff that is "out"
0246             if ~isempty(o.bus.status.off)
0247                 mpc.bus(o.bus.status.off, :) = [];
0248             end
0249             if ~isempty(o.branch.status.off)
0250                 mpc.branch(o.branch.status.off, :) = [];
0251             end
0252             if ~isempty(o.gen.status.off)
0253                 mpc.gen(o.gen.status.off, :) = [];
0254             end
0255             if isfield(mpc, 'areas') && ~isempty(o.areas.status.off)
0256                 mpc.areas(o.areas.status.off, :) = [];
0257             end
0258 
0259             %% update size
0260             nb = size(mpc.bus, 1);
0261 
0262             %% apply consecutive bus numbering
0263             o.bus.i2e = mpc.bus(:, BUS_I);
0264             o.bus.e2i = sparse(max(o.bus.i2e), 1);
0265             o.bus.e2i(o.bus.i2e) = (1:nb)';
0266             mpc.bus(:, BUS_I)       = o.bus.e2i( mpc.bus(:, BUS_I)      );
0267             mpc.gen(:, GEN_BUS)     = o.bus.e2i( mpc.gen(:, GEN_BUS)    );
0268             mpc.branch(:, F_BUS)    = o.bus.e2i( mpc.branch(:, F_BUS)   );
0269             mpc.branch(:, T_BUS)    = o.bus.e2i( mpc.branch(:, T_BUS)   );
0270             if isfield(mpc, 'areas')
0271                 mpc.areas(:, PRICE_REF_BUS) = o.bus.e2i( mpc.areas(:, PRICE_REF_BUS)  );
0272             end
0273 
0274             %% reorder gens in order of increasing bus number
0275             [tmp, o.gen.e2i] = sort(mpc.gen(:, GEN_BUS));
0276             [tmp, o.gen.i2e] = sort(o.gen.e2i);
0277             mpc.gen = mpc.gen(o.gen.e2i, :);
0278 
0279             if isfield(o, 'int')
0280                 o = rmfield(o, 'int');
0281             end
0282             o.state = 'i';
0283             mpc.order = o;
0284 
0285             %% update gencost, A and N
0286             if isfield(mpc, 'gencost')
0287                 ordering = {'gen'};         %% Pg cost only
0288                 if size(mpc.gencost, 1) == 2*ng0
0289                     ordering{2} = 'gen';    %% include Qg cost
0290                 end
0291                 mpc = ext2int(mpc, 'gencost', ordering);
0292             end
0293             if isfield(mpc, 'A') || isfield(mpc, 'N')
0294                 if dc
0295                     ordering = {'bus', 'gen'};
0296                 else
0297                     ordering = {'bus', 'bus', 'gen', 'gen'};
0298                 end
0299             end
0300             if isfield(mpc, 'A')
0301                 mpc = ext2int(mpc, 'A', ordering, 2);
0302             end
0303             if isfield(mpc, 'N')
0304                 mpc = ext2int(mpc, 'N', ordering, 2);
0305             end
0306 
0307             %% execute userfcn callbacks for 'ext2int' stage
0308             if isfield(mpc, 'userfcn')
0309                 mpc = run_userfcn(mpc.userfcn, 'ext2int', mpc);
0310             end
0311         end
0312 
0313         i2e = mpc;
0314     else                    %% convert extra data
0315         ordering = branch;              %% rename argument
0316         if nargin < 4
0317             dim = 1;
0318         else
0319             dim = areas;                %% rename argument
0320         end
0321         if ischar(gen) || iscell(gen)   %% field
0322             field = gen;                %% rename argument
0323             if ischar(field)
0324                 mpc.order.ext.(field) = mpc.(field);
0325                 mpc.(field) = ext2int(mpc, mpc.(field), ordering, dim);
0326             else
0327                 for k = 1:length(field)
0328                     s(k).type = '.';
0329                     s(k).subs = field{k};
0330                 end
0331                 mpc.order.ext = subsasgn(mpc.order.ext, s, subsref(mpc, s));
0332                 mpc = subsasgn(mpc, s, ...
0333                     ext2int(mpc, subsref(mpc, s), ordering, dim));
0334             end
0335             i2e = mpc;
0336         else                            %% value
0337             val = gen;                  %% rename argument
0338             o = mpc.order;
0339             if ischar(ordering)         %% single set
0340                 if strcmp(ordering, 'gen')
0341                     idx = o.(ordering).status.on(o.(ordering).e2i);
0342                 else
0343                     idx = o.(ordering).status.on;
0344                 end
0345                 i2e = get_reorder(val, idx, dim);
0346             else                            %% multiple sets
0347                 b = 0;  %% base
0348                 for k = 1:length(ordering)
0349                     n = size(o.ext.(ordering{k}), 1);
0350                     v = get_reorder(val, b+(1:n), dim);
0351                     new_v{k} = ext2int(mpc, v, ordering{k}, dim);
0352                     b = b + n;
0353                 end
0354                 n = size(val, dim);
0355                 if n > b                %% the rest
0356                     v = get_reorder(val, b+1:n, dim);
0357                     new_v{length(new_v)+1} = v;
0358                 end
0359                 i2e = cat(dim, new_v{:});
0360             end
0361         end
0362     end
0363 else            %% old form
0364     %% define names for columns to data matrices
0365     [PQ, PV, REF, NONE, BUS_I] = idx_bus;
0366     [GEN_BUS] = idx_gen;
0367     [F_BUS, T_BUS] = idx_brch;
0368     [AREA_I, PRICE_REF_BUS] = idx_area;
0369 
0370     %% create map of external bus numbers to bus indices
0371     i2e = bus(:, BUS_I);
0372     e2i = sparse(max(i2e), 1);
0373     e2i(i2e) = (1:size(bus, 1))';
0374 
0375     %% renumber buses consecutively
0376     bus(:, BUS_I)               = e2i( bus(:, BUS_I)            );
0377     gen(:, GEN_BUS)             = e2i( gen(:, GEN_BUS)          );
0378     branch(:, F_BUS)            = e2i( branch(:, F_BUS)         );
0379     branch(:, T_BUS)            = e2i( branch(:, T_BUS)         );
0380     if nargin > 3 && nargout > 4 && ~isempty(areas)
0381         areas(:, PRICE_REF_BUS) = e2i( areas(:, PRICE_REF_BUS)  );
0382     end
0383 end

Generated on Mon 26-Jan-2015 14:56:45 by m2html © 2005