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.
Files changed (191) hide show
  1. ams/__init__.py +4 -11
  2. ams/_version.py +3 -3
  3. ams/cases/5bus/pjm5bus_demo.xlsx +0 -0
  4. ams/cases/5bus/pjm5bus_jumper.xlsx +0 -0
  5. ams/cases/5bus/pjm5bus_uced.json +1062 -0
  6. ams/cases/5bus/pjm5bus_uced.xlsx +0 -0
  7. ams/cases/5bus/pjm5bus_uced_esd1.xlsx +0 -0
  8. ams/cases/5bus/pjm5bus_uced_ev.xlsx +0 -0
  9. ams/cases/ieee123/ieee123.xlsx +0 -0
  10. ams/cases/ieee123/ieee123_regcv1.xlsx +0 -0
  11. ams/cases/ieee14/ieee14.json +1166 -0
  12. ams/cases/ieee14/ieee14.raw +92 -0
  13. ams/cases/ieee14/ieee14_conn.xlsx +0 -0
  14. ams/cases/ieee14/ieee14_uced.xlsx +0 -0
  15. ams/cases/ieee39/ieee39.xlsx +0 -0
  16. ams/cases/ieee39/ieee39_uced.xlsx +0 -0
  17. ams/cases/ieee39/ieee39_uced_esd1.xlsx +0 -0
  18. ams/cases/ieee39/ieee39_uced_pvd1.xlsx +0 -0
  19. ams/cases/ieee39/ieee39_uced_vis.xlsx +0 -0
  20. ams/cases/matpower/benchmark.json +1594 -0
  21. ams/cases/matpower/case118.m +787 -0
  22. ams/cases/matpower/case14.m +129 -0
  23. ams/cases/matpower/case300.m +1315 -0
  24. ams/cases/matpower/case39.m +205 -0
  25. ams/cases/matpower/case5.m +62 -0
  26. ams/cases/matpower/case_ACTIVSg2000.m +9460 -0
  27. ams/cases/npcc/npcc.m +644 -0
  28. ams/cases/npcc/npcc_uced.xlsx +0 -0
  29. ams/cases/pglib/pglib_opf_case39_epri__api.m +243 -0
  30. ams/cases/wecc/wecc.m +714 -0
  31. ams/cases/wecc/wecc_uced.xlsx +0 -0
  32. ams/cli.py +6 -0
  33. ams/core/__init__.py +2 -0
  34. ams/core/documenter.py +652 -0
  35. ams/core/matprocessor.py +782 -0
  36. ams/core/model.py +330 -0
  37. ams/core/param.py +322 -0
  38. ams/core/service.py +918 -0
  39. ams/core/symprocessor.py +224 -0
  40. ams/core/var.py +59 -0
  41. ams/extension/__init__.py +5 -0
  42. ams/extension/eva.py +401 -0
  43. ams/interface.py +1085 -0
  44. ams/io/__init__.py +133 -0
  45. ams/io/json.py +82 -0
  46. ams/io/matpower.py +406 -0
  47. ams/io/psse.py +6 -0
  48. ams/io/pypower.py +103 -0
  49. ams/io/xlsx.py +80 -0
  50. ams/main.py +81 -4
  51. ams/models/__init__.py +24 -0
  52. ams/models/area.py +40 -0
  53. ams/models/bus.py +52 -0
  54. ams/models/cost.py +169 -0
  55. ams/models/distributed/__init__.py +3 -0
  56. ams/models/distributed/esd1.py +71 -0
  57. ams/models/distributed/ev.py +60 -0
  58. ams/models/distributed/pvd1.py +67 -0
  59. ams/models/group.py +231 -0
  60. ams/models/info.py +26 -0
  61. ams/models/line.py +238 -0
  62. ams/models/renewable/__init__.py +5 -0
  63. ams/models/renewable/regc.py +119 -0
  64. ams/models/reserve.py +94 -0
  65. ams/models/shunt.py +14 -0
  66. ams/models/static/__init__.py +2 -0
  67. ams/models/static/gen.py +165 -0
  68. ams/models/static/pq.py +61 -0
  69. ams/models/timeslot.py +69 -0
  70. ams/models/zone.py +49 -0
  71. ams/opt/__init__.py +12 -0
  72. ams/opt/constraint.py +175 -0
  73. ams/opt/exprcalc.py +127 -0
  74. ams/opt/expression.py +188 -0
  75. ams/opt/objective.py +174 -0
  76. ams/opt/omodel.py +432 -0
  77. ams/opt/optzbase.py +192 -0
  78. ams/opt/param.py +156 -0
  79. ams/opt/var.py +233 -0
  80. ams/pypower/__init__.py +8 -0
  81. ams/pypower/_compat.py +9 -0
  82. ams/pypower/core/__init__.py +8 -0
  83. ams/pypower/core/pips.py +894 -0
  84. ams/pypower/core/ppoption.py +244 -0
  85. ams/pypower/core/ppver.py +18 -0
  86. ams/pypower/core/solver.py +2451 -0
  87. ams/pypower/eps.py +6 -0
  88. ams/pypower/idx.py +174 -0
  89. ams/pypower/io.py +604 -0
  90. ams/pypower/make/__init__.py +11 -0
  91. ams/pypower/make/matrices.py +665 -0
  92. ams/pypower/make/pdv.py +506 -0
  93. ams/pypower/routines/__init__.py +7 -0
  94. ams/pypower/routines/cpf.py +513 -0
  95. ams/pypower/routines/cpf_callbacks.py +114 -0
  96. ams/pypower/routines/opf.py +1803 -0
  97. ams/pypower/routines/opffcns.py +1946 -0
  98. ams/pypower/routines/pflow.py +852 -0
  99. ams/pypower/toggle.py +1098 -0
  100. ams/pypower/utils.py +293 -0
  101. ams/report.py +212 -50
  102. ams/routines/__init__.py +23 -0
  103. ams/routines/acopf.py +117 -0
  104. ams/routines/cpf.py +65 -0
  105. ams/routines/dcopf.py +241 -0
  106. ams/routines/dcpf.py +209 -0
  107. ams/routines/dcpf0.py +196 -0
  108. ams/routines/dopf.py +150 -0
  109. ams/routines/ed.py +312 -0
  110. ams/routines/pflow.py +255 -0
  111. ams/routines/pflow0.py +113 -0
  112. ams/routines/routine.py +1033 -0
  113. ams/routines/rted.py +519 -0
  114. ams/routines/type.py +160 -0
  115. ams/routines/uc.py +376 -0
  116. ams/shared.py +63 -9
  117. ams/system.py +61 -22
  118. ams/utils/__init__.py +3 -0
  119. ams/utils/misc.py +77 -0
  120. ams/utils/paths.py +257 -0
  121. docs/Makefile +21 -0
  122. docs/make.bat +35 -0
  123. docs/source/_templates/autosummary/base.rst +5 -0
  124. docs/source/_templates/autosummary/class.rst +35 -0
  125. docs/source/_templates/autosummary/module.rst +65 -0
  126. docs/source/_templates/autosummary/module_toctree.rst +66 -0
  127. docs/source/api.rst +102 -0
  128. docs/source/conf.py +206 -0
  129. docs/source/examples/index.rst +34 -0
  130. docs/source/genmodelref.py +61 -0
  131. docs/source/genroutineref.py +47 -0
  132. docs/source/getting_started/copyright.rst +20 -0
  133. docs/source/getting_started/formats/index.rst +20 -0
  134. docs/source/getting_started/formats/matpower.rst +183 -0
  135. docs/source/getting_started/formats/psse.rst +46 -0
  136. docs/source/getting_started/formats/pypower.rst +223 -0
  137. docs/source/getting_started/formats/xlsx.png +0 -0
  138. docs/source/getting_started/formats/xlsx.rst +23 -0
  139. docs/source/getting_started/index.rst +76 -0
  140. docs/source/getting_started/install.rst +231 -0
  141. docs/source/getting_started/overview.rst +26 -0
  142. docs/source/getting_started/testcase.rst +45 -0
  143. docs/source/getting_started/verification.rst +13 -0
  144. docs/source/images/curent.ico +0 -0
  145. docs/source/images/dcopf_time.png +0 -0
  146. docs/source/images/sponsors/CURENT_Logo_NameOnTrans.png +0 -0
  147. docs/source/images/sponsors/CURENT_Logo_Transparent.png +0 -0
  148. docs/source/images/sponsors/CURENT_Logo_Transparent_Name.png +0 -0
  149. docs/source/images/sponsors/doe.png +0 -0
  150. docs/source/index.rst +108 -0
  151. docs/source/modeling/example.rst +159 -0
  152. docs/source/modeling/index.rst +17 -0
  153. docs/source/modeling/model.rst +210 -0
  154. docs/source/modeling/routine.rst +122 -0
  155. docs/source/modeling/system.rst +51 -0
  156. docs/source/release-notes.rst +398 -0
  157. ltbams-1.0.2.dist-info/METADATA +215 -0
  158. ltbams-1.0.2.dist-info/RECORD +188 -0
  159. {ltbams-0.9.9.dist-info → ltbams-1.0.2.dist-info}/WHEEL +1 -1
  160. ltbams-1.0.2.dist-info/top_level.txt +3 -0
  161. tests/__init__.py +0 -0
  162. tests/test_1st_system.py +33 -0
  163. tests/test_addressing.py +40 -0
  164. tests/test_andes_mats.py +61 -0
  165. tests/test_case.py +266 -0
  166. tests/test_cli.py +34 -0
  167. tests/test_export_csv.py +89 -0
  168. tests/test_group.py +83 -0
  169. tests/test_interface.py +216 -0
  170. tests/test_io.py +32 -0
  171. tests/test_jumper.py +27 -0
  172. tests/test_known_good.py +267 -0
  173. tests/test_matp.py +437 -0
  174. tests/test_model.py +54 -0
  175. tests/test_omodel.py +119 -0
  176. tests/test_paths.py +22 -0
  177. tests/test_report.py +251 -0
  178. tests/test_repr.py +21 -0
  179. tests/test_routine.py +178 -0
  180. tests/test_rtn_dcopf.py +101 -0
  181. tests/test_rtn_dcpf.py +77 -0
  182. tests/test_rtn_ed.py +279 -0
  183. tests/test_rtn_pflow.py +219 -0
  184. tests/test_rtn_rted.py +273 -0
  185. tests/test_rtn_uc.py +248 -0
  186. tests/test_service.py +73 -0
  187. ltbams-0.9.9.dist-info/LICENSE +0 -692
  188. ltbams-0.9.9.dist-info/METADATA +0 -859
  189. ltbams-0.9.9.dist-info/RECORD +0 -14
  190. ltbams-0.9.9.dist-info/top_level.txt +0 -1
  191. {ltbams-0.9.9.dist-info → ltbams-1.0.2.dist-info}/entry_points.txt +0 -0
