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

Source Code for Module pypower.dSbr_dV

  1  # Copyright (C) 1996-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  """Computes partial derivatives of power flows w.r.t. voltage. 
 18  """ 
 19   
 20  from numpy import conj, arange, diag, zeros, asmatrix, asarray, asscalar 
 21  from scipy.sparse import issparse, csr_matrix as sparse 
 22   
 23  from idx_brch import F_BUS, T_BUS 
 24   
25 -def dSbr_dV(branch, Yf, Yt, V):
26 """Computes partial derivatives of power flows w.r.t. voltage. 27 28 returns four matrices containing partial derivatives of the complex 29 branch power flows at "from" and "to" ends of each branch w.r.t voltage 30 magnitude and voltage angle respectively (for all buses). If C{Yf} is a 31 sparse matrix, the partial derivative matrices will be as well. Optionally 32 returns vectors containing the power flows themselves. The following 33 explains the expressions used to form the matrices:: 34 35 If = Yf * V; 36 Sf = diag(Vf) * conj(If) = diag(conj(If)) * Vf 37 38 Partials of V, Vf & If w.r.t. voltage angles:: 39 dV/dVa = j * diag(V) 40 dVf/dVa = sparse(range(nl), f, j*V(f)) = j * sparse(range(nl), f, V(f)) 41 dIf/dVa = Yf * dV/dVa = Yf * j * diag(V) 42 43 Partials of V, Vf & If w.r.t. voltage magnitudes:: 44 dV/dVm = diag(V / abs(V)) 45 dVf/dVm = sparse(range(nl), f, V(f) / abs(V(f)) 46 dIf/dVm = Yf * dV/dVm = Yf * diag(V / abs(V)) 47 48 Partials of Sf w.r.t. voltage angles:: 49 dSf/dVa = diag(Vf) * conj(dIf/dVa) 50 + diag(conj(If)) * dVf/dVa 51 = diag(Vf) * conj(Yf * j * diag(V)) 52 + conj(diag(If)) * j * sparse(range(nl), f, V(f)) 53 = -j * diag(Vf) * conj(Yf * diag(V)) 54 + j * conj(diag(If)) * sparse(range(nl), f, V(f)) 55 = j * (conj(diag(If)) * sparse(range(nl), f, V(f)) 56 - diag(Vf) * conj(Yf * diag(V))) 57 58 Partials of Sf w.r.t. voltage magnitudes:: 59 dSf/dVm = diag(Vf) * conj(dIf/dVm) 60 + diag(conj(If)) * dVf/dVm 61 = diag(Vf) * conj(Yf * diag(V / abs(V))) 62 + conj(diag(If)) * sparse(range(nl), f, V(f)/abs(V(f))) 63 64 Derivations for "to" bus are similar. 65 66 For more details on the derivations behind the derivative code used 67 in PYPOWER information, see: 68 69 [TN2] R. D. Zimmerman, "AC Power Flows, Generalized OPF Costs and 70 their Derivatives using Complex Matrix Notation", MATPOWER 71 Technical Note 2, February 2010. 72 U{http://www.pserc.cornell.edu/matpower/TN2-OPF-Derivatives.pdf} 73 74 @author: Ray Zimmerman (PSERC Cornell) 75 @author: Richard Lincoln 76 """ 77 ## define 78 f = branch[:, F_BUS].astype(int) ## list of "from" buses 79 t = branch[:, T_BUS].astype(int) ## list of "to" buses 80 nl = len(f) 81 nb = len(V) 82 il = arange(nl) 83 ib = arange(nb) 84 85 Vnorm = V / abs(V) 86 87 if issparse(Yf): 88 ## compute currents 89 If = Yf * V 90 It = Yt * V 91 92 diagVf = sparse((V[f], (il, il))) 93 diagIf = sparse((If, (il, il))) 94 diagVt = sparse((V[t], (il, il))) 95 diagIt = sparse((It, (il, il))) 96 diagV = sparse((V, (ib, ib))) 97 diagVnorm = sparse((Vnorm, (ib, ib))) 98 99 shape = (nl, nb) 100 # Partial derivative of S w.r.t voltage phase angle. 101 dSf_dVa = 1j * (conj(diagIf) * 102 sparse((V[f], (il, f)), shape) - diagVf * conj(Yf * diagV)) 103 104 dSt_dVa = 1j * (conj(diagIt) * 105 sparse((V[t], (il, t)), shape) - diagVt * conj(Yt * diagV)) 106 107 # Partial derivative of S w.r.t. voltage amplitude. 108 dSf_dVm = diagVf * conj(Yf * diagVnorm) + conj(diagIf) * \ 109 sparse((Vnorm[f], (il, f)), shape) 110 111 dSt_dVm = diagVt * conj(Yt * diagVnorm) + conj(diagIt) * \ 112 sparse((Vnorm[t], (il, t)), shape) 113 else: ## dense version 114 ## compute currents 115 If = asarray( Yf * asmatrix(V).T ).flatten() 116 It = asarray( Yt * asmatrix(V).T ).flatten() 117 118 diagVf = asmatrix( diag(V[f]) ) 119 diagIf = asmatrix( diag(If) ) 120 diagVt = asmatrix( diag(V[t]) ) 121 diagIt = asmatrix( diag(It) ) 122 diagV = asmatrix( diag(V) ) 123 diagVnorm = asmatrix( diag(Vnorm) ) 124 temp1 = asmatrix( zeros((nl, nb), complex) ) 125 temp2 = asmatrix( zeros((nl, nb), complex) ) 126 temp3 = asmatrix( zeros((nl, nb), complex) ) 127 temp4 = asmatrix( zeros((nl, nb), complex) ) 128 for i in range(nl): 129 fi, ti = f[i], t[i] 130 temp1[i, fi] = asscalar(V[fi]) 131 temp2[i, fi] = asscalar(Vnorm[fi]) 132 temp3[i, ti] = asscalar(V[ti]) 133 temp4[i, ti] = asscalar(Vnorm[ti]) 134 135 dSf_dVa = 1j * (conj(diagIf) * temp1 - diagVf * conj(Yf * diagV)) 136 dSf_dVm = diagVf * conj(Yf * diagVnorm) + conj(diagIf) * temp2 137 dSt_dVa = 1j * (conj(diagIt) * temp3 - diagVt * conj(Yt * diagV)) 138 dSt_dVm = diagVt * conj(Yt * diagVnorm) + conj(diagIt) * temp4 139 140 # Compute power flow vectors. 141 Sf = V[f] * conj(If) 142 St = V[t] * conj(It) 143 144 return dSf_dVa, dSf_dVm, dSt_dVa, dSt_dVm, Sf, St
145