Package pypower :: Module makePTDF
[hide private]
[frames] | no frames]

Source Code for Module pypower.makePTDF

 1  # Copyright (C) 2006-2011 Power System Engineering Research Center (PSERC) 
 2  # Copyright (C) 2011 Richard Lincoln 
 3  # 
 4  # PYPOWER is free software: you can redistribute it and/or modify 
 5  # it under the terms of the GNU General Public License as published 
 6  # by the Free Software Foundation, either version 3 of the License, 
 7  # or (at your option) any later version. 
 8  # 
 9  # PYPOWER is distributed in the hope that it will be useful, 
10  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
11  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
12  # GNU General Public License for more details. 
13  # 
14  # You should have received a copy of the GNU General Public License 
15  # along with PYPOWER. If not, see <http://www.gnu.org/licenses/>. 
16   
17  """Builds the DC PTDF matrix for a given choice of slack. 
18  """ 
19   
20  from sys import stderr 
21   
22  from numpy import zeros, arange, isscalar, dot, ix_, flatnonzero as find 
23   
24  from numpy.linalg import solve 
25   
26  from idx_bus import BUS_TYPE, REF, BUS_I 
27  from makeBdc import makeBdc 
28   
29   
30 -def makePTDF(baseMVA, bus, branch, slack=None):
31 """Builds the DC PTDF matrix for a given choice of slack. 32 33 Returns the DC PTDF matrix for a given choice of slack. The matrix is 34 C{nbr x nb}, where C{nbr} is the number of branches and C{nb} is the 35 number of buses. The C{slack} can be a scalar (single slack bus) or an 36 C{nb x 1} column vector of weights specifying the proportion of the 37 slack taken up at each bus. If the C{slack} is not specified the 38 reference bus is used by default. 39 40 For convenience, C{slack} can also be an C{nb x nb} matrix, where each 41 column specifies how the slack should be handled for injections 42 at that bus. 43 44 @see: L{makeLODF} 45 46 @author: Ray Zimmerman (PSERC Cornell) 47 @author: Richard Lincoln 48 """ 49 ## use reference bus for slack by default 50 if slack is None: 51 slack = find(bus[:, BUS_TYPE] == REF) 52 slack = slack[0] 53 54 ## set the slack bus to be used to compute initial PTDF 55 if isscalar(slack): 56 slack_bus = slack 57 else: 58 slack_bus = 0 ## use bus 1 for temp slack bus 59 60 nb = bus.shape[0] 61 nbr = branch.shape[0] 62 noref = arange(1, nb) ## use bus 1 for voltage angle reference 63 noslack = find(arange(nb) != slack_bus) 64 65 ## check that bus numbers are equal to indices to bus (one set of bus numbers) 66 if any(bus[:, BUS_I] != arange(nb)): 67 stderr.write('makePTDF: buses must be numbered consecutively') 68 69 ## compute PTDF for single slack_bus 70 Bbus, Bf, _, _ = makeBdc(baseMVA, bus, branch) 71 Bbus, Bf = Bbus.todense(), Bf.todense() 72 H = zeros((nbr, nb)) 73 H[:, noslack] = solve( Bbus[ix_(noslack, noref)].T, Bf[:, noref].T ).T 74 # = Bf[:, noref] * inv(Bbus[ix_(noslack, noref)]) 75 76 ## distribute slack, if requested 77 if not isscalar(slack): 78 if len(slack.shape) == 1: ## slack is a vector of weights 79 slack = slack / sum(slack) ## normalize weights 80 81 ## conceptually, we want to do ... 82 ## H = H * (eye(nb, nb) - slack * ones((1, nb))) 83 ## ... we just do it more efficiently 84 v = dot(H, slack) 85 for k in range(nb): 86 H[:, k] = H[:, k] - v 87 else: 88 H = dot(H, slack) 89 90 return H
91