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 % $Id: ext2int.m 2409 2014-10-22 20:59:54Z ray $ 0074 % by Ray Zimmerman, PSERC Cornell 0075 % Copyright (c) 1996-2011 by Power System Engineering Research Center (PSERC) 0076 % 0077 % This file is part of MATPOWER. 0078 % See http://www.pserc.cornell.edu/matpower/ for more info. 0079 % 0080 % MATPOWER is free software: you can redistribute it and/or modify 0081 % it under the terms of the GNU General Public License as published 0082 % by the Free Software Foundation, either version 3 of the License, 0083 % or (at your option) any later version. 0084 % 0085 % MATPOWER is distributed in the hope that it will be useful, 0086 % but WITHOUT ANY WARRANTY; without even the implied warranty of 0087 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0088 % GNU General Public License for more details. 0089 % 0090 % You should have received a copy of the GNU General Public License 0091 % along with MATPOWER. If not, see <http://www.gnu.org/licenses/>. 0092 % 0093 % Additional permission under GNU GPL version 3 section 7 0094 % 0095 % If you modify MATPOWER, or any covered work, to interface with 0096 % other modules (such as MATLAB code and MEX-files) available in a 0097 % MATLAB(R) or comparable environment containing parts covered 0098 % under other licensing terms, the licensors of MATPOWER grant 0099 % you additional permission to convey the resulting work. 0100 0101 if isstruct(bus) 0102 mpc = bus; 0103 if nargin == 1 0104 first = ~isfield(mpc, 'order'); 0105 if first || mpc.order.state == 'e' 0106 %% define names for columns to data matrices 0107 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE] = idx_bus; 0108 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS] = idx_gen; 0109 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ... 0110 TAP, SHIFT, BR_STATUS] = idx_brch; 0111 0112 %% initialize order 0113 if first 0114 status = struct('on', [], ... 0115 'off', [] ); 0116 tmp = struct( ... 0117 'e2i', [], ... 0118 'i2e', [], ... 0119 'status', status ... 0120 ); 0121 o = struct( ... 0122 'ext', struct( ... 0123 'bus', [], ... 0124 'branch', [], ... 0125 'gen', [] ... 0126 ), ... 0127 'bus', tmp, ... 0128 'gen', tmp, ... 0129 'branch', struct('status', status) ... 0130 ); 0131 else 0132 o = mpc.order; 0133 end 0134 0135 %% sizes 0136 nb = size(mpc.bus, 1); 0137 ng = size(mpc.gen, 1); 0138 ng0 = ng; 0139 if isfield(mpc, 'A') && size(mpc.A, 2) < 2*nb + 2*ng 0140 dc = 1; 0141 elseif isfield(mpc, 'N') && size(mpc.N, 2) < 2*nb + 2*ng 0142 dc = 1; 0143 else 0144 dc = 0; 0145 end 0146 0147 %% save data matrices with external ordering 0148 o.ext.bus = mpc.bus; 0149 o.ext.branch = mpc.branch; 0150 o.ext.gen = mpc.gen; 0151 0152 %% check that all buses have a valid BUS_TYPE 0153 bt = mpc.bus(:, BUS_TYPE); 0154 err = find(~(bt == PQ | bt == PV | bt == REF | bt == NONE)); 0155 if ~isempty(err) 0156 error('ext2int: bus %d has an invalid BUS_TYPE', err); 0157 end 0158 0159 %% determine which buses, branches, gens are connected & in-service 0160 n2i = sparse(mpc.bus(:, BUS_I), ones(nb, 1), 1:nb, max(mpc.bus(:, BUS_I)), 1); 0161 bs = (bt ~= NONE); %% bus status 0162 o.bus.status.on = find( bs ); %% connected 0163 o.bus.status.off = find( ~bs ); %% isolated 0164 gs = ( mpc.gen(:, GEN_STATUS) > 0 & ... %% gen status 0165 bs(n2i(mpc.gen(:, GEN_BUS))) ); 0166 o.gen.status.on = find( gs ); %% on and connected 0167 o.gen.status.off = find( ~gs ); %% off or isolated 0168 brs = ( mpc.branch(:, BR_STATUS) & ... %% branch status 0169 bs(n2i(mpc.branch(:, F_BUS))) & ... 0170 bs(n2i(mpc.branch(:, T_BUS))) ); 0171 o.branch.status.on = find( brs ); %% on and connected 0172 o.branch.status.off = find( ~brs ); 0173 0174 %% delete stuff that is "out" 0175 if ~isempty(o.bus.status.off) 0176 mpc.bus(o.bus.status.off, :) = []; 0177 end 0178 if ~isempty(o.branch.status.off) 0179 mpc.branch(o.branch.status.off, :) = []; 0180 end 0181 if ~isempty(o.gen.status.off) 0182 mpc.gen(o.gen.status.off, :) = []; 0183 end 0184 0185 %% update size 0186 nb = size(mpc.bus, 1); 0187 0188 %% apply consecutive bus numbering 0189 o.bus.i2e = mpc.bus(:, BUS_I); 0190 o.bus.e2i = sparse(max(o.bus.i2e), 1); 0191 o.bus.e2i(o.bus.i2e) = (1:nb)'; 0192 mpc.bus(:, BUS_I) = o.bus.e2i( mpc.bus(:, BUS_I) ); 0193 mpc.gen(:, GEN_BUS) = o.bus.e2i( mpc.gen(:, GEN_BUS) ); 0194 mpc.branch(:, F_BUS) = o.bus.e2i( mpc.branch(:, F_BUS) ); 0195 mpc.branch(:, T_BUS) = o.bus.e2i( mpc.branch(:, T_BUS) ); 0196 0197 %% reorder gens in order of increasing bus number 0198 [tmp, o.gen.e2i] = sort(mpc.gen(:, GEN_BUS)); 0199 [tmp, o.gen.i2e] = sort(o.gen.e2i); 0200 mpc.gen = mpc.gen(o.gen.e2i, :); 0201 0202 if isfield(o, 'int') 0203 o = rmfield(o, 'int'); 0204 end 0205 o.state = 'i'; 0206 mpc.order = o; 0207 0208 %% update gencost, A and N 0209 if isfield(mpc, 'gencost') 0210 ordering = {'gen'}; %% Pg cost only 0211 if size(mpc.gencost, 1) == 2*ng0 0212 ordering{2} = 'gen'; %% include Qg cost 0213 end 0214 mpc = e2i_field(mpc, 'gencost', ordering); 0215 end 0216 if isfield(mpc, 'A') || isfield(mpc, 'N') 0217 if dc 0218 ordering = {'bus', 'gen'}; 0219 else 0220 ordering = {'bus', 'bus', 'gen', 'gen'}; 0221 end 0222 end 0223 if isfield(mpc, 'A') 0224 mpc = e2i_field(mpc, 'A', ordering, 2); 0225 end 0226 if isfield(mpc, 'N') 0227 mpc = e2i_field(mpc, 'N', ordering, 2); 0228 end 0229 0230 %% execute userfcn callbacks for 'ext2int' stage 0231 if isfield(mpc, 'userfcn') 0232 mpc = run_userfcn(mpc.userfcn, 'ext2int', mpc); 0233 end 0234 end 0235 0236 i2e = mpc; 0237 else %% convert extra data 0238 ordering = branch; %% rename argument 0239 if nargin < 4 0240 dim = 1; 0241 else 0242 dim = areas; %% rename argument 0243 end 0244 if ischar(gen) || iscell(gen) %% field 0245 warning('Calls of the form MPC = EXT2INT(MPC, ''FIELD_NAME'', ...) have been deprecated. Please replace EXT2INT with E2I_FIELD.'); 0246 i2e = e2i_field(mpc, gen, branch, dim); 0247 else %% value 0248 warning('Calls of the form VAL = EXT2INT(MPC, VAL, ...) have been deprecated. Please replace EXT2INT with E2I_DATA.'); 0249 i2e = e2i_data(mpc, gen, branch, dim); 0250 end 0251 end 0252 else %% old form 0253 %% define names for columns to data matrices 0254 [PQ, PV, REF, NONE, BUS_I] = idx_bus; 0255 [GEN_BUS] = idx_gen; 0256 [F_BUS, T_BUS] = idx_brch; 0257 0258 %% create map of external bus numbers to bus indices 0259 i2e = bus(:, BUS_I); 0260 e2i = sparse(max(i2e), 1); 0261 e2i(i2e) = (1:size(bus, 1))'; 0262 0263 %% renumber buses consecutively 0264 bus(:, BUS_I) = e2i( bus(:, BUS_I) ); 0265 gen(:, GEN_BUS) = e2i( gen(:, GEN_BUS) ); 0266 branch(:, F_BUS) = e2i( branch(:, F_BUS) ); 0267 branch(:, T_BUS) = e2i( branch(:, T_BUS) ); 0268 end