Home > matpower5.1 > extract_islands.m

extract_islands

PURPOSE ^

function mpck = extract_islands(mpc, groups, k, custom)

SYNOPSIS ^

function mpck = extract_islands(mpc, varargin)

DESCRIPTION ^

function mpck = extract_islands(mpc, groups, k, custom)
EXTRACT_ISLANDS Extracts each island in a network with islands
   MPC_ARRAY = EXTRACT_ISLANDS(MPC)
   MPC_ARRAY = EXTRACT_ISLANDS(MPC, GROUPS)
   MPC_K = EXTRACT_ISLANDS(MPC, K)
   MPC_K = EXTRACT_ISLANDS(MPC, GROUPS, K)
   MPC_K = EXTRACT_ISLANDS(MPC, K, CUSTOM)
   MPC_K = EXTRACT_ISLANDS(MPC, GROUPS, K, CUSTOM)

   Returns a cell array of MATPOWER case structs for each island in
   the input case struct. If the optional second argument is a cell
   array GROUPS it is assumed to be a cell array of vectors of bus
   indices for each island (as returned by FIND_ISLANDS). Providing
   the GROUPS avoids the need for another traversal of the network
   connectivity and can save a significant amount of time on very
   large systems. If an additional argument K is included, it indicates
   which island(s) to return and the return value is a single case
   struct, rather than a cell array. If K is a scalar or vector, it
   it specifies the index(indices) of the island(s) to include in
   the resulting case file. K can also be the string 'all' which
   will include all islands. This is the same as simply eliminating
   all isolated buses.

   A final optional argument CUSTOM is a struct that can be used to
   indicate custom fields of MPC from which to extract data
   corresponding to buses generators, branches or DC lines. It has
   the following structure:

       CUSTOM.<ORDERING>{DIM} = FIELDS

   <ORDERING> is either 'bus', 'gen', 'branch' or 'dcline' and
   indicates that dimension DIM of FIELDS has dimensions
   corresponding to this <ORDERING> and should have the appropriate
   dimension extracted as well. FIELDS is a cell array, where
   each element is either a single string (field name of MPC) or
   a cell array of strings (nested fields of MPC).

   Examples:
       Extract each island into it's own case struct:
           mpc_list = extract_islands(mpc);

       Extract the 2nd (that is, 2nd largest) island:
           mpc2 = extract_islands(mpc, 2);

       Extract the first and 3rd islands without a re-traverals of the
       network:
           groups = find_islands(mpc);
           mpc1 = extract_islands(mpc, groups, 1);
           mpc3 = extract_islands(mpc, groups, 3);

       Extract the 2nd island, including custom fields, where
       mpc.bus_name{b} contains the name of bus b, and mpc.genfuel{g},
       mpc.emissions.rate(g, :), and mpc.genloc(:, g) contain,
       respectively, the generator's fuel type, emission rates and
       location coordinates:
           custom.bus{1} = {'bus_name'};
           custom.gen{1} = {'genfuel', {'emissions', 'rate'}};
           custom.gen{2} = {'genloc'};
           mpc = extract_islands(mpc, 1, custom);

   See also FIND_ISLANDS, CASE_INFO, CONNECTED_COMPONENTS.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function mpck = extract_islands(mpc, varargin)
0002 %function mpck = extract_islands(mpc, groups, k, custom)
0003 %EXTRACT_ISLANDS Extracts each island in a network with islands
0004 %   MPC_ARRAY = EXTRACT_ISLANDS(MPC)
0005 %   MPC_ARRAY = EXTRACT_ISLANDS(MPC, GROUPS)
0006 %   MPC_K = EXTRACT_ISLANDS(MPC, K)
0007 %   MPC_K = EXTRACT_ISLANDS(MPC, GROUPS, K)
0008 %   MPC_K = EXTRACT_ISLANDS(MPC, K, CUSTOM)
0009 %   MPC_K = EXTRACT_ISLANDS(MPC, GROUPS, K, CUSTOM)
0010 %
0011 %   Returns a cell array of MATPOWER case structs for each island in
0012 %   the input case struct. If the optional second argument is a cell
0013 %   array GROUPS it is assumed to be a cell array of vectors of bus
0014 %   indices for each island (as returned by FIND_ISLANDS). Providing
0015 %   the GROUPS avoids the need for another traversal of the network
0016 %   connectivity and can save a significant amount of time on very
0017 %   large systems. If an additional argument K is included, it indicates
0018 %   which island(s) to return and the return value is a single case
0019 %   struct, rather than a cell array. If K is a scalar or vector, it
0020 %   it specifies the index(indices) of the island(s) to include in
0021 %   the resulting case file. K can also be the string 'all' which
0022 %   will include all islands. This is the same as simply eliminating
0023 %   all isolated buses.
0024 %
0025 %   A final optional argument CUSTOM is a struct that can be used to
0026 %   indicate custom fields of MPC from which to extract data
0027 %   corresponding to buses generators, branches or DC lines. It has
0028 %   the following structure:
0029 %
0030 %       CUSTOM.<ORDERING>{DIM} = FIELDS
0031 %
0032 %   <ORDERING> is either 'bus', 'gen', 'branch' or 'dcline' and
0033 %   indicates that dimension DIM of FIELDS has dimensions
0034 %   corresponding to this <ORDERING> and should have the appropriate
0035 %   dimension extracted as well. FIELDS is a cell array, where
0036 %   each element is either a single string (field name of MPC) or
0037 %   a cell array of strings (nested fields of MPC).
0038 %
0039 %   Examples:
0040 %       Extract each island into it's own case struct:
0041 %           mpc_list = extract_islands(mpc);
0042 %
0043 %       Extract the 2nd (that is, 2nd largest) island:
0044 %           mpc2 = extract_islands(mpc, 2);
0045 %
0046 %       Extract the first and 3rd islands without a re-traverals of the
0047 %       network:
0048 %           groups = find_islands(mpc);
0049 %           mpc1 = extract_islands(mpc, groups, 1);
0050 %           mpc3 = extract_islands(mpc, groups, 3);
0051 %
0052 %       Extract the 2nd island, including custom fields, where
0053 %       mpc.bus_name{b} contains the name of bus b, and mpc.genfuel{g},
0054 %       mpc.emissions.rate(g, :), and mpc.genloc(:, g) contain,
0055 %       respectively, the generator's fuel type, emission rates and
0056 %       location coordinates:
0057 %           custom.bus{1} = {'bus_name'};
0058 %           custom.gen{1} = {'genfuel', {'emissions', 'rate'}};
0059 %           custom.gen{2} = {'genloc'};
0060 %           mpc = extract_islands(mpc, 1, custom);
0061 %
0062 %   See also FIND_ISLANDS, CASE_INFO, CONNECTED_COMPONENTS.
0063 
0064 %   MATPOWER
0065 %   Copyright (c) 2012-2015 by Power System Engineering Research Center (PSERC)
0066 %   by Ray Zimmerman, PSERC Cornell
0067 %
0068 %   $Id: extract_islands.m 2644 2015-03-11 19:34:22Z ray $
0069 %
0070 %   This file is part of MATPOWER.
0071 %   Covered by the 3-clause BSD License (see LICENSE file for details).
0072 %   See http://www.pserc.cornell.edu/matpower/ for more info.
0073 
0074 %% define named indices into data matrices
0075 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
0076     VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
0077 [GEN_BUS, PG, QG, QMAX, QMIN, VG, MBASE, GEN_STATUS, PMAX, PMIN, ...
0078     MU_PMAX, MU_PMIN, MU_QMAX, MU_QMIN, PC1, PC2, QC1MIN, QC1MAX, ...
0079     QC2MIN, QC2MAX, RAMP_AGC, RAMP_10, RAMP_30, RAMP_Q, APF] = idx_gen;
0080 [F_BUS, T_BUS, BR_R, BR_X, BR_B, RATE_A, RATE_B, RATE_C, ...
0081     TAP, SHIFT, BR_STATUS, PF, QF, PT, QT, MU_SF, MU_ST, ...
0082     ANGMIN, ANGMAX, MU_ANGMIN, MU_ANGMAX] = idx_brch;
0083 c = idx_dcline;
0084 
0085 %% set up connectivity matrices
0086 nb  = size(mpc.bus, 1);     %% number of buses
0087 nl  = size(mpc.branch, 1);  %% number of branches
0088 if isfield(mpc, 'dcline')   %% number of DC lines
0089     ndc = size(mpc.dcline, 1);
0090 else
0091     ndc = 0;
0092 end
0093 ng  = size(mpc.gen, 1);     %% number of dispatchable injections
0094 
0095 e2i = sparse(mpc.bus(:, BUS_I), ones(nb, 1), 1:nb, max(mpc.bus(:, BUS_I)), 1);
0096 C_on = sparse(1:nl, e2i(mpc.branch(:, F_BUS)), -mpc.branch(:, BR_STATUS), nl, nb) + ...
0097     sparse(1:nl, e2i(mpc.branch(:, T_BUS)),  mpc.branch(:, BR_STATUS), nl, nb);
0098 C = sparse(1:nl, e2i(mpc.branch(:, F_BUS)), -1, nl, nb) + ...
0099     sparse(1:nl, e2i(mpc.branch(:, T_BUS)),  1, nl, nb);
0100 if ndc
0101     Cdc_on = sparse(1:ndc, e2i(mpc.dcline(:, c.F_BUS)), -mpc.dcline(:, c.BR_STATUS), ndc, nb) + ...
0102         sparse(1:ndc, e2i(mpc.dcline(:, c.T_BUS)),  mpc.dcline(:, c.BR_STATUS), ndc, nb);
0103     Cdc = sparse(1:ndc, e2i(mpc.dcline(:, c.F_BUS)), -1, ndc, nb) + ...
0104         sparse(1:ndc, e2i(mpc.dcline(:, c.T_BUS)),  1, ndc, nb);
0105 end
0106 Cg_on = sparse(1:ng, e2i(mpc.gen(:, GEN_BUS)), mpc.gen(:, GEN_STATUS), ng, nb);
0107 Cg = sparse(1:ng, e2i(mpc.gen(:, GEN_BUS)), 1, ng, nb);
0108 
0109 if nnz(C)
0110     n = length(varargin);
0111     if n >= 1 && iscell(varargin{1})
0112         groups = varargin{1};
0113         z = 1;
0114     else
0115         groups = {};
0116         z = 0;
0117     end
0118     if z+1 <= n
0119         k = varargin{z+1};
0120     else
0121         k = [];
0122     end
0123     if z+2 <= n
0124         custom = varargin{z+2};
0125     else
0126         custom = struct();
0127     end
0128     
0129     %% find islands, if not provided
0130     if isempty(groups)
0131         groups = connected_components(C_on);
0132     end
0133     
0134     %% check inputs
0135     if isempty(k)
0136         g1 = 1;
0137         gn = length(groups);
0138     else
0139         if ischar(k)
0140             if strcmp(upper(k), 'ALL')
0141                 k = (1:length(groups))';
0142             else
0143                 error('extract_islands: K = ''%s'' is not a valid input', k);
0144             end
0145         end
0146         if max(k) > length(groups)
0147             error('extract_islands: cannot extract island %d, network has only %d islands', ...
0148                     max(k), length(groups));
0149         end
0150         if length(k) > 1        %% extract multiple islands as one case
0151             tmpgroup = groups{k(1)};
0152             for j = 2:length(k)
0153                 tmpgroup = union(tmpgroup, groups{k(j)});
0154             end
0155             groups = { tmpgroup };
0156             g1 = 1;
0157             gn = 1;
0158         else                    %% extract single island
0159             g1 = k;
0160             gn = k;
0161         end
0162     end
0163     
0164     %% extract islands
0165     for i = g1:gn
0166         kk  = i-g1+1;
0167         b  = groups{i};                     %% buses in group i
0168         %% branches with both ends in group i
0169         ibr = find(sum(abs(C(:, b)), 2) & ~sum(C(:, b), 2));
0170         ig  = find(sum(Cg(:, b), 2));       %% gens in group i
0171         %% DC lines with both ends in group i
0172         if ndc
0173             idc = find(sum(abs(Cdc(:, b)), 2) & ~sum(Cdc(:, b), 2));
0174         else
0175             idc = [];
0176         end
0177     
0178         mpck{kk}        = mpc;
0179         mpck{kk}.bus    = mpc.bus(b, :);
0180         mpck{kk}.branch = mpc.branch(ibr, :);
0181         mpck{kk}.gen    = mpc.gen(ig, :);
0182         if isfield(mpck{kk}, 'gencost')
0183             if size(mpck{kk}.gencost, 1) == 2*ng
0184                 mpck{kk}.gencost = mpc.gencost([ig; ng+ig], :);
0185             else
0186                 mpck{kk}.gencost = mpc.gencost(ig, :);
0187             end
0188         end
0189         if ndc
0190             mpck{kk}.dcline = mpc.dcline(idc, :);
0191             if isfield(mpck{kk}, 'dclinecost')
0192                 mpck{kk}.dclinecost = mpc.dclinecost(idc, :);
0193             end
0194         end
0195 
0196         %% handle custom fields
0197         orderings = {'bus', 'gen', 'branch', 'dcline'};
0198         indexes = {b, ig, ibr, idc};
0199 
0200         for n = 1:length(orderings)
0201             ord = orderings{n};
0202             if isfield(custom, ord)
0203                 for dim = 1:length(custom.(ord))
0204                     for j = 1:length(custom.(ord){dim})
0205                         s = [];
0206                         field = custom.(ord){dim}{j};
0207                         if ischar(field)
0208                             field = { field };
0209                         end
0210 
0211                         tmp = mpck{kk}; %% check this for presence of sub-fields
0212                         skip = 0;
0213                         for i = 1:length(field)
0214                             s(i).type = '.';
0215                             s(i).subs = field{i};
0216                             if isfield(tmp, field{i}) && ~isempty(tmp.(field{i}))
0217                                 %% have sub-field, continue
0218                                 tmp = tmp.(field{i});
0219                             else
0220                                 %% sub-field doesn't exist, skip it
0221                                 skip = 1;
0222                                 break;
0223                             end
0224                         end
0225                         if ~skip
0226                             mpck{kk} = subsasgn(mpck{kk}, s, get_reorder(subsref(mpck{kk}, s), indexes{n}, dim));
0227                         end
0228                     end
0229                 end
0230             end
0231         end
0232     end
0233 
0234     %% convert from cell array to single MATPOWER case struct as appropriate
0235     if ~isempty(k)
0236         mpck = mpck{1};
0237     end
0238 else
0239     mpck = [];
0240 end

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