Home > matpower7.1 > lib > makePTDF.m

makePTDF

PURPOSE ^

MAKEPTDF Builds the DC PTDF matrix for a given choice of slack.

SYNOPSIS ^

function H = makePTDF(baseMVA, bus, branch, slack, bus_idx)

DESCRIPTION ^

MAKEPTDF   Builds the DC PTDF matrix for a given choice of slack.
   H = MAKEPTDF(MPC)
   H = MAKEPTDF(MPC, SLACK)
   H = MAKEPTDF(MPC, SLACK, TXFR)
   H = MAKEPTDF(MPC, SLACK, BUS_IDX)
   H = MAKEPTDF(BASEMVA, BUS, BRANCH)
   H = MAKEPTDF(BASEMVA, BUS, BRANCH, SLACK)
   H = MAKEPTDF(BASEMVA, BUS, BRANCH, SLACK, TXFR)
   H = MAKEPTDF(BASEMVA, BUS, BRANCH, SLACK, BUS_IDX)

   Returns the DC PTDF matrix for a given choice of slack. The matrix is
   nbr x nb, where nbr is the number of branches and nb is the number of
   buses. The SLACK can be a scalar (single slack bus) or an nb x 1 column
   vector of weights specifying the proportion of the slack taken up at each
   bus. If the SLACK is not specified the reference bus is used by default.
   Bus numbers must be consecutive beginning at 1 (i.e. internal ordering).

   If TXFR is supplied it must be a matrix (or vector) with nb rows whose
   columns each sum to zero, where each column defines a specific (slack
   independent) transfer. E.g. if k-th transfer is from bus i to bus j,
   TXFR(i, k) = 1 and TXFR(j, k) = -1. In this case H has the same number
   of columns as TXFR.

   If BUS_IDX is supplied, it contains a column vector of bus indices.
   The columns of H correspond to these indices, but they are computed
   individually rather than computing the full PTDF matrix and selecting
   the desired columns.

   Examples:
       H = makePTDF(mpc);
       H = makePTDF(baseMVA, bus, branch, 1);
       slack = rand(size(bus, 1), 1);
       H = makePTDF(mpc, slack);

       % for transfer from bus i to bus j
       txfr = zeros(nb, 1); txfr(i) = 1; txfr(j) = -1;
       H = makePTDF(mpc, slack, txfr);

       % for buses i and j only
       H = makePTDF(mpc, slack, [i;j]);

   See also MAKELODF.

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SOURCE CODE ^

