ltbams 0.9.9__py3-none-any.whl → 1.0.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ams/__init__.py +4 -11
- ams/_version.py +3 -3
- ams/cases/5bus/pjm5bus_demo.xlsx +0 -0
- ams/cases/5bus/pjm5bus_jumper.xlsx +0 -0
- ams/cases/5bus/pjm5bus_uced.json +1062 -0
- ams/cases/5bus/pjm5bus_uced.xlsx +0 -0
- ams/cases/5bus/pjm5bus_uced_esd1.xlsx +0 -0
- ams/cases/5bus/pjm5bus_uced_ev.xlsx +0 -0
- ams/cases/ieee123/ieee123.xlsx +0 -0
- ams/cases/ieee123/ieee123_regcv1.xlsx +0 -0
- ams/cases/ieee14/ieee14.json +1166 -0
- ams/cases/ieee14/ieee14.raw +92 -0
- ams/cases/ieee14/ieee14_conn.xlsx +0 -0
- ams/cases/ieee14/ieee14_uced.xlsx +0 -0
- ams/cases/ieee39/ieee39.xlsx +0 -0
- ams/cases/ieee39/ieee39_uced.xlsx +0 -0
- ams/cases/ieee39/ieee39_uced_esd1.xlsx +0 -0
- ams/cases/ieee39/ieee39_uced_pvd1.xlsx +0 -0
- ams/cases/ieee39/ieee39_uced_vis.xlsx +0 -0
- ams/cases/matpower/benchmark.json +1594 -0
- ams/cases/matpower/case118.m +787 -0
- ams/cases/matpower/case14.m +129 -0
- ams/cases/matpower/case300.m +1315 -0
- ams/cases/matpower/case39.m +205 -0
- ams/cases/matpower/case5.m +62 -0
- ams/cases/matpower/case_ACTIVSg2000.m +9460 -0
- ams/cases/npcc/npcc.m +644 -0
- ams/cases/npcc/npcc_uced.xlsx +0 -0
- ams/cases/pglib/pglib_opf_case39_epri__api.m +243 -0
- ams/cases/wecc/wecc.m +714 -0
- ams/cases/wecc/wecc_uced.xlsx +0 -0
- ams/cli.py +6 -0
- ams/core/__init__.py +2 -0
- ams/core/documenter.py +652 -0
- ams/core/matprocessor.py +782 -0
- ams/core/model.py +330 -0
- ams/core/param.py +322 -0
- ams/core/service.py +918 -0
- ams/core/symprocessor.py +224 -0
- ams/core/var.py +59 -0
- ams/extension/__init__.py +5 -0
- ams/extension/eva.py +401 -0
- ams/interface.py +1085 -0
- ams/io/__init__.py +133 -0
- ams/io/json.py +82 -0
- ams/io/matpower.py +406 -0
- ams/io/psse.py +6 -0
- ams/io/pypower.py +103 -0
- ams/io/xlsx.py +80 -0
- ams/main.py +81 -4
- ams/models/__init__.py +24 -0
- ams/models/area.py +40 -0
- ams/models/bus.py +52 -0
- ams/models/cost.py +169 -0
- ams/models/distributed/__init__.py +3 -0
- ams/models/distributed/esd1.py +71 -0
- ams/models/distributed/ev.py +60 -0
- ams/models/distributed/pvd1.py +67 -0
- ams/models/group.py +231 -0
- ams/models/info.py +26 -0
- ams/models/line.py +238 -0
- ams/models/renewable/__init__.py +5 -0
- ams/models/renewable/regc.py +119 -0
- ams/models/reserve.py +94 -0
- ams/models/shunt.py +14 -0
- ams/models/static/__init__.py +2 -0
- ams/models/static/gen.py +165 -0
- ams/models/static/pq.py +61 -0
- ams/models/timeslot.py +69 -0
- ams/models/zone.py +49 -0
- ams/opt/__init__.py +12 -0
- ams/opt/constraint.py +175 -0
- ams/opt/exprcalc.py +127 -0
- ams/opt/expression.py +188 -0
- ams/opt/objective.py +174 -0
- ams/opt/omodel.py +432 -0
- ams/opt/optzbase.py +192 -0
- ams/opt/param.py +156 -0
- ams/opt/var.py +233 -0
- ams/pypower/__init__.py +8 -0
- ams/pypower/_compat.py +9 -0
- ams/pypower/core/__init__.py +8 -0
- ams/pypower/core/pips.py +894 -0
- ams/pypower/core/ppoption.py +244 -0
- ams/pypower/core/ppver.py +18 -0
- ams/pypower/core/solver.py +2451 -0
- ams/pypower/eps.py +6 -0
- ams/pypower/idx.py +174 -0
- ams/pypower/io.py +604 -0
- ams/pypower/make/__init__.py +11 -0
- ams/pypower/make/matrices.py +665 -0
- ams/pypower/make/pdv.py +506 -0
- ams/pypower/routines/__init__.py +7 -0
- ams/pypower/routines/cpf.py +513 -0
- ams/pypower/routines/cpf_callbacks.py +114 -0
- ams/pypower/routines/opf.py +1803 -0
- ams/pypower/routines/opffcns.py +1946 -0
- ams/pypower/routines/pflow.py +852 -0
- ams/pypower/toggle.py +1098 -0
- ams/pypower/utils.py +293 -0
- ams/report.py +212 -50
- ams/routines/__init__.py +23 -0
- ams/routines/acopf.py +117 -0
- ams/routines/cpf.py +65 -0
- ams/routines/dcopf.py +241 -0
- ams/routines/dcpf.py +209 -0
- ams/routines/dcpf0.py +196 -0
- ams/routines/dopf.py +150 -0
- ams/routines/ed.py +312 -0
- ams/routines/pflow.py +255 -0
- ams/routines/pflow0.py +113 -0
- ams/routines/routine.py +1033 -0
- ams/routines/rted.py +519 -0
- ams/routines/type.py +160 -0
- ams/routines/uc.py +376 -0
- ams/shared.py +63 -9
- ams/system.py +61 -22
- ams/utils/__init__.py +3 -0
- ams/utils/misc.py +77 -0
- ams/utils/paths.py +257 -0
- docs/Makefile +21 -0
- docs/make.bat +35 -0
- docs/source/_templates/autosummary/base.rst +5 -0
- docs/source/_templates/autosummary/class.rst +35 -0
- docs/source/_templates/autosummary/module.rst +65 -0
- docs/source/_templates/autosummary/module_toctree.rst +66 -0
- docs/source/api.rst +102 -0
- docs/source/conf.py +206 -0
- docs/source/examples/index.rst +34 -0
- docs/source/genmodelref.py +61 -0
- docs/source/genroutineref.py +47 -0
- docs/source/getting_started/copyright.rst +20 -0
- docs/source/getting_started/formats/index.rst +20 -0
- docs/source/getting_started/formats/matpower.rst +183 -0
- docs/source/getting_started/formats/psse.rst +46 -0
- docs/source/getting_started/formats/pypower.rst +223 -0
- docs/source/getting_started/formats/xlsx.png +0 -0
- docs/source/getting_started/formats/xlsx.rst +23 -0
- docs/source/getting_started/index.rst +76 -0
- docs/source/getting_started/install.rst +231 -0
- docs/source/getting_started/overview.rst +26 -0
- docs/source/getting_started/testcase.rst +45 -0
- docs/source/getting_started/verification.rst +13 -0
- docs/source/images/curent.ico +0 -0
- docs/source/images/dcopf_time.png +0 -0
- docs/source/images/sponsors/CURENT_Logo_NameOnTrans.png +0 -0
- docs/source/images/sponsors/CURENT_Logo_Transparent.png +0 -0
- docs/source/images/sponsors/CURENT_Logo_Transparent_Name.png +0 -0
- docs/source/images/sponsors/doe.png +0 -0
- docs/source/index.rst +108 -0
- docs/source/modeling/example.rst +159 -0
- docs/source/modeling/index.rst +17 -0
- docs/source/modeling/model.rst +210 -0
- docs/source/modeling/routine.rst +122 -0
- docs/source/modeling/system.rst +51 -0
- docs/source/release-notes.rst +398 -0
- ltbams-1.0.2.dist-info/METADATA +215 -0
- ltbams-1.0.2.dist-info/RECORD +188 -0
- {ltbams-0.9.9.dist-info → ltbams-1.0.2.dist-info}/WHEEL +1 -1
- ltbams-1.0.2.dist-info/top_level.txt +3 -0
- tests/__init__.py +0 -0
- tests/test_1st_system.py +33 -0
- tests/test_addressing.py +40 -0
- tests/test_andes_mats.py +61 -0
- tests/test_case.py +266 -0
- tests/test_cli.py +34 -0
- tests/test_export_csv.py +89 -0
- tests/test_group.py +83 -0
- tests/test_interface.py +216 -0
- tests/test_io.py +32 -0
- tests/test_jumper.py +27 -0
- tests/test_known_good.py +267 -0
- tests/test_matp.py +437 -0
- tests/test_model.py +54 -0
- tests/test_omodel.py +119 -0
- tests/test_paths.py +22 -0
- tests/test_report.py +251 -0
- tests/test_repr.py +21 -0
- tests/test_routine.py +178 -0
- tests/test_rtn_dcopf.py +101 -0
- tests/test_rtn_dcpf.py +77 -0
- tests/test_rtn_ed.py +279 -0
- tests/test_rtn_pflow.py +219 -0
- tests/test_rtn_rted.py +273 -0
- tests/test_rtn_uc.py +248 -0
- tests/test_service.py +73 -0
- ltbams-0.9.9.dist-info/LICENSE +0 -692
- ltbams-0.9.9.dist-info/METADATA +0 -859
- ltbams-0.9.9.dist-info/RECORD +0 -14
- ltbams-0.9.9.dist-info/top_level.txt +0 -1
- {ltbams-0.9.9.dist-info → ltbams-1.0.2.dist-info}/entry_points.txt +0 -0
ams/pypower/make/pdv.py
ADDED
@@ -0,0 +1,506 @@
|
|
1
|
+
"""
|
2
|
+
Make partial derivatives matrices w.r.t. voltage.
|
3
|
+
"""
|
4
|
+
|
5
|
+
import logging # NOQA
|
6
|
+
|
7
|
+
import numpy as np # NOQA
|
8
|
+
import scipy.sparse as sp # NOQA
|
9
|
+
from scipy.sparse import csr_matrix as c_sparse # NOQA
|
10
|
+
|
11
|
+
from ams.pypower.idx import IDX # NOQA
|
12
|
+
|
13
|
+
logger = logging.getLogger(__name__)
|
14
|
+
|
15
|
+
|
16
|
+
def dSbus_dV(Ybus, V):
|
17
|
+
"""
|
18
|
+
Computes partial derivatives of power injection w.r.t. voltage.
|
19
|
+
|
20
|
+
Returns two matrices containing partial derivatives of the complex bus
|
21
|
+
power injections w.r.t voltage magnitude and voltage angle respectively
|
22
|
+
(for all buses). If C{Ybus} is a c_sparse matrix, the return values will be
|
23
|
+
also. The following explains the expressions used to form the matrices::
|
24
|
+
|
25
|
+
S = diag(V) * conj(Ibus) = diag(conj(Ibus)) * V
|
26
|
+
|
27
|
+
Partials of V & Ibus w.r.t. voltage magnitudes::
|
28
|
+
dV/dVm = diag(V / abs(V))
|
29
|
+
dI/dVm = Ybus * dV/dVm = Ybus * diag(V / abs(V))
|
30
|
+
|
31
|
+
Partials of V & Ibus w.r.t. voltage angles::
|
32
|
+
dV/dVa = j * diag(V)
|
33
|
+
dI/dVa = Ybus * dV/dVa = Ybus * j * diag(V)
|
34
|
+
|
35
|
+
Partials of S w.r.t. voltage magnitudes::
|
36
|
+
dS/dVm = diag(V) * conj(dI/dVm) + diag(conj(Ibus)) * dV/dVm
|
37
|
+
= diag(V) * conj(Ybus * diag(V / abs(V)))
|
38
|
+
+ conj(diag(Ibus)) * diag(V / abs(V))
|
39
|
+
|
40
|
+
Partials of S w.r.t. voltage angles::
|
41
|
+
dS/dVa = diag(V) * conj(dI/dVa) + diag(conj(Ibus)) * dV/dVa
|
42
|
+
= diag(V) * conj(Ybus * j * diag(V))
|
43
|
+
+ conj(diag(Ibus)) * j * diag(V)
|
44
|
+
= -j * diag(V) * conj(Ybus * diag(V))
|
45
|
+
+ conj(diag(Ibus)) * j * diag(V)
|
46
|
+
= j * diag(V) * conj(diag(Ibus) - Ybus * diag(V))
|
47
|
+
|
48
|
+
For more details on the derivations behind the derivative code used
|
49
|
+
in PYPOWER information, see:
|
50
|
+
|
51
|
+
[TN2] R. D. Zimmerman, "AC Power Flows, Generalized OPF Costs and
|
52
|
+
their Derivatives using Complex Matrix Notation", MATPOWER
|
53
|
+
Technical Note 2, February 2010.
|
54
|
+
U{http://www.pserc.cornell.edu/matpower/TN2-OPF-Derivatives.pdf}
|
55
|
+
|
56
|
+
@author: Ray Zimmerman (PSERC Cornell)
|
57
|
+
"""
|
58
|
+
ib = range(len(V))
|
59
|
+
|
60
|
+
if sp.issparse(Ybus):
|
61
|
+
Ibus = Ybus * V
|
62
|
+
|
63
|
+
diagV = c_sparse((V, (ib, ib)))
|
64
|
+
diagIbus = c_sparse((Ibus, (ib, ib)))
|
65
|
+
diagVnorm = c_sparse((V / abs(V), (ib, ib)))
|
66
|
+
else:
|
67
|
+
Ibus = Ybus * np.asmatrix(V).T
|
68
|
+
|
69
|
+
diagV = np.asmatrix(np.diag(V))
|
70
|
+
diagIbus = np.asmatrix(np.diag(np.asarray(Ibus).flatten()))
|
71
|
+
diagVnorm = np.asmatrix(np.diag(V / abs(V)))
|
72
|
+
|
73
|
+
dS_dVm = diagV * np.conj(Ybus * diagVnorm) + np.conj(diagIbus) * diagVnorm
|
74
|
+
dS_dVa = 1j * diagV * np.conj(diagIbus - Ybus * diagV)
|
75
|
+
|
76
|
+
return dS_dVm, dS_dVa
|
77
|
+
|
78
|
+
|
79
|
+
def dIbr_dV(branch, Yf, Yt, V):
|
80
|
+
"""Computes partial derivatives of branch currents w.r.t. voltage.
|
81
|
+
|
82
|
+
Returns four matrices containing partial derivatives of the complex
|
83
|
+
branch currents at "from" and "to" ends of each branch w.r.t voltage
|
84
|
+
magnitude and voltage angle respectively (for all buses). If C{Yf} is a
|
85
|
+
c_sparse matrix, the partial derivative matrices will be as well. Optionally
|
86
|
+
returns vectors containing the currents themselves. The following
|
87
|
+
explains the expressions used to form the matrices::
|
88
|
+
|
89
|
+
If = Yf * V
|
90
|
+
|
91
|
+
Partials of V, Vf & If w.r.t. voltage angles::
|
92
|
+
dV/dVa = j * diag(V)
|
93
|
+
dVf/dVa = c_sparse(range(nl), f, j*V(f)) = j * c_sparse(range(nl), f, V(f))
|
94
|
+
dIf/dVa = Yf * dV/dVa = Yf * j * diag(V)
|
95
|
+
|
96
|
+
Partials of V, Vf & If w.r.t. voltage magnitudes::
|
97
|
+
dV/dVm = diag(V / abs(V))
|
98
|
+
dVf/dVm = c_sparse(range(nl), f, V(f) / abs(V(f))
|
99
|
+
dIf/dVm = Yf * dV/dVm = Yf * diag(V / abs(V))
|
100
|
+
|
101
|
+
Derivations for "to" bus are similar.
|
102
|
+
|
103
|
+
@author: Ray Zimmerman (PSERC Cornell)
|
104
|
+
"""
|
105
|
+
i = range(len(V))
|
106
|
+
|
107
|
+
Vnorm = V / abs(V)
|
108
|
+
|
109
|
+
if sp.issparse(Yf):
|
110
|
+
diagV = c_sparse((V, (i, i)))
|
111
|
+
diagVnorm = c_sparse((Vnorm, (i, i)))
|
112
|
+
else:
|
113
|
+
diagV = np.asmatrix(np.diag(V))
|
114
|
+
diagVnorm = np.asmatrix(np.diag(Vnorm))
|
115
|
+
|
116
|
+
dIf_dVa = Yf * 1j * diagV
|
117
|
+
dIf_dVm = Yf * diagVnorm
|
118
|
+
dIt_dVa = Yt * 1j * diagV
|
119
|
+
dIt_dVm = Yt * diagVnorm
|
120
|
+
|
121
|
+
# Compute currents.
|
122
|
+
if sp.issparse(Yf):
|
123
|
+
If = Yf * V
|
124
|
+
It = Yt * V
|
125
|
+
else:
|
126
|
+
If = np.asarray(Yf * np.asmatrix(V).T).flatten()
|
127
|
+
It = np.asarray(Yt * np.asmatrix(V).T).flatten()
|
128
|
+
|
129
|
+
return dIf_dVa, dIf_dVm, dIt_dVa, dIt_dVm, If, It
|
130
|
+
|
131
|
+
|
132
|
+
def dSbr_dV(branch, Yf, Yt, V):
|
133
|
+
"""Computes partial derivatives of power flows w.r.t. voltage.
|
134
|
+
|
135
|
+
returns four matrices containing partial derivatives of the complex
|
136
|
+
branch power flows at "from" and "to" ends of each branch w.r.t voltage
|
137
|
+
magnitude and voltage angle respectively (for all buses). If C{Yf} is a
|
138
|
+
c_sparse matrix, the partial derivative matrices will be as well. Optionally
|
139
|
+
returns vectors containing the power flows themselves. The following
|
140
|
+
explains the expressions used to form the matrices::
|
141
|
+
|
142
|
+
If = Yf * V;
|
143
|
+
Sf = diag(Vf) * conj(If) = diag(conj(If)) * Vf
|
144
|
+
|
145
|
+
Partials of V, Vf & If w.r.t. voltage angles::
|
146
|
+
dV/dVa = j * diag(V)
|
147
|
+
dVf/dVa = c_sparse(range(nl), f, j*V(f)) = j * c_sparse(range(nl), f, V(f))
|
148
|
+
dIf/dVa = Yf * dV/dVa = Yf * j * diag(V)
|
149
|
+
|
150
|
+
Partials of V, Vf & If w.r.t. voltage magnitudes::
|
151
|
+
dV/dVm = diag(V / abs(V))
|
152
|
+
dVf/dVm = c_sparse(range(nl), f, V(f) / abs(V(f))
|
153
|
+
dIf/dVm = Yf * dV/dVm = Yf * diag(V / abs(V))
|
154
|
+
|
155
|
+
Partials of Sf w.r.t. voltage angles::
|
156
|
+
dSf/dVa = diag(Vf) * conj(dIf/dVa)
|
157
|
+
+ diag(conj(If)) * dVf/dVa
|
158
|
+
= diag(Vf) * conj(Yf * j * diag(V))
|
159
|
+
+ conj(diag(If)) * j * c_sparse(range(nl), f, V(f))
|
160
|
+
= -j * diag(Vf) * conj(Yf * diag(V))
|
161
|
+
+ j * conj(diag(If)) * c_sparse(range(nl), f, V(f))
|
162
|
+
= j * (conj(diag(If)) * c_sparse(range(nl), f, V(f))
|
163
|
+
- diag(Vf) * conj(Yf * diag(V)))
|
164
|
+
|
165
|
+
Partials of Sf w.r.t. voltage magnitudes::
|
166
|
+
dSf/dVm = diag(Vf) * conj(dIf/dVm)
|
167
|
+
+ diag(conj(If)) * dVf/dVm
|
168
|
+
= diag(Vf) * conj(Yf * diag(V / abs(V)))
|
169
|
+
+ conj(diag(If)) * c_sparse(range(nl), f, V(f)/abs(V(f)))
|
170
|
+
|
171
|
+
Derivations for "to" bus are similar.
|
172
|
+
|
173
|
+
For more details on the derivations behind the derivative code used
|
174
|
+
in PYPOWER information, see:
|
175
|
+
|
176
|
+
[TN2] R. D. Zimmerman, "AC Power Flows, Generalized OPF Costs and
|
177
|
+
their Derivatives using Complex Matrix Notation", MATPOWER
|
178
|
+
Technical Note 2, February 2010.
|
179
|
+
U{http://www.pserc.cornell.edu/matpower/TN2-OPF-Derivatives.pdf}
|
180
|
+
|
181
|
+
@author: Ray Zimmerman (PSERC Cornell)
|
182
|
+
"""
|
183
|
+
# define
|
184
|
+
f = branch[:, IDX.branch.F_BUS].astype(int) # list of "from" buses
|
185
|
+
t = branch[:, IDX.branch.T_BUS].astype(int) # list of "to" buses
|
186
|
+
nl = len(f)
|
187
|
+
nb = len(V)
|
188
|
+
il = np.arange(nl)
|
189
|
+
ib = np.arange(nb)
|
190
|
+
|
191
|
+
Vnorm = V / abs(V)
|
192
|
+
|
193
|
+
if sp.issparse(Yf):
|
194
|
+
# compute currents
|
195
|
+
If = Yf * V
|
196
|
+
It = Yt * V
|
197
|
+
|
198
|
+
diagVf = c_sparse((V[f], (il, il)))
|
199
|
+
diagIf = c_sparse((If, (il, il)))
|
200
|
+
diagVt = c_sparse((V[t], (il, il)))
|
201
|
+
diagIt = c_sparse((It, (il, il)))
|
202
|
+
diagV = c_sparse((V, (ib, ib)))
|
203
|
+
diagVnorm = c_sparse((Vnorm, (ib, ib)))
|
204
|
+
|
205
|
+
shape = (nl, nb)
|
206
|
+
# Partial derivative of S w.r.t voltage phase angle.
|
207
|
+
dSf_dVa = 1j * (np.conj(diagIf) *
|
208
|
+
c_sparse((V[f], (il, f)), shape) - diagVf * np.conj(Yf * diagV))
|
209
|
+
|
210
|
+
dSt_dVa = 1j * (np.conj(diagIt) *
|
211
|
+
c_sparse((V[t], (il, t)), shape) - diagVt * np.conj(Yt * diagV))
|
212
|
+
|
213
|
+
# Partial derivative of S w.r.t. voltage amplitude.
|
214
|
+
dSf_dVm = diagVf * np.conj(Yf * diagVnorm) + np.conj(diagIf) * \
|
215
|
+
c_sparse((Vnorm[f], (il, f)), shape)
|
216
|
+
|
217
|
+
dSt_dVm = diagVt * np.conj(Yt * diagVnorm) + np.conj(diagIt) * \
|
218
|
+
c_sparse((Vnorm[t], (il, t)), shape)
|
219
|
+
else: # dense version
|
220
|
+
# compute currents
|
221
|
+
If = np.asarray(Yf * np.asmatrix(V).T).flatten()
|
222
|
+
It = np.asarray(Yt * np.asmatrix(V).T).flatten()
|
223
|
+
|
224
|
+
diagVf = np.asmatrix(np.diag(V[f]))
|
225
|
+
diagIf = np.asmatrix(np.diag(If))
|
226
|
+
diagVt = np.asmatrix(np.diag(V[t]))
|
227
|
+
diagIt = np.asmatrix(np.diag(It))
|
228
|
+
diagV = np.asmatrix(np.diag(V))
|
229
|
+
diagVnorm = np.asmatrix(np.diag(Vnorm))
|
230
|
+
temp1 = np.asmatrix(np.zeros((nl, nb), complex))
|
231
|
+
temp2 = np.asmatrix(np.zeros((nl, nb), complex))
|
232
|
+
temp3 = np.asmatrix(np.zeros((nl, nb), complex))
|
233
|
+
temp4 = np.asmatrix(np.zeros((nl, nb), complex))
|
234
|
+
for i in range(nl):
|
235
|
+
fi, ti = f[i], t[i]
|
236
|
+
temp1[i, fi] = V[fi].item()
|
237
|
+
temp2[i, fi] = Vnorm[fi].item()
|
238
|
+
temp3[i, ti] = V[ti].item()
|
239
|
+
temp4[i, ti] = Vnorm[ti].item()
|
240
|
+
|
241
|
+
dSf_dVa = 1j * (np.conj(diagIf) * temp1 - diagVf * np.conj(Yf * diagV))
|
242
|
+
dSf_dVm = diagVf * np.conj(Yf * diagVnorm) + np.conj(diagIf) * temp2
|
243
|
+
dSt_dVa = 1j * (np.conj(diagIt) * temp3 - diagVt * np.conj(Yt * diagV))
|
244
|
+
dSt_dVm = diagVt * np.conj(Yt * diagVnorm) + np.conj(diagIt) * temp4
|
245
|
+
|
246
|
+
# Compute power flow vectors.
|
247
|
+
Sf = V[f] * np.conj(If)
|
248
|
+
St = V[t] * np.conj(It)
|
249
|
+
|
250
|
+
return dSf_dVa, dSf_dVm, dSt_dVa, dSt_dVm, Sf, St
|
251
|
+
|
252
|
+
|
253
|
+
def d2Sbus_dV2(Ybus, V, lam):
|
254
|
+
"""Computes 2nd derivatives of power injection w.r.t. voltage.
|
255
|
+
|
256
|
+
Returns 4 matrices containing the partial derivatives w.r.t. voltage angle
|
257
|
+
and magnitude of the product of a vector C{lam} with the 1st partial
|
258
|
+
derivatives of the complex bus power injections. Takes sparse bus
|
259
|
+
admittance matrix C{Ybus}, voltage vector C{V} and C{nb x 1} vector of
|
260
|
+
multipliers C{lam}. Output matrices are sparse.
|
261
|
+
|
262
|
+
For more details on the derivations behind the derivative code used
|
263
|
+
in PYPOWER information, see:
|
264
|
+
|
265
|
+
[TN2] R. D. Zimmerman, I{"AC Power Flows, Generalized OPF Costs and
|
266
|
+
their Derivatives using Complex Matrix Notation"}, MATPOWER
|
267
|
+
Technical Note 2, February 2010.
|
268
|
+
U{http://www.pserc.cornell.edu/matpower/TN2-OPF-Derivatives.pdf}
|
269
|
+
|
270
|
+
@author: Ray Zimmerman (PSERC Cornell)
|
271
|
+
"""
|
272
|
+
nb = len(V)
|
273
|
+
ib = np.arange(nb)
|
274
|
+
Ibus = Ybus * V
|
275
|
+
diaglam = c_sparse((lam, (ib, ib)))
|
276
|
+
diagV = c_sparse((V, (ib, ib)))
|
277
|
+
|
278
|
+
A = c_sparse((lam * V, (ib, ib)))
|
279
|
+
B = Ybus * diagV
|
280
|
+
C = A * np.conj(B)
|
281
|
+
D = Ybus.getH() * diagV
|
282
|
+
E = diagV.conj() * (D * diaglam - c_sparse((D * lam, (ib, ib))))
|
283
|
+
F = C - A * c_sparse((np.conj(Ibus), (ib, ib)))
|
284
|
+
G = c_sparse((np.ones(nb) / abs(V), (ib, ib)))
|
285
|
+
|
286
|
+
Gaa = E + F
|
287
|
+
Gva = 1j * G * (E - F)
|
288
|
+
Gav = Gva.T
|
289
|
+
Gvv = G * (C + C.T) * G
|
290
|
+
|
291
|
+
return Gaa, Gav, Gva, Gvv
|
292
|
+
|
293
|
+
|
294
|
+
def d2AIbr_dV2(dIbr_dVa, dIbr_dVm, Ibr, Ybr, V, lam):
|
295
|
+
"""Computes 2nd derivatives of |complex current|**2 w.r.t. V.
|
296
|
+
|
297
|
+
Returns 4 matrices containing the partial derivatives w.r.t. voltage
|
298
|
+
angle and magnitude of the product of a vector C{lam} with the 1st partial
|
299
|
+
derivatives of the square of the magnitude of the branch currents.
|
300
|
+
Takes sparse first derivative matrices of complex flow, complex flow
|
301
|
+
vector, sparse branch admittance matrix C{Ybr}, voltage vector C{V} and
|
302
|
+
C{nl x 1} vector of multipliers C{lam}. Output matrices are sparse.
|
303
|
+
|
304
|
+
For more details on the derivations behind the derivative code used
|
305
|
+
in PYPOWER information, see:
|
306
|
+
|
307
|
+
[TN2] R. D. Zimmerman, I{"AC Power Flows, Generalized OPF Costs and
|
308
|
+
their Derivatives using Complex Matrix Notation"}, MATPOWER
|
309
|
+
Technical Note 2, February 2010.
|
310
|
+
U{http://www.pserc.cornell.edu/matpower/TN2-OPF-Derivatives.pdf}
|
311
|
+
|
312
|
+
@see: L{dIbr_dV}.
|
313
|
+
|
314
|
+
@author: Ray Zimmerman (PSERC Cornell)
|
315
|
+
"""
|
316
|
+
# define
|
317
|
+
il = range(len(lam))
|
318
|
+
|
319
|
+
diaglam = c_sparse((lam, (il, il)))
|
320
|
+
diagIbr_conj = c_sparse((Ibr.conj(), (il, il)))
|
321
|
+
|
322
|
+
Iaa, Iav, Iva, Ivv = d2Ibr_dV2(Ybr, V, diagIbr_conj * lam)
|
323
|
+
|
324
|
+
Haa = 2 * (Iaa + dIbr_dVa.T * diaglam * dIbr_dVa.conj()).real
|
325
|
+
Hva = 2 * (Iva + dIbr_dVm.T * diaglam * dIbr_dVa.conj()).real
|
326
|
+
Hav = 2 * (Iav + dIbr_dVa.T * diaglam * dIbr_dVm.conj()).real
|
327
|
+
Hvv = 2 * (Ivv + dIbr_dVm.T * diaglam * dIbr_dVm.conj()).real
|
328
|
+
|
329
|
+
return Haa, Hav, Hva, Hvv
|
330
|
+
|
331
|
+
|
332
|
+
def d2ASbr_dV2(dSbr_dVa, dSbr_dVm, Sbr, Cbr, Ybr, V, lam):
|
333
|
+
"""Computes 2nd derivatives of |complex power flow|**2 w.r.t. V.
|
334
|
+
|
335
|
+
Returns 4 matrices containing the partial derivatives w.r.t. voltage
|
336
|
+
angle and magnitude of the product of a vector C{lam} with the 1st partial
|
337
|
+
derivatives of the square of the magnitude of branch complex power flows.
|
338
|
+
Takes sparse first derivative matrices of complex flow, complex flow
|
339
|
+
vector, sparse connection matrix C{Cbr}, sparse branch admittance matrix
|
340
|
+
C{Ybr}, voltage vector C{V} and C{nl x 1} vector of multipliers C{lam}.
|
341
|
+
Output matrices are sparse.
|
342
|
+
|
343
|
+
For more details on the derivations behind the derivative code used
|
344
|
+
in PYPOWER information, see:
|
345
|
+
|
346
|
+
[TN2] R. D. Zimmerman, I{"AC Power Flows, Generalized OPF Costs and
|
347
|
+
their Derivatives using Complex Matrix Notation"}, MATPOWER
|
348
|
+
Technical Note 2, February 2010.
|
349
|
+
U{http://www.pserc.cornell.edu/matpower/TN2-OPF-Derivatives.pdf}
|
350
|
+
|
351
|
+
@see: L{dSbr_dV}
|
352
|
+
|
353
|
+
@author: Ray Zimmerman (PSERC Cornell)
|
354
|
+
"""
|
355
|
+
il = range(len(lam))
|
356
|
+
|
357
|
+
diaglam = c_sparse((lam, (il, il)))
|
358
|
+
diagSbr_conj = c_sparse((Sbr.conj(), (il, il)))
|
359
|
+
|
360
|
+
Saa, Sav, Sva, Svv = d2Sbr_dV2(Cbr, Ybr, V, diagSbr_conj * lam)
|
361
|
+
|
362
|
+
Haa = 2 * (Saa + dSbr_dVa.T * diaglam * dSbr_dVa.conj()).real
|
363
|
+
Hva = 2 * (Sva + dSbr_dVm.T * diaglam * dSbr_dVa.conj()).real
|
364
|
+
Hav = 2 * (Sav + dSbr_dVa.T * diaglam * dSbr_dVm.conj()).real
|
365
|
+
Hvv = 2 * (Svv + dSbr_dVm.T * diaglam * dSbr_dVm.conj()).real
|
366
|
+
|
367
|
+
return Haa, Hav, Hva, Hvv
|
368
|
+
|
369
|
+
|
370
|
+
def d2Ibr_dV2(Ybr, V, lam):
|
371
|
+
"""Computes 2nd derivatives of complex branch current w.r.t. voltage.
|
372
|
+
|
373
|
+
Returns 4 matrices containing the partial derivatives w.r.t. voltage
|
374
|
+
angle and magnitude of the product of a vector LAM with the 1st partial
|
375
|
+
derivatives of the complex branch currents. Takes sparse branch admittance
|
376
|
+
matrix C{Ybr}, voltage vector C{V} and C{nl x 1} vector of multipliers
|
377
|
+
C{lam}. Output matrices are sparse.
|
378
|
+
|
379
|
+
For more details on the derivations behind the derivative code used
|
380
|
+
in PYPOWER information, see:
|
381
|
+
|
382
|
+
[TN2] R. D. Zimmerman, I{"AC Power Flows, Generalized OPF Costs and
|
383
|
+
their Derivatives using Complex Matrix Notation"}, MATPOWER
|
384
|
+
Technical Note 2, February 2010.
|
385
|
+
U{http://www.pserc.cornell.edu/matpower/TN2-OPF-Derivatives.pdf}
|
386
|
+
|
387
|
+
@author: Ray Zimmerman (PSERC Cornell)
|
388
|
+
"""
|
389
|
+
nb = len(V)
|
390
|
+
ib = np.arange(nb)
|
391
|
+
diaginvVm = c_sparse((np.ones(nb) / abs(V), (ib, ib)))
|
392
|
+
|
393
|
+
Haa = c_sparse((-(Ybr.T * lam) * V, (ib, ib)))
|
394
|
+
Hva = -1j * Haa * diaginvVm
|
395
|
+
Hav = Hva.copy()
|
396
|
+
Hvv = c_sparse((nb, nb))
|
397
|
+
|
398
|
+
return Haa, Hav, Hva, Hvv
|
399
|
+
|
400
|
+
|
401
|
+
def d2Sbr_dV2(Cbr, Ybr, V, lam):
|
402
|
+
"""Computes 2nd derivatives of complex power flow w.r.t. voltage.
|
403
|
+
|
404
|
+
Returns 4 matrices containing the partial derivatives w.r.t. voltage angle
|
405
|
+
and magnitude of the product of a vector C{lam} with the 1st partial
|
406
|
+
derivatives of the complex branch power flows. Takes sparse connection
|
407
|
+
matrix C{Cbr}, sparse branch admittance matrix C{Ybr}, voltage vector C{V}
|
408
|
+
and C{nl x 1} vector of multipliers C{lam}. Output matrices are sparse.
|
409
|
+
|
410
|
+
For more details on the derivations behind the derivative code used
|
411
|
+
in PYPOWER information, see:
|
412
|
+
|
413
|
+
[TN2] R. D. Zimmerman, I{"AC Power Flows, Generalized OPF Costs and
|
414
|
+
their Derivatives using Complex Matrix Notation"}, MATPOWER
|
415
|
+
Technical Note 2, February 2010.
|
416
|
+
U{http://www.pserc.cornell.edu/matpower/TN2-OPF-Derivatives.pdf}
|
417
|
+
|
418
|
+
@author: Ray Zimmerman (PSERC Cornell)
|
419
|
+
"""
|
420
|
+
nb = len(V)
|
421
|
+
nl = len(lam)
|
422
|
+
ib = range(nb)
|
423
|
+
il = range(nl)
|
424
|
+
|
425
|
+
diaglam = c_sparse((lam, (il, il)))
|
426
|
+
diagV = c_sparse((V, (ib, ib)))
|
427
|
+
|
428
|
+
A = Ybr.getH() * diaglam * Cbr
|
429
|
+
B = np.conj(diagV) * A * diagV
|
430
|
+
D = c_sparse(((A * V) * np.conj(V), (ib, ib)))
|
431
|
+
E = c_sparse(((A.T * np.conj(V) * V), (ib, ib)))
|
432
|
+
F = B + B.T
|
433
|
+
G = c_sparse((np.ones(nb) / abs(V), (ib, ib)))
|
434
|
+
|
435
|
+
Haa = F - D - E
|
436
|
+
Hva = 1j * G * (B - B.T - D + E)
|
437
|
+
Hav = Hva.T
|
438
|
+
Hvv = G * F * G
|
439
|
+
|
440
|
+
return Haa, Hav, Hva, Hvv
|
441
|
+
|
442
|
+
|
443
|
+
def dAbr_dV(dSf_dVa, dSf_dVm, dSt_dVa, dSt_dVm, Sf, St):
|
444
|
+
"""Partial derivatives of squared flow magnitudes w.r.t voltage.
|
445
|
+
|
446
|
+
Returns four matrices containing partial derivatives of the square of
|
447
|
+
the branch flow magnitudes at "from" & "to" ends of each branch w.r.t
|
448
|
+
voltage magnitude and voltage angle respectively (for all buses), given
|
449
|
+
the flows and flow sensitivities. Flows could be complex current or
|
450
|
+
complex or real power. Notation below is based on complex power. The
|
451
|
+
following explains the expressions used to form the matrices:
|
452
|
+
|
453
|
+
Let Af refer to the square of the apparent power at the "from" end of
|
454
|
+
each branch::
|
455
|
+
|
456
|
+
Af = abs(Sf)**2
|
457
|
+
= Sf .* conj(Sf)
|
458
|
+
= Pf**2 + Qf**2
|
459
|
+
|
460
|
+
then ...
|
461
|
+
|
462
|
+
Partial w.r.t real power::
|
463
|
+
dAf/dPf = 2 * diag(Pf)
|
464
|
+
|
465
|
+
Partial w.r.t reactive power::
|
466
|
+
dAf/dQf = 2 * diag(Qf)
|
467
|
+
|
468
|
+
Partial w.r.t Vm & Va::
|
469
|
+
dAf/dVm = dAf/dPf * dPf/dVm + dAf/dQf * dQf/dVm
|
470
|
+
dAf/dVa = dAf/dPf * dPf/dVa + dAf/dQf * dQf/dVa
|
471
|
+
|
472
|
+
Derivations for "to" bus are similar.
|
473
|
+
|
474
|
+
For more details on the derivations behind the derivative code used
|
475
|
+
in PYPOWER information, see:
|
476
|
+
|
477
|
+
[TN2] R. D. Zimmerman, I{"AC Power Flows, Generalized OPF Costs and
|
478
|
+
their Derivatives using Complex Matrix Notation"}, MATPOWER
|
479
|
+
Technical Note 2, February 2010.
|
480
|
+
U{http://www.pserc.cornell.edu/matpower/TN2-OPF-Derivatives.pdf}
|
481
|
+
|
482
|
+
@return: The partial derivatives of the squared flow magnitudes w.r.t
|
483
|
+
voltage magnitude and voltage angle given the flows and flow
|
484
|
+
sensitivities. Flows could be complex current or complex or
|
485
|
+
real power.
|
486
|
+
@see: L{dIbr_dV}, L{dSbr_dV}
|
487
|
+
|
488
|
+
@author: Ray Zimmerman (PSERC Cornell)
|
489
|
+
"""
|
490
|
+
il = range(len(Sf))
|
491
|
+
|
492
|
+
dAf_dPf = c_sparse((2 * Sf.real, (il, il)))
|
493
|
+
dAf_dQf = c_sparse((2 * Sf.imag, (il, il)))
|
494
|
+
dAt_dPt = c_sparse((2 * St.real, (il, il)))
|
495
|
+
dAt_dQt = c_sparse((2 * St.imag, (il, il)))
|
496
|
+
|
497
|
+
# Partial derivative of apparent power magnitude w.r.t voltage
|
498
|
+
# phase angle.
|
499
|
+
dAf_dVa = dAf_dPf * dSf_dVa.real + dAf_dQf * dSf_dVa.imag
|
500
|
+
dAt_dVa = dAt_dPt * dSt_dVa.real + dAt_dQt * dSt_dVa.imag
|
501
|
+
# Partial derivative of apparent power magnitude w.r.t. voltage
|
502
|
+
# amplitude.
|
503
|
+
dAf_dVm = dAf_dPf * dSf_dVm.real + dAf_dQf * dSf_dVm.imag
|
504
|
+
dAt_dVm = dAt_dPt * dSt_dVm.real + dAt_dQt * dSt_dVm.imag
|
505
|
+
|
506
|
+
return dAf_dVa, dAf_dVm, dAt_dVa, dAt_dVm
|