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) If the input is a single MATPOWER case 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, and the generators are sorted by increasing bus number. 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. Example: mpc = ext2int(mpc); 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.
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 % 0026 % If the input is a single MATPOWER case struct, then all isolated 0027 % buses, off-line generators and branches are removed along with any 0028 % generators or branches connected to isolated buses. Then the 0029 % buses are renumbered consecutively, beginning at 1, and the 0030 % generators are sorted by increasing bus number. Any 'ext2int' 0031 % callback routines registered in the case are also invoked 0032 % automatically. All of the related indexing information and the 0033 % original data matrices are stored in an 'order' field in the struct 0034 % to be used by INT2EXT to perform the reverse conversions. If the 0035 % case is already using internal numbering it is returned unchanged. 0036 % 0037 % Example: 0038 % mpc = ext2int(mpc); 0039 % 0040 % The 'order' field of MPC used to store the indexing information 0041 % needed for subsequent internal to external conversion is structured 0042 % as: 0043 % 0044 % order 0045 % state 'i' | 'e' 0046 % ext | int 0047 % bus 0048 % branch 0049 % gen 0050 % gencost 0051 % A 0052 % N 0053 % bus 0054 % e2i 0055 % i2e 0056 % status 0057 % on 0058 % off 0059 % gen 0060 % e2i 0061 % i2e 0062 % status 0063 % on 0064 % off 0065 % branch 0066 % status 0067 % on 0068 % off 0069 % 0070 % See also INT2EXT, E2I_FIELD, E2I_DATA. 0071 0072 % MATPOWER 0073 % Copyright (c) 1996-2015 by Power System Engineering Research Center (PSERC) 0074 % by Ray Zimmerman, PSERC Cornell 0075 % 0076 % $Id: ext2int.m 2644 2015-03-11 19:34:22Z ray $ 0077 % 0078 % This file is part of MATPOWER. 0079 % Covered by the 3-clause BSD License (see LICENSE file for details). 0080 % See http://www.pserc.cornell.edu/matpower/ for more info. 0081 0082 if isstruct(bus) 0083 mpc = bus; 0084 if nargin == 1 0085 first = ~isfield(mpc, 'order'); 0086 if first || mpc.order.state == 'e' 0087 %% define names for columns to data matrices 0088 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE] = idx_bus; 0089 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS] = idx_gen; 0090 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ... 0091 TAP, SHIFT, BR_STATUS] = idx_brch; 0092 0093 %% initialize order 0094 if first 0095 status = struct('on', [], ... 0096 'off', [] ); 0097 tmp = struct( ... 0098 'e2i', [], ... 0099 'i2e', [], ... 0100 'status', status ... 0101 ); 0102 o = struct( ... 0103 'ext', struct( ... 0104 'bus', [], ... 0105 'branch', [], ... 0106 'gen', [] ... 0107 ), ... 0108 'bus', tmp, ... 0109 'gen', tmp, ... 0110 'branch', struct('status', status) ... 0111 ); 0112 else 0113 o = mpc.order; 0114 end 0115 0116 %% sizes 0117 nb = size(mpc.bus, 1); 0118 ng = size(mpc.gen, 1); 0119 ng0 = ng; 0120 if isfield(mpc, 'A') && size(mpc.A, 2) < 2*nb + 2*ng 0121 dc = 1; 0122 elseif isfield(mpc, 'N') && size(mpc.N, 2) < 2*nb + 2*ng 0123 dc = 1; 0124 else 0125 dc = 0; 0126 end 0127 0128 %% save data matrices with external ordering 0129 o.ext.bus = mpc.bus; 0130 o.ext.branch = mpc.branch; 0131 o.ext.gen = mpc.gen; 0132 0133 %% check that all buses have a valid BUS_TYPE 0134 bt = mpc.bus(:, BUS_TYPE); 0135 err = find(~(bt == PQ | bt == PV | bt == REF | bt == NONE)); 0136 if ~isempty(err) 0137 error('ext2int: bus %d has an invalid BUS_TYPE', err); 0138 end 0139 0140 %% determine which buses, branches, gens are connected & in-service 0141 n2i = sparse(mpc.bus(:, BUS_I), ones(nb, 1), 1:nb, max(mpc.bus(:, BUS_I)), 1); 0142 bs = (bt ~= NONE); %% bus status 0143 o.bus.status.on = find( bs ); %% connected 0144 o.bus.status.off = find( ~bs ); %% isolated 0145 gs = ( mpc.gen(:, GEN_STATUS) > 0 & ... %% gen status 0146 bs(n2i(mpc.gen(:, GEN_BUS))) ); 0147 o.gen.status.on = find( gs ); %% on and connected 0148 o.gen.status.off = find( ~gs ); %% off or isolated 0149 brs = ( mpc.branch(:, BR_STATUS) & ... %% branch status 0150 bs(n2i(mpc.branch(:, F_BUS))) & ... 0151 bs(n2i(mpc.branch(:, T_BUS))) ); 0152 o.branch.status.on = find( brs ); %% on and connected 0153 o.branch.status.off = find( ~brs ); 0154 0155 %% delete stuff that is "out" 0156 if ~isempty(o.bus.status.off) 0157 mpc.bus(o.bus.status.off, :) = []; 0158 end 0159 if ~isempty(o.branch.status.off) 0160 mpc.branch(o.branch.status.off, :) = []; 0161 end 0162 if ~isempty(o.gen.status.off) 0163 mpc.gen(o.gen.status.off, :) = []; 0164 end 0165 0166 %% update size 0167 nb = size(mpc.bus, 1); 0168 0169 %% apply consecutive bus numbering 0170 o.bus.i2e = mpc.bus(:, BUS_I); 0171 o.bus.e2i = sparse(max(o.bus.i2e), 1); 0172 o.bus.e2i(o.bus.i2e) = (1:nb)'; 0173 mpc.bus(:, BUS_I) = o.bus.e2i( mpc.bus(:, BUS_I) ); 0174 mpc.gen(:, GEN_BUS) = o.bus.e2i( mpc.gen(:, GEN_BUS) ); 0175 mpc.branch(:, F_BUS) = o.bus.e2i( mpc.branch(:, F_BUS) ); 0176 mpc.branch(:, T_BUS) = o.bus.e2i( mpc.branch(:, T_BUS) ); 0177 0178 %% reorder gens in order of increasing bus number 0179 [tmp, o.gen.e2i] = sort(mpc.gen(:, GEN_BUS)); 0180 [tmp, o.gen.i2e] = sort(o.gen.e2i); 0181 mpc.gen = mpc.gen(o.gen.e2i, :); 0182 0183 if isfield(o, 'int') 0184 o = rmfield(o, 'int'); 0185 end 0186 o.state = 'i'; 0187 mpc.order = o; 0188 0189 %% update gencost, A and N 0190 if isfield(mpc, 'gencost') 0191 ordering = {'gen'}; %% Pg cost only 0192 if size(mpc.gencost, 1) == 2*ng0 0193 ordering{2} = 'gen'; %% include Qg cost 0194 end 0195 mpc = e2i_field(mpc, 'gencost', ordering); 0196 end 0197 if isfield(mpc, 'A') || isfield(mpc, 'N') 0198 if dc 0199 ordering = {'bus', 'gen'}; 0200 else 0201 ordering = {'bus', 'bus', 'gen', 'gen'}; 0202 end 0203 end 0204 if isfield(mpc, 'A') 0205 mpc = e2i_field(mpc, 'A', ordering, 2); 0206 end 0207 if isfield(mpc, 'N') 0208 mpc = e2i_field(mpc, 'N', ordering, 2); 0209 end 0210 0211 %% execute userfcn callbacks for 'ext2int' stage 0212 if isfield(mpc, 'userfcn') 0213 mpc = run_userfcn(mpc.userfcn, 'ext2int', mpc); 0214 end 0215 end 0216 0217 i2e = mpc; 0218 else %% convert extra data 0219 ordering = branch; %% rename argument 0220 if nargin < 4 0221 dim = 1; 0222 else 0223 dim = areas; %% rename argument 0224 end 0225 if ischar(gen) || iscell(gen) %% field 0226 warning('Calls of the form MPC = EXT2INT(MPC, ''FIELD_NAME'', ...) have been deprecated. Please replace EXT2INT with E2I_FIELD.'); 0227 i2e = e2i_field(mpc, gen, branch, dim); 0228 else %% value 0229 warning('Calls of the form VAL = EXT2INT(MPC, VAL, ...) have been deprecated. Please replace EXT2INT with E2I_DATA.'); 0230 i2e = e2i_data(mpc, gen, branch, dim); 0231 end 0232 end 0233 else %% old form 0234 %% define names for columns to data matrices 0235 [PQ, PV, REF, NONE, BUS_I] = idx_bus; 0236 [GEN_BUS] = idx_gen; 0237 [F_BUS, T_BUS] = idx_brch; 0238 0239 %% create map of external bus numbers to bus indices 0240 i2e = bus(:, BUS_I); 0241 e2i = sparse(max(i2e), 1); 0242 e2i(i2e) = (1:size(bus, 1))'; 0243 0244 %% renumber buses consecutively 0245 bus(:, BUS_I) = e2i( bus(:, BUS_I) ); 0246 gen(:, GEN_BUS) = e2i( gen(:, GEN_BUS) ); 0247 branch(:, F_BUS) = e2i( branch(:, F_BUS) ); 0248 branch(:, T_BUS) = e2i( branch(:, T_BUS) ); 0249 end