0001 function H = makePTDF(baseMVA, bus, branch, slack, bus_idx)
0002 %MAKEPTDF   Builds the DC PTDF matrix for a given choice of slack.
0003 %   H = MAKEPTDF(MPC)
0004 %   H = MAKEPTDF(MPC, SLACK)
0005 %   H = MAKEPTDF(MPC, SLACK, TXFR)
0006 %   H = MAKEPTDF(MPC, SLACK, BUS_IDX)
0007 %   H = MAKEPTDF(BASEMVA, BUS, BRANCH)
0008 %   H = MAKEPTDF(BASEMVA, BUS, BRANCH, SLACK)
0009 %   H = MAKEPTDF(BASEMVA, BUS, BRANCH, SLACK, TXFR)
0010 %   H = MAKEPTDF(BASEMVA, BUS, BRANCH, SLACK, BUS_IDX)
0011 %
0012 %   Returns the DC PTDF matrix for a given choice of slack. The matrix is
0013 %   nbr x nb, where nbr is the number of branches and nb is the number of
0014 %   buses. The SLACK can be a scalar (single slack bus) or an nb x 1 column
0015 %   vector of weights specifying the proportion of the slack taken up at each
0016 %   bus. If the SLACK is not specified the reference bus is used by default.
0017 %   Bus numbers must be consecutive beginning at 1 (i.e. internal ordering).
0018 %
0019 %   If TXFR is supplied it must be a matrix (or vector) with nb rows whose
0020 %   columns each sum to zero, where each column defines a specific (slack
0021 %   independent) transfer. E.g. if k-th transfer is from bus i to bus j,
0022 %   TXFR(i, k) = 1 and TXFR(j, k) = -1. In this case H has the same number
0023 %   of columns as TXFR.
0024 %
0025 %   If BUS_IDX is supplied, it contains a column vector of bus indices.
0026 %   The columns of H correspond to these indices, but they are computed
0027 %   individually rather than computing the full PTDF matrix and selecting
0028 %   the desired columns.
0029 %
0030 %   Examples:
0031 %       H = makePTDF(mpc);
0032 %       H = makePTDF(baseMVA, bus, branch, 1);
0033 %       slack = rand(size(bus, 1), 1);
0034 %       H = makePTDF(mpc, slack);
0035 %
0036 %       % for transfer from bus i to bus j
0037 %       txfr = zeros(nb, 1); txfr(i) = 1; txfr(j) = -1;
0038 %       H = makePTDF(mpc, slack, txfr);
0039 %
0040 %       % for buses i and j only
0041 %       H = makePTDF(mpc, slack, [i;j]);
0042 %
0043 %   See also MAKELODF.
0044 
0045 %   For convenience, SLACK can also be an nb x nb matrix, where each
0046 %   column specifies how the slack should be handled for injections
0047 %   at that bus. This option only applies when computing the full
0048 %   PTDF matrix (i.e. when TXFR and BUS_IDX are not provided.)
0049 
0050 %   MATPOWER
0051 %   Copyright (c) 2006-2020, Power Systems Engineering Research Center (PSERC)
0052 %   by Ray Zimmerman, PSERC Cornell
0053 %
0054 %   This file is part of MATPOWER.
0055 %   Covered by the 3-clause BSD License (see LICENSE file for details).
0056 %   See https://matpower.org for more info.
0057 
0058 %% extract from MPC if necessary
0059 if isstruct(baseMVA)
0060     mpc = baseMVA;
0061     if nargin < 3
0062         bus_idx = [];
0063         if nargin < 2
0064             slack = [];
0065         else
0066             slack = bus;
0067         end
0068     else
0069         slack = bus;
0070         bus_idx = branch;
0071     end
0072     baseMVA = mpc.baseMVA;
0073     bus     = mpc.bus;
0074     branch  = mpc.branch;
0075 else
0076     if nargin < 5
0077         bus_idx = [];
0078         if nargin < 4
0079             slack = [];
0080         end
0081     end
0082 end
0083 
0084 %% define named indices into bus matrix
0085 [PQ, PV, REF, NONE, BUS_I, BUS_TYPE, PD, QD, GS, BS, BUS_AREA, VM, ...
0086     VA, BASE_KV, ZONE, VMAX, VMIN, LAM_P, LAM_Q, MU_VMAX, MU_VMIN] = idx_bus;
0087 
0088 %% use reference bus for slack by default
0089 if isempty(slack)
0090     slack = find(bus(:, BUS_TYPE) == REF);
0091     slack = slack(1);
0092 end
0093 
0094 %% compute full PTDF?
0095 nb = size(bus, 1);
0096 nbr = size(branch, 1);
0097 txfr = 0;               %% default assumes not just for specific transfers
0098 if ~isempty(bus_idx)
0099     compute_full_H = 0;
0100     if size(bus_idx, 1) == nb && sum(sum(bus_idx)) == 0
0101         txfr = 1;       %% cols of H for specific (slack independent) transfers
0102         dP = bus_idx;
0103     end
0104 else
0105     compute_full_H = 1;
0106 end
0107 
0108 %% set the slack bus to be used to compute initial PTDF
0109 if length(slack) == 1
0110     slack_bus = slack;
0111 else
0112     slack_bus = 1;      %% use bus 1 for temp slack bus
0113 end
0114 
0115 noref   = (2:nb)';      %% use bus 1 for voltage angle reference
0116 noslack = find((1:nb)' ~= slack_bus);
0117 
0118 %% check that bus numbers are equal to indices to bus (one set of bus numbers)
0119 if any(bus(:, BUS_I) ~= (1:nb)')
0120     error('makePTDF: buses must be numbered consecutively in bus matrix; use ext2int() to convert to internal ordering')
0121 end
0122 
0123 %%-----  compute PTDF for single slack_bus  -----
0124 [Bbus, Bf, Pbusinj, Pfinj] = makeBdc(baseMVA, bus, branch);
0125 
0126 %% set up injections/transfers
0127 if compute_full_H   %% full H for all columns
0128 %     %% old (slower) method
0129 %     H = zeros(nbr, nb);
0130 %     H(:, noslack) = full(Bf(:, noref) / Bbus(noslack, noref));
0131 %             %%    = full(Bf(:, noref) * inv(Bbus(noslack, noref)));
0132     nbi = nb;       %% number of buses of interest (i.e. all of them)
0133     dP = speye(nb, nb);
0134 else                %% compute only for specific columns
0135     if txfr             %% for specific transfers
0136         nbi = size(dP, 2);          %% number of transfers
0137     else                %% for subset of columns of H for specific buses
0138         %% if necessary add missing slacks to bus index list
0139         nbi0 = length(bus_idx);     %% number of original buses of interest
0140         bidx = bus_idx;
0141         if length(slack) ~= 1 && size(slack, 2) == 1
0142             slacks = find(slack);   %% get all slack buses
0143             k = find(~ismember(slacks, bus_idx));   %% find slacks not in bus_idx
0144             if ~isempty(k)
0145                 bidx = [bus_idx; slacks(k)];
0146             end
0147         end
0148         nbi = size(bidx, 1);        %% number of buses of interest
0149 
0150         %% define the equivalent transfer, each column is a single transfer
0151         dP = accumarray([bidx (1:nbi)'], 1, [nb, nbi]);
0152     end
0153 end
0154 
0155 %% solve for change in voltage angles
0156 dTheta = zeros(nb, nbi);
0157 dTheta(noref, :) = Bbus(noslack, noref) \ dP(noslack, :);
0158 
0159 %% compute corresponding change in branch flows
0160 H = Bf * dTheta;
0161 
0162 %%-----  distribute slack, if requested  -----
0163 if length(slack) ~= 1 && ~txfr
0164     if size(slack, 2) == 1  %% slack is a vector of weights
0165         slack = slack/sum(slack);   %% normalize weights
0166         
0167         %% conceptually, we want to do ...
0168         %%    H = H * (eye(nb,nb) - slack * ones(1, nb));
0169         %% ... we just do it more efficiently
0170         if compute_full_H
0171             v = H * slack;
0172             for k = 1:nb
0173                 H(:, k) = H(:, k) - v;
0174             end
0175         else
0176             v = H * slack(bidx);
0177             for k = 1:nbi
0178                 H(:, k) = H(:, k) - v;
0179             end
0180             H = H(:, 1:nbi0);   %% remove temp cols added for missing slacks
0181         end
0182     else
0183         H = H * slack;
0184     end
0185 end

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