Home > matpower7.1 > lib > 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 has two forms, (1) the old form that operates on
   and returns individual matrices and (2) the new form that operates
   on and returns an entire MATPOWER case struct.

   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 and BRANCH,
   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).
   AREAS is completely ignored and is only included here for backward
   compatibility of the API.

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

   2.  MPC = EXT2INT(MPC)
       MPC = EXT2INT(MPC, MPOPT)

   If the input is a single MATPOWER case struct, followed optionally
   by a MATOWER options struct, then all isolated buses, off-line
   generators and branches are removed along with any generators or
   branches connected to isolated buses. Then the buses are renumbered
   consecutively, beginning at 1. Any 'ext2int' callback routines registered
   in the case are also invoked automatically. 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.

   Examples:
       mpc = ext2int(mpc);
       mpc = ext2int(mpc, mpopt);

   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
               bus
               branch
               gen
               gencost
               A
               N
           bus
               e2i
               i2e
               status
                   on
                   off
           gen
               e2i
               i2e
               status
                   on
                   off
           branch
               status
                   on
                   off

   See also INT2EXT, E2I_FIELD, E2I_DATA.

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 has two forms, (1) the old form that operates on
0005 %   and returns individual matrices and (2) the new form that operates
0006 %   on and returns an entire MATPOWER case struct.
0007 %
0008 %   1.  [I2E, BUS, GEN, BRANCH, AREAS] = EXT2INT(BUS, GEN, BRANCH, AREAS)
0009 %       [I2E, BUS, GEN, BRANCH] = EXT2INT(BUS, GEN, BRANCH)
0010 %
0011 %   If the first argument is a matrix, it simply converts from (possibly
0012 %   non-consecutive) external bus numbers to consecutive internal bus
0013 %   numbers which start at 1. Changes are made to BUS, GEN and BRANCH,
0014 %   which are returned along with a vector of indices I2E that can be
0015 %   passed to INT2EXT to perform the reverse conversion, where
0016 %   EXTERNAL_BUS_NUMBER = I2E(INTERNAL_BUS_NUMBER).
0017 %   AREAS is completely ignored and is only included here for backward
0018 %   compatibility of the API.
0019 %
0020 %   Examples:
0021 %       [i2e, bus, gen, branch, areas] = ext2int(bus, gen, branch, areas);
0022 %       [i2e, bus, gen, branch] = ext2int(bus, gen, branch);
0023 %
0024 %   2.  MPC = EXT2INT(MPC)
0025 %       MPC = EXT2INT(MPC, MPOPT)
0026 %
0027 %   If the input is a single MATPOWER case struct, followed optionally
0028 %   by a MATOWER options struct, then all isolated buses, off-line
0029 %   generators and branches are removed along with any generators or
0030 %   branches connected to isolated buses. Then the buses are renumbered
0031 %   consecutively, beginning at 1. Any 'ext2int' callback routines registered
0032 %   in the case are also invoked automatically. All of the related indexing
0033 %   information and the original data matrices are stored in an 'order'
0034 %   field in the struct to be used by INT2EXT to perform the reverse
0035 %   conversions. If the case is already using internal numbering it is
0036 %   returned unchanged.
0037 %
0038 %   Examples:
0039 %       mpc = ext2int(mpc);
0040 %       mpc = ext2int(mpc, mpopt);
0041 %
0042 %   The 'order' field of MPC used to store the indexing information
0043 %   needed for subsequent internal to external conversion is structured
0044 %   as:
0045 %
0046 %       order
0047 %           state       'i' | 'e'
0048 %           ext | int
0049 %               bus
0050 %               branch
0051 %               gen
0052 %               gencost
0053 %               A
0054 %               N
0055 %           bus
0056 %               e2i
0057 %               i2e
0058 %               status
0059 %                   on
0060 %                   off
0061 %           gen
0062 %               e2i
0063 %               i2e
0064 %               status
0065 %                   on
0066 %                   off
0067 %           branch
0068 %               status
0069 %                   on
0070 %                   off
0071 %
0072 %   See also INT2EXT, E2I_FIELD, E2I_DATA.
0073 
0074 %   UNDOCUMENTED OPTION:
0075 %       MPC = EXT2INT(MPC, MPOPT, 1)
0076 %       Calling EXT2INT in the second form with a 3rd argument of 1 will
0077 %       cause it to sort the generators by increasing bus index as in
0078 %       MATPOWER v4 through v7.0b1.
0079 
0080 %   MATPOWER
0081 %   Copyright (c) 1996-2019, Power Systems Engineering Research Center (PSERC)
0082 %   by Ray Zimmerman, PSERC Cornell
0083 %
0084 %   This file is part of MATPOWER.
0085 %   Covered by the 3-clause BSD License (see LICENSE file for details).
0086 %   See https://matpower.org for more info.
0087 
0088 if isstruct(bus)
0089     mpc = bus;
0090     if nargin < 3 || isscalar(gen)
0091         first = ~isfield(mpc, 'order');
0092         if first || mpc.order.state == 'e'
0093             %% define names for columns to data matrices
0094             [PQ, PV, REF, NONE, BUS_I, BUS_TYPE] = idx_bus;
0095             [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS] = idx_gen;
0096             [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0097                 TAP, SHIFT, BR_STATUS] = idx_brch;
0098 
0099             %% initialize order
0100             if first
0101                 status = struct('on',   [], ...
0102                                 'off',  []  );
0103                 tmp = struct( ...
0104                         'e2i',      [], ...
0105                         'i2e',      [], ...
0106                         'status',   status ...
0107                     );
0108                 o = struct( ...
0109                         'ext',      struct( ...
0110                                 'bus',      [], ...
0111                                 'branch',   [], ...
0112                                 'gen',      [] ...
0113                             ), ...
0114                         'bus',      tmp, ...
0115                         'gen',      tmp, ...
0116                         'branch',   struct('status', status) ...
0117                     );
0118             else
0119                 o = mpc.order;
0120             end
0121 
0122             %% sizes
0123             nb = size(mpc.bus, 1);
0124             ng = size(mpc.gen, 1);
0125             nb0 = nb;
0126             ng0 = ng;
0127             if isfield(mpc, 'A') && size(mpc.A, 2) < 2*nb + 2*ng
0128                 dc = 1;
0129             elseif isfield(mpc, 'N') && size(mpc.N, 2) < 2*nb + 2*ng
0130                 dc = 1;
0131             else
0132                 dc = 0;
0133             end
0134             if nargin == 3
0135                 reorder_gens = gen;
0136             else
0137                 reorder_gens = 0;
0138             end
0139 
0140             %% save data matrices with external ordering
0141             o.ext.bus    = mpc.bus;
0142             o.ext.branch = mpc.branch;
0143             o.ext.gen    = mpc.gen;
0144 
0145             %% check that all buses have a valid BUS_TYPE
0146             bt = mpc.bus(:, BUS_TYPE);
0147             err = find(~(bt == PQ | bt == PV | bt == REF | bt == NONE));
0148             if ~isempty(err)
0149                 error('ext2int: bus %d has an invalid BUS_TYPE', err);
0150             end
0151 
0152             %% determine which buses, branches, gens are connected & in-service
0153             n2i = sparse(mpc.bus(:, BUS_I), ones(nb, 1), 1:nb, max(mpc.bus(:, BUS_I)), 1);
0154             bs = (bt ~= NONE);                      %% bus status
0155             o.bus.status.on     = find(  bs );      %% connected
0156             o.bus.status.off    = find( ~bs );      %% isolated
0157             gs = ( mpc.gen(:, GEN_STATUS) > 0 & ... %% gen status
0158                     bs(n2i(mpc.gen(:, GEN_BUS))) );
0159             o.gen.status.on     = find(  gs );      %% on and connected
0160             o.gen.status.off    = find( ~gs );      %% off or isolated
0161             brs = ( mpc.branch(:, BR_STATUS) & ...  %% branch status
0162                     bs(n2i(mpc.branch(:, F_BUS))) & ...
0163                     bs(n2i(mpc.branch(:, T_BUS))) );
0164             o.branch.status.on  = find(  brs );     %% on and connected
0165             o.branch.status.off = find( ~brs );
0166 
0167             %% delete stuff that is "out"
0168             if ~isempty(o.bus.status.off)
0169                 mpc.bus(o.bus.status.off, :) = [];
0170             end
0171             if ~isempty(o.branch.status.off)
0172                 mpc.branch(o.branch.status.off, :) = [];
0173             end
0174             if ~isempty(o.gen.status.off)
0175                 mpc.gen(o.gen.status.off, :) = [];
0176             end
0177 
0178             %% update sizes
0179             nb = size(mpc.bus, 1);
0180             ng = size(mpc.gen, 1);
0181 
0182             %% apply consecutive bus numbering
0183             o.bus.i2e = mpc.bus(:, BUS_I);
0184             o.bus.e2i = sparse(o.bus.i2e, 1, 1:nb);
0185             if nb
0186                 mpc.bus(:, BUS_I)       = o.bus.e2i( mpc.bus(:, BUS_I)      );
0187                 mpc.gen(:, GEN_BUS)     = o.bus.e2i( mpc.gen(:, GEN_BUS)    );
0188                 mpc.branch(:, F_BUS)    = o.bus.e2i( mpc.branch(:, F_BUS)   );
0189                 mpc.branch(:, T_BUS)    = o.bus.e2i( mpc.branch(:, T_BUS)   );
0190             end
0191 
0192             if reorder_gens
0193                 %% reorder gens in order of increasing bus number
0194                 [tmp, o.gen.i2e] = sort(mpc.gen(:, GEN_BUS));
0195                 [tmp, o.gen.e2i] = sort(o.gen.i2e);
0196                 mpc.gen = mpc.gen(o.gen.i2e, :);
0197             else
0198                 %% don't reorder gens in order of increasing bus number, but
0199                 %% keep the mappings in place for backward compatibility
0200                 o.gen.i2e = (1:ng)';
0201                 o.gen.e2i = o.gen.i2e;
0202             end
0203 
0204             if isfield(o, 'int')
0205                 o = rmfield(o, 'int');
0206             end
0207             o.state = 'i';
0208             mpc.order = o;
0209 
0210             %% update gencost, bus_name, gentype, genfuel, A and N
0211             if isfield(mpc, 'gencost')
0212                 ordering = {'gen'};         %% Pg cost only
0213                 if size(mpc.gencost, 1) == 2*ng0
0214                     ordering{2} = 'gen';    %% include Qg cost
0215                 end
0216                 mpc = e2i_field(mpc, 'gencost', ordering);
0217             end
0218             if isfield(mpc, 'bus_name')
0219                 mpc = e2i_field(mpc, 'bus_name', {'bus'});
0220             end
0221             if isfield(mpc, 'gentype')
0222                 mpc = e2i_field(mpc, 'gentype', {'gen'});
0223             end
0224             if isfield(mpc, 'genfuel')
0225                 mpc = e2i_field(mpc, 'genfuel', {'gen'});
0226             end
0227             if isfield(mpc, 'A') || isfield(mpc, 'N')
0228                 if dc
0229                     ordering = {'bus', 'gen'};
0230                 else
0231                     ordering = {'bus', 'bus', 'gen', 'gen'};
0232                 end
0233             end
0234             if isfield(mpc, 'A')
0235                 mpc = e2i_field(mpc, 'A', ordering, 2);
0236             end
0237             if isfield(mpc, 'N')
0238                 mpc = e2i_field(mpc, 'N', ordering, 2);
0239             end
0240 
0241             %% execute userfcn callbacks for 'ext2int' stage
0242             if isfield(mpc, 'userfcn')
0243                 if nargin < 2
0244                     mpopt = struct();
0245                 else
0246                     mpopt = gen;
0247                 end
0248                 mpc = run_userfcn(mpc.userfcn, 'ext2int', mpc, mpopt);
0249             end
0250         end
0251 
0252         i2e = mpc;
0253     else                    %% convert extra data (DEPRECATED)
0254         ordering = branch;              %% rename argument
0255         if nargin < 4
0256             dim = 1;
0257         else
0258             dim = areas;                %% rename argument
0259         end
0260         if ischar(gen) || iscell(gen)   %% field
0261             warning('Calls of the form MPC = EXT2INT(MPC, ''FIELD_NAME'', ...) have been deprecated. Please replace EXT2INT with E2I_FIELD.');
0262             i2e = e2i_field(mpc, gen, ordering, dim);
0263         else                            %% value
0264             warning('Calls of the form VAL = EXT2INT(MPC, VAL, ...) have been deprecated. Please replace EXT2INT with E2I_DATA.');
0265             i2e = e2i_data(mpc, gen, ordering, dim);
0266         end
0267     end
0268 else            %% old form
0269     %% define names for columns to data matrices
0270     [PQ, PV, REF, NONE, BUS_I] = idx_bus;
0271     [GEN_BUS] = idx_gen;
0272     [F_BUS, T_BUS] = idx_brch;
0273 
0274     %% create map of external bus numbers to bus indices
0275     i2e = bus(:, BUS_I);
0276     e2i = sparse(max(i2e), 1);
0277     e2i(i2e) = (1:size(bus, 1))';
0278 
0279     %% renumber buses consecutively
0280     bus(:, BUS_I)               = e2i( bus(:, BUS_I)            );
0281     gen(:, GEN_BUS)             = e2i( gen(:, GEN_BUS)          );
0282     branch(:, F_BUS)            = e2i( branch(:, F_BUS)         );
0283     branch(:, T_BUS)            = e2i( branch(:, T_BUS)         );
0284 end

Generated on Fri 09-Oct-2020 11:21:31 by m2html © 2005