ams/pypower/io.py ADDED
@@ -0,0 +1,604 @@
1
+ """
2
+ Save and load PYPOWER cases.
3
+ """
4
+
5
+ import logging
6
+ from copy import deepcopy
7
+
8
+ from os.path import basename, splitext, exists
9
+
10
+ from numpy import array, zeros, ones, c_
11
+
12
+ from scipy.io import loadmat, savemat
13
+
14
+
15
+ from sys import stderr
16
+
17
+ from os.path import basename
18
+
19
+ from numpy import array, c_, r_, any
20
+
21
+ from ams.pypower.routines.opffcns import run_userfcn
22
+
23
+ from ams.pypower.idx import IDX
24
+
25
+
26
+ logger = logging.getLogger(__name__)
27
+
28
+
29
+ def loadcase(casefile,
30
+ return_as_obj=True, expect_gencost=True, expect_areas=True):
31
+ """Returns the individual data matrices or an dict containing them
32
+ as values.
33
+
34
+ Here C{casefile} is either a dict containing the keys C{baseMVA}, C{bus},
35
+ C{gen}, C{branch}, C{areas}, C{gencost}, or a string containing the name
36
+ of the file. If C{casefile} contains the extension '.mat' or '.py', then
37
+ the explicit file is searched. If C{casefile} containts no extension, then
38
+ L{loadcase} looks for a '.mat' file first, then for a '.py' file. If the
39
+ file does not exist or doesn't define all matrices, the function returns
40
+ an exit code as follows:
41
+
42
+ 0. all variables successfully defined
43
+ 1. input argument is not a string or dict
44
+ 2. specified extension-less file name does not exist
45
+ 3. specified .mat file does not exist
46
+ 4. specified .py file does not exist
47
+ 5. specified file fails to define all matrices or contains syntax
48
+ error
49
+
50
+ If the input data is not a dict containing a 'version' key, it is
51
+ assumed to be a PYPOWER case file in version 1 format, and will be
52
+ converted to version 2 format.
53
+
54
+ @author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
55
+ Autonoma de Manizales)
56
+ @author: Ray Zimmerman (PSERC Cornell)
57
+ """
58
+ if return_as_obj == True:
59
+ expect_gencost = False
60
+ expect_areas = False
61
+
62
+ info = 0
63
+
64
+ # read data into case object
65
+ if isinstance(casefile, str):
66
+ lasterr = ''
67
+ # check for explicit extension
68
+ if casefile.endswith(('.py', '.mat')):
69
+ rootname, extension = splitext(casefile)
70
+ fname = basename(rootname)
71
+ else:
72
+ # set extension if not specified explicitly
73
+ rootname = casefile
74
+ if exists(casefile + '.mat'):
75
+ extension = '.mat'
76
+ elif exists(casefile + '.py'):
77
+ extension = '.py'
78
+ else:
79
+ info = 2
80
+ fname = basename(rootname)
81
+
82
+ # attempt to read file
83
+ if info == 0:
84
+ if extension == '.mat': # from MAT file
85
+ try:
86
+ d = loadmat(rootname + extension, struct_as_record=True)
87
+ if 'ppc' in d or 'mpc' in d: # it's a MAT/PYPOWER dict
88
+ if 'ppc' in d:
89
+ struct = d['ppc']
90
+ else:
91
+ struct = d['mpc']
92
+ val = struct[0, 0]
93
+
94
+ s = {}
95
+ for a in val.dtype.names:
96
+ s[a] = val[a]
97
+ else: # individual data matrices
98
+ d['version'] = '1'
99
+
100
+ s = {}
101
+ for k, v in d.items():
102
+ s[k] = v
103
+
104
+ s['baseMVA'] = s['baseMVA'][0] # convert array to float
105
+
106
+ except IOError as e:
107
+ info = 3
108
+ lasterr = str(e)
109
+ elif extension == '.py': # from Python file
110
+ try:
111
+ if PY2:
112
+ execfile(rootname + extension)
113
+ else:
114
+ exec(compile(open(rootname + extension).read(),
115
+ rootname + extension, 'exec'))
116
+
117
+ try: # assume it returns an object
118
+ s = eval(fname)()
119
+ except ValueError as e:
120
+ info = 4
121
+ lasterr = str(e)
122
+ # if not try individual data matrices
123
+ if info == 0 and not isinstance(s, dict):
124
+ s = {}
125
+ s['version'] = '1'
126
+ if expect_gencost:
127
+ try:
128
+ s['baseMVA'], s['bus'], s['gen'], s['branch'], \
129
+ s['areas'], s['gencost'] = eval(fname)()
130
+ except IOError as e:
131
+ info = 4
132
+ lasterr = str(e)
133
+ else:
134
+ if return_as_obj:
135
+ try:
136
+ s['baseMVA'], s['bus'], s['gen'], \
137
+ s['branch'], s['areas'], \
138
+ s['gencost'] = eval(fname)()
139
+ except ValueError as e:
140
+ try:
141
+ s['baseMVA'], s['bus'], s['gen'], \
142
+ s['branch'] = eval(fname)()
143
+ except ValueError as e:
144
+ info = 4
145
+ lasterr = str(e)
146
+ else:
147
+ try:
148
+ s['baseMVA'], s['bus'], s['gen'], \
149
+ s['branch'] = eval(fname)()
150
+ except ValueError as e:
151
+ info = 4
152
+ lasterr = str(e)
153
+
154
+ except IOError as e:
155
+ info = 4
156
+ lasterr = str(e)
157
+
158
+ if info == 4 and exists(rootname + '.py'):
159
+ info = 5
160
+ err5 = lasterr
161
+
162
+ elif isinstance(casefile, dict):
163
+ s = deepcopy(casefile)
164
+ else:
165
+ info = 1
166
+
167
+ # check contents of dict
168
+ if info == 0:
169
+ # check for required keys
170
+ if (s['baseMVA'] is None or s['bus'] is None
171
+ or s['gen'] is None or s['branch'] is None) or \
172
+ (expect_gencost and s['gencost'] is None) or \
173
+ (expect_areas and s['areas'] is None):
174
+ info = 5 # missing some expected fields
175
+ err5 = 'missing data'
176
+ else:
177
+ # remove empty areas if not needed
178
+ if hasattr(s, 'areas') and (len(s['areas']) == 0) and (not expect_areas):
179
+ del s['areas']
180
+
181
+ # all fields present, copy to ppc
182
+ ppc = deepcopy(s)
183
+ if not hasattr(ppc, 'version'): # hmm, struct with no 'version' field
184
+ if ppc['gen'].shape[1] < 21: # version 2 has 21 or 25 cols
185
+ ppc['version'] = '1'
186
+ else:
187
+ ppc['version'] = '2'
188
+
189
+ if (ppc['version'] == '1'):
190
+ # convert from version 1 to version 2
191
+ ppc['gen'], ppc['branch'] = ppc_1to2(ppc['gen'], ppc['branch'])
192
+ ppc['version'] = '2'
193
+
194
+ if info == 0: # no errors
195
+ if return_as_obj:
196
+ return ppc
197
+ else:
198
+ result = [ppc['baseMVA'], ppc['bus'], ppc['gen'], ppc['branch']]
199
+ if expect_gencost:
200
+ if expect_areas:
201
+ result.extend([ppc['areas'], ppc['gencost']])
202
+ else:
203
+ result.extend([ppc['gencost']])
204
+ return result
205
+ else: # error encountered
206
+ if info == 1:
207
+ logger.debug('Input arg should be a case or a string '
208
+ 'containing a filename\n')
209
+ elif info == 2:
210
+ logger.debug('Specified case not a valid file\n')
211
+ elif info == 3:
212
+ logger.debug('Specified MAT file does not exist\n')
213
+ elif info == 4:
214
+ logger.debug('Specified Python file does not exist\n')
215
+ elif info == 5:
216
+ logger.debug('Syntax error or undefined data '
217
+ 'matrix(ices) in the file\n')
218
+ else:
219
+ logger.debug('Unknown error encountered loading case.\n')
220
+
221
+ return info
222
+
223
+
224
+ def ppc_1to2(gen, branch):
225
+ # ----- gen -----
226
+ # use the version 1 values for column names
227
+ if gen.shape[1] >= IDX.gen.APF:
228
+ logger.debug('ppc_1to2: gen matrix appears to already be in '
229
+ 'version 2 format\n')
230
+ return gen, branch
231
+
232
+ shift = IDX.gen.MU_PMAX - IDX.gen.PMIN - 1
233
+ tmp = array([IDX.gen.MU_PMAX, IDX.gen.MU_PMIN, IDX.gen.MU_QMAX, IDX.gen.MU_QMIN]) - shift
234
+ mu_Pmax, mu_Pmin, mu_Qmax, mu_Qmin = tmp
235
+
236
+ # add extra columns to gen
237
+ tmp = zeros((gen.shape[0], shift))
238
+ if gen.shape[1] >= mu_Qmin:
239
+ gen = c_[gen[:, 0:IDX.gen.PMIN + 1], tmp, gen[:, mu_Pmax:mu_Qmin]]
240
+ else:
241
+ gen = c_[gen[:, 0:IDX.gen.PMIN + 1], tmp]
242
+
243
+ # ----- branch -----
244
+ # use the version 1 values for column names
245
+ shift = IDX.branch.PF - IDX.branch.BR_STATUS - 1
246
+ tmp = array([IDX.branch.PF, IDX.branch.QF, IDX.branch.PT,
247
+ IDX.branch.QT, IDX.branch.MU_SF, IDX.branch.MU_ST]) - shift
248
+ Pf, Qf, Pt, Qt, mu_Sf, mu_St = tmp
249
+
250
+ # add extra columns to branch
251
+ tmp = ones((branch.shape[0], 1)) * array([-360, 360])
252
+ tmp2 = zeros((branch.shape[0], 2))
253
+ if branch.shape[1] >= mu_St - 1:
254
+ branch = c_[branch[:, 0:IDX.branch.BR_STATUS + 1], tmp, branch[:, IDX.branch.PF - 1:IDX.branch.MU_ST + 1], tmp2]
255
+ elif branch.shape[1] >= IDX.branch.QT - 1:
256
+ branch = c_[branch[:, 0:IDX.branch.BR_STATUS + 1], tmp, branch[:, IDX.branch.PF - 1:IDX.branch.QT + 1]]
257
+ else:
258
+ branch = c_[branch[:, 0:IDX.branch.BR_STATUS + 1], tmp]
259
+
260
+ return gen, branch
261
+
262
+
263
+ def savecase(fname, ppc, comment=None, version='2'):
264
+ """Saves a PYPOWER case file, given a filename and the data.
265
+
266
+ Writes a PYPOWER case file, given a filename and data dict. The C{fname}
267
+ parameter is the name of the file to be created or overwritten. Returns
268
+ the filename, with extension added if necessary. The optional C{comment}
269
+ argument is either string (single line comment) or a list of strings which
270
+ are inserted as comments. When using a PYPOWER case dict, if the
271
+ optional C{version} argument is '1' it will modify the data matrices to
272
+ version 1 format before saving.
273
+
274
+ @author: Carlos E. Murillo-Sanchez (PSERC Cornell & Universidad
275
+ Autonoma de Manizales)
276
+ @author: Ray Zimmerman (PSERC Cornell)
277
+ """
278
+ ppc_ver = ppc["version"] = version
279
+ baseMVA, bus, gen, branch = \
280
+ ppc["baseMVA"], ppc["bus"], ppc["gen"], ppc["branch"]
281
+ areas = ppc["areas"] if "areas" in ppc else None
282
+ gencost = ppc["gencost"] if "gencost" in ppc else None
283
+
284
+ # modifications for version 1 format
285
+ if ppc_ver == "1":
286
+ raise NotImplementedError
287
+
288
+ # verify valid filename
289
+ l = len(fname)
290
+ rootname = ""
291
+ if l > 2:
292
+ if fname[-3:] == ".py":
293
+ rootname = fname[:-3]
294
+ extension = ".py"
295
+ elif l > 4:
296
+ if fname[-4:] == ".mat":
297
+ rootname = fname[:-4]
298
+ extension = ".mat"
299
+
300
+ if not rootname:
301
+ rootname = fname
302
+ extension = ".py"
303
+ fname = rootname + extension
304
+
305
+ indent = ' ' # four spaces
306
+ indent2 = indent + indent
307
+
308
+ # open and write the file
309
+ if extension == ".mat": # MAT-file
310
+ ppc_mat = {}
311
+ ppc_mat['version'] = ppc_ver
312
+ ppc_mat['baseMVA'] = baseMVA
313
+ ppc_keys = ['bus', 'gen', 'branch']
314
+ # Assign non-scalar values as NumPy arrays
315
+ for key in ppc_keys:
316
+ ppc_mat[key] = array(ppc[key])
317
+ if 'areas' in ppc:
318
+ ppc_mat['areas'] = array(ppc['areas'])
319
+ if 'gencost' in ppc:
320
+ ppc_mat['gencost'] = array(ppc['gencost'])
321
+ if "A" in ppc and len(ppc["A"]) > 0:
322
+ ppc_mat["A"] = array(ppc["A"])
323
+ if "l" in ppc and len(ppc["l"]) > 0:
324
+ ppc_mat["l"] = array(ppc["l"])
325
+ if "u" in ppc and len(ppc["u"]) > 0:
326
+ ppc_mat["u"] = array(ppc["u"])
327
+ if "N" in ppc and len(ppc["N"]) > 0:
328
+ ppc_mat["N"] = array(ppc["N"])
329
+ if "H" in ppc and len(ppc["H"]) > 0:
330
+ ppc_mat["H"] = array(ppc["H"])
331
+ if "fparm" in ppc and len(ppc["fparm"]) > 0:
332
+ ppc_mat["fparm"] = array(ppc["fparm"])
333
+ ppc_mat["Cw"] = array(ppc["Cw"])
334
+ if 'z0' in ppc or 'zl' in ppc or 'zu' in ppc:
335
+ if 'z0' in ppc and len(ppc['z0']) > 0:
336
+ ppc_mat['z0'] = array(ppc['z0'])
337
+ if 'zl' in ppc and len(ppc['zl']) > 0:
338
+ ppc_mat['zl'] = array(ppc['zl'])
339
+ if 'zu' in ppc and len(ppc['zu']) > 0:
340
+ ppc_mat['zu'] = array(ppc['zu'])
341
+ if 'userfcn' in ppc and len(ppc['userfcn']) > 0:
342
+ ppc_mat['userfcn'] = array(ppc['userfcn'])
343
+ elif 'userfcn' in ppc:
344
+ ppc_mat['userfcn'] = ppc['userfcn']
345
+ for key in ['x', 'f']:
346
+ if key in ppc:
347
+ ppc_mat[key] = ppc[key]
348
+ for key in ['lin', 'order', 'nln', 'var', 'raw', 'mu']:
349
+ if key in ppc:
350
+ ppc_mat[key] = array(ppc[key])
351
+
352
+ savemat(fname, ppc_mat)
353
+ else: # Python file
354
+ try:
355
+ fd = open(fname, "wb")
356
+ except Exception as detail:
357
+ logger.debug("savecase: %s.\n" % detail)
358
+ return fname
359
+
360
+ # function header, etc.
361
+ if ppc_ver == "1":
362
+ raise NotImplementedError
363
+ # if (areas != None) and (gencost != None) and (len(gencost) > 0):
364
+ # fd.write('function [baseMVA, bus, gen, branch, areas, gencost] = %s\n' % rootname)
365
+ # else:
366
+ # fd.write('function [baseMVA, bus, gen, branch] = %s\n' % rootname)
367
+ # prefix = ''
368
+ else:
369
+ fd.write('def %s():\n' % basename(rootname))
370
+ prefix = 'ppc'
371
+ if comment:
372
+ if isinstance(comment, str):
373
+ fd.write('#%s\n' % comment)
374
+ elif isinstance(comment, list):
375
+ for c in comment:
376
+ fd.write('#%s\n' % c)
377
+ fd.write('\n%s## PYPOWER Case Format : Version %s\n' % (indent, ppc_ver))
378
+ if ppc_ver != "1":
379
+ fd.write("%sppc = {'version': '%s'}\n" % (indent, ppc_ver))
380
+ fd.write('\n%s##----- Power Flow Data -----##\n' % indent)
381
+ fd.write('%s## system MVA base\n' % indent)
382
+ fd.write("%s%s['baseMVA'] = %.9g\n" % (indent, prefix, baseMVA))
383
+
384
+ # bus data
385
+ ncols = bus.shape[1]
386
+ fd.write('\n%s## bus data\n' % indent)
387
+ fd.write('%s# bus_i type Pd Qd Gs Bs area Vm Va baseKV zone Vmax Vmin' % indent)
388
+ if ncols >= IDX.bus.MU_VMIN + 1: # opf SOLVED, save with lambda's & mu's
389
+ fd.write('lam_P lam_Q mu_Vmax mu_Vmin')
390
+ fd.write("\n%s%s['bus'] = array([\n" % (indent, prefix))
391
+ if ncols < IDX.bus.MU_VMIN + 1: # opf NOT SOLVED, save without lambda's & mu's
392
+ for i in range(bus.shape[0]):
393
+ fd.write('%s[%d, %d, %.9g, %.9g, %.9g, %.9g, %d, %.9g, %.9g, %.9g, %d, %.9g, %.9g],\n' %
394
+ ((indent2,) + tuple(bus[i, :IDX.bus.VMIN + 1])))
395
+ else: # opf SOLVED, save with lambda's & mu's
396
+ for i in range(bus.shape[0]):
397
+ fd.write('%s[%d, %d, %.9g, %.9g, %.9g, %.9g, %d, %.9g, %.9g, %.9g, %d, %.9g, %.9g, %.4f, %.4f, %.4f, %.4f],\n' % (
398
+ (indent2,) + tuple(bus[i, :IDX.bus.MU_VMIN + 1])))
399
+ fd.write('%s])\n' % indent)
400
+
401
+ # generator data
402
+ ncols = gen.shape[1]
403
+ fd.write('\n%s## generator data\n' % indent)
404
+ fd.write('%s# bus Pg Qg Qmax Qmin Vg mBase status Pmax Pmin' % indent)
405
+ if ppc_ver != "1":
406
+ fd.write(' Pc1 Pc2 Qc1min Qc1max Qc2min Qc2max ramp_agc ramp_10 ramp_30 ramp_q apf')
407
+ if ncols >= IDX.gen.MU_QMIN + 1: # opf SOLVED, save with mu's
408
+ fd.write(' mu_Pmax mu_Pmin mu_Qmax mu_Qmin')
409
+ fd.write("\n%s%s['gen'] = array([\n" % (indent, prefix))
410
+ if ncols < IDX.gen.MU_QMIN + 1: # opf NOT SOLVED, save without mu's
411
+ if ppc_ver == "1":
412
+ for i in range(gen.shape[0]):
413
+ fd.write('%s[%d, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %d, %.9g, %.9g],\n' %
414
+ ((indent2,) + tuple(gen[i, :IDX.gen.PMIN + 1])))
415
+ else:
416
+ for i in range(gen.shape[0]):
417
+ fd.write('%s[%d, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %d, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g],\n' % (
418
+ (indent2,) + tuple(gen[i, :IDX.gen.APF + 1])))
419
+ else:
420
+ if ppc_ver == "1":
421
+ for i in range(gen.shape[0]):
422
+ fd.write(
423
+ '%s[%d, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %d, %.9g, %.9g, %.4f, %.4f, %.4f, %.4f],\n' %
424
+ ((indent2,) + tuple(gen[i, : IDX.gen.MU_QMIN + 1])))
425
+ else:
426
+ for i in range(gen.shape[0]):
427
+ fd.write('%s[%d, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %d, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.4f, %.4f, %.4f, %.4f],\n' % (
428
+ (indent2,) + tuple(gen[i, :IDX.gen.MU_QMIN + 1])))
429
+ fd.write('%s])\n' % indent)
430
+
431
+ # branch data
432
+ ncols = branch.shape[1]
433
+ fd.write('\n%s## branch data\n' % indent)
434
+ fd.write('%s# fbus tbus r x b rateA rateB rateC ratio angle status' % indent)
435
+ if ppc_ver != "1":
436
+ fd.write(' angmin angmax')
437
+ if ncols >= IDX.branch.QT + 1: # power flow SOLVED, save with line flows
438
+ fd.write(' Pf Qf Pt Qt')
439
+ if ncols >= IDX.branch.MU_ST + 1: # opf SOLVED, save with mu's
440
+ fd.write(' mu_Sf mu_St')
441
+ if ppc_ver != "1":
442
+ fd.write(' mu_angmin mu_angmax')
443
+ fd.write('\n%s%s[\'branch\'] = array([\n' % (indent, prefix))
444
+ if ncols < IDX.branch.QT + 1: # power flow NOT SOLVED, save without line flows or mu's
445
+ if ppc_ver == "1":
446
+ for i in range(branch.shape[0]):
447
+ fd.write('%s[%d, %d, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %d],\n' %
448
+ ((indent2,) + tuple(branch[i, :IDX.branch.BR_STATUS + 1])))
449
+ else:
450
+ for i in range(branch.shape[0]):
451
+ fd.write(
452
+ '%s[%d, %d, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %d, %.9g, %.9g],\n' %
453
+ ((indent2,) + tuple(branch[i, : IDX.branch.ANGMAX + 1])))
454
+ elif ncols < IDX.branch.MU_ST + 1: # power flow SOLVED, save with line flows but without mu's
455
+ if ppc_ver == "1":
456
+ for i in range(branch.shape[0]):
457
+ fd.write(
458
+ '%s[%d, %d, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %d, %.4f, %.4f, %.4f, %.4f],\n' %
459
+ ((indent2,) + tuple(branch[i, : IDX.branch.QT + 1])))
460
+ else:
461
+ for i in range(branch.shape[0]):
462
+ fd.write('%s[%d, %d, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %d, %.9g, %.9g, %.4f, %.4f, %.4f, %.4f],\n' % (
463
+ (indent2,) + tuple(branch[i, :IDX.branch.QT + 1])))
464
+ else: # opf SOLVED, save with lineflows & mu's
465
+ if ppc_ver == "1":
466
+ for i in range(branch.shape[0]):
467
+ fd.write('%s[%d, %d, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %d, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f],\n' % (
468
+ (indent2,) + tuple(branch[i, :IDX.branch.MU_ST + 1])))
469
+ else:
470
+ for i in range(branch.shape[0]):
471
+ fd.write('%s[%d, %d, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %d, %.9g, %.9g, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f],\n' % (
472
+ (indent2,) + tuple(branch[i, :IDX.branch.MU_ANGMAX + 1])))
473
+ fd.write('%s])\n' % indent)
474
+
475
+ # OPF data
476
+ if (areas is not None) and (len(areas) > 0) or (gencost is not None) and (len(gencost) > 0):
477
+ fd.write('\n%s##----- OPF Data -----##' % indent)
478
+ if (areas is not None) and (len(areas) > 0):
479
+ # area data
480
+ fd.write('\n%s## area data\n' % indent)
481
+ fd.write('%s# area refbus\n' % indent)
482
+ fd.write("%s%s['areas'] = array([\n" % (indent, prefix))
483
+ if len(areas) > 0:
484
+ for i in range(areas.shape[0]):
485
+ fd.write('%s[%d, %d],\n' % ((indent2,) + tuple(areas[i, :IDX.area.PRICE_REF_BUS + 1])))
486
+ fd.write('%s])\n' % indent)
487
+ if gencost is not None and len(gencost) > 0:
488
+ # generator cost data
489
+ fd.write('\n%s## generator cost data\n' % indent)
490
+ fd.write('%s# 1 startup shutdown n x1 y1 ... xn yn\n' % indent)
491
+ fd.write('%s# 2 startup shutdown n c(n-1) ... c0\n' % indent)
492
+ fd.write('%s%s[\'gencost\'] = array([\n' % (indent, prefix))
493
+ if len(gencost > 0):
494
+ if any(gencost[:, IDX.cost.MODEL] == IDX.cost.PW_LINEAR):
495
+ n1 = 2 * max(gencost[gencost[:, IDX.cost.MODEL] == IDX.cost.PW_LINEAR, IDX.cost.NCOST])
496
+ else:
497
+ n1 = 0
498
+ if any(gencost[:, IDX.cost.MODEL] == IDX.cost.POLYNOMIAL):
499
+ n2 = max(gencost[gencost[:, IDX.cost.MODEL] == IDX.cost.POLYNOMIAL, IDX.cost.NCOST])
500
+ else:
501
+ n2 = 0
502
+ n = int(max([n1, n2]))
503
+ if gencost.shape[1] < n + 4:
504
+ logger.debug('savecase: gencost data claims it has more columns than it does\n')
505
+ template = '%s[%d, %.9g, %.9g, %d'
506
+ for i in range(n):
507
+ template = template + ', %.9g'
508
+ template = template + '],\n'
509
+ for i in range(gencost.shape[0]):
510
+ fd.write(template % ((indent2,) + tuple(gencost[i])))
511
+ fd.write('%s])\n' % indent)
512
+
513
+ # generalized OPF user data
514
+ if ("A" in ppc) and (len(ppc["A"]) > 0) or ("N" in ppc) and (len(ppc["N"]) > 0):
515
+ fd.write('\n%s##----- Generalized OPF User Data -----##' % indent)
516
+
517
+ # user constraints
518
+ if ("A" in ppc) and (len(ppc["A"]) > 0):
519
+ # A
520
+ fd.write('\n%s## user constraints\n' % indent)
521
+ print_sparse(fd, prefix + "['A']", ppc["A"])
522
+ if ("l" in ppc) and (len(ppc["l"]) > 0) and ("u" in ppc) and (len(ppc["u"]) > 0):
523
+ fd.write('%slu = array([\n' % indent)
524
+ for i in range(len(ppc["l"])):
525
+ fd.write('%s[%.9g, %.9g],\n' % (indent2, ppc["l"][i], ppc["u"][i]))
526
+ fd.write('%s])\n' % indent)
527
+ fd.write("%s%s['l'] = lu[:, 0]\n" % (indent, prefix))
528
+ fd.write("%s%s['u'] = lu[:, 1]\n\n" % (indent, prefix))
529
+ elif ("l" in ppc) and (len(ppc["l"]) > 0):
530
+ fd.write("%s%s['l'] = array([\n" % (indent, prefix))
531
+ for i in range(len(l)):
532
+ fd.write('%s[%.9g],\n' % (indent2, ppc["l"][i]))
533
+ fd.write('%s])\n\n' % indent)
534
+ elif ("u" in ppc) and (len(ppc["u"]) > 0):
535
+ fd.write("%s%s['u'] = array([\n" % (indent, prefix))
536
+ for i in range(len(l)):
537
+ fd.write('%s[%.9g],\n' % (indent2, ppc["u"][i]))
538
+ fd.write('%s])\n\n' % indent)
539
+
540
+ # user costs
541
+ if ("N" in ppc) and (len(ppc["N"]) > 0):
542
+ fd.write('\n%s## user costs\n' % indent)
543
+ print_sparse(fd, prefix + "['N']", ppc["N"])
544
+ if ("H" in ppc) and (len(ppc["H"]) > 0):
545
+ print_sparse(fd, prefix + "['H']", ppc["H"])
546
+ if ("fparm" in ppc) and (len(ppc["fparm"]) > 0):
547
+ fd.write("%sCw_fparm = array([\n" % indent)
548
+ for i in range(ppc["Cw"]):
549
+ fd.write('%s[%.9g, %d, %.9g, %.9g, %.9g],\n' %
550
+ ((indent2,) + tuple(ppc["Cw"][i]) + tuple(ppc["fparm"][i, :])))
551
+ fd.write('%s])\n' % indent)
552
+ fd.write('%s%s[\'Cw\'] = Cw_fparm[:, 0]\n' % (indent, prefix))
553
+ fd.write("%s%s['fparm'] = Cw_fparm[:, 1:5]\n" % (indent, prefix))
554
+ else:
555
+ fd.write("%s%s['Cw'] = array([\n" % (indent, prefix))
556
+ for i in range(len(ppc["Cw"])):
557
+ fd.write('%s[%.9g],\n' % (indent2, ppc["Cw"][i]))
558
+ fd.write('%s])\n' % indent)
559
+
560
+ # user vars
561
+ if ('z0' in ppc) or ('zl' in ppc) or ('zu' in ppc):
562
+ fd.write('\n%s## user vars\n' % indent)
563
+ if ('z0' in ppc) and (len(ppc['z0']) > 0):
564
+ fd.write('%s%s["z0"] = array([\n' % (indent, prefix))
565
+ for i in range(len(ppc['z0'])):
566
+ fd.write('%s[%.9g],\n' % (indent2, ppc["z0"]))
567
+ fd.write('%s])\n' % indent)
568
+ if ('zl' in ppc) and (len(ppc['zl']) > 0):
569
+ fd.write('%s%s["zl"] = array([\n' % (indent2, prefix))
570
+ for i in range(len(ppc['zl'])):
571
+ fd.write('%s[%.9g],\n' % (indent2, ppc["zl"]))
572
+ fd.write('%s])\n' % indent)
573
+ if ('zu' in ppc) and (len(ppc['zu']) > 0):
574
+ fd.write('%s%s["zu"] = array([\n' % (indent, prefix))
575
+ for i in range(len(ppc['zu'])):
576
+ fd.write('%s[%.9g],\n' % (indent2, ppc["zu"]))
577
+ fd.write('%s])\n' % indent)
578
+
579
+ # execute userfcn callbacks for 'savecase' stage
580
+ if 'userfcn' in ppc:
581
+ run_userfcn(ppc["userfcn"], 'savecase', ppc, fd, prefix)
582
+
583
+ fd.write('\n%sreturn ppc\n' % indent)
584
+
585
+ # close file
586
+ fd.close()
587
+
588
+ return fname
589
+
590
+
591
+ def print_sparse(fd, varname, A):
592
+ A = A.tocoo()
593
+ i, j, s = A.row, A.col, A.data
594
+ m, n = A.shape
595
+
596
+ if len(s) == 0:
597
+ fd.write('%s = sparse((%d, %d))\n' % (varname, m, n))
598
+ else:
599
+ fd.write('ijs = array([\n')
600
+ for k in range(len(i)):
601
+ fd.write('[%d, %d, %.9g],\n' % (i[k], j[k], s[k]))
602
+
603
+ fd.write('])\n')
604
+ fd.write('%s = sparse(ijs[:, 0], ijs[:, 1], ijs[:, 2], %d, %d)\n' % (varname, m, n))
@@ -0,0 +1,11 @@
1
+ """
2
+ Module for build matrices.
3
+ """
4
+
5
+ from ams.pypower.make.matrices import (makeAang, makeApq, makeAvl, makeAy,
6
+ makeB, makeBdc,
7
+ makeLODF, makePTDF,
8
+ makeSbus, makeYbus) # NOQA
9
+ from ams.pypower.make.pdv import (dSbus_dV, dIbr_dV, dSbr_dV,
10
+ d2Sbus_dV2, d2AIbr_dV2, d2ASbr_dV2,
11
+ d2Ibr_dV2, d2Sbr_dV2, dAbr_dV) # NOQA