ltbams 0.9.10__tar.gz → 0.9.11__tar.gz

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 (196) hide show
  1. {ltbams-0.9.10 → ltbams-0.9.11}/LICENSE +1 -1
  2. ltbams-0.9.11/PKG-INFO +11 -0
  3. {ltbams-0.9.10 → ltbams-0.9.11}/README.md +14 -1
  4. ltbams-0.9.11/ams/__init__.py +13 -0
  5. {ltbams-0.9.10 → ltbams-0.9.11}/ams/_version.py +3 -3
  6. ltbams-0.9.11/ams/benchmarks.py +302 -0
  7. ltbams-0.9.11/ams/cases/5bus/pjm5bus_jumper.xlsx +0 -0
  8. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/5bus/pjm5bus_uced_esd1.xlsx +0 -0
  9. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cli.py +6 -0
  10. {ltbams-0.9.10 → ltbams-0.9.11}/ams/core/matprocessor.py +19 -5
  11. {ltbams-0.9.10 → ltbams-0.9.11}/ams/core/param.py +6 -2
  12. {ltbams-0.9.10 → ltbams-0.9.11}/ams/core/service.py +3 -2
  13. {ltbams-0.9.10 → ltbams-0.9.11}/ams/core/symprocessor.py +11 -3
  14. ltbams-0.9.10/ams/interop/andes.py → ltbams-0.9.11/ams/interface.py +41 -52
  15. {ltbams-0.9.10 → ltbams-0.9.11}/ams/io/__init__.py +0 -1
  16. {ltbams-0.9.10 → ltbams-0.9.11}/ams/io/json.py +2 -9
  17. {ltbams-0.9.10 → ltbams-0.9.11}/ams/io/matpower.py +14 -14
  18. {ltbams-0.9.10 → ltbams-0.9.11}/ams/io/xlsx.py +3 -10
  19. {ltbams-0.9.10 → ltbams-0.9.11}/ams/main.py +79 -2
  20. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/__init__.py +1 -1
  21. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/group.py +10 -3
  22. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/line.py +28 -0
  23. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/reserve.py +4 -4
  24. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/static/gen.py +9 -3
  25. {ltbams-0.9.10 → ltbams-0.9.11}/ams/opt/omodel.py +484 -188
  26. {ltbams-0.9.10 → ltbams-0.9.11}/ams/report.py +6 -0
  27. {ltbams-0.9.10 → ltbams-0.9.11}/ams/routines/__init__.py +0 -1
  28. {ltbams-0.9.10 → ltbams-0.9.11}/ams/routines/acopf.py +3 -5
  29. {ltbams-0.9.10 → ltbams-0.9.11}/ams/routines/dcopf.py +39 -18
  30. {ltbams-0.9.10 → ltbams-0.9.11}/ams/routines/dcpf.py +7 -10
  31. {ltbams-0.9.10 → ltbams-0.9.11}/ams/routines/ed.py +14 -23
  32. {ltbams-0.9.10 → ltbams-0.9.11}/ams/routines/pflow.py +4 -6
  33. {ltbams-0.9.10 → ltbams-0.9.11}/ams/routines/routine.py +115 -41
  34. {ltbams-0.9.10 → ltbams-0.9.11}/ams/routines/rted.py +11 -10
  35. {ltbams-0.9.10 → ltbams-0.9.11}/ams/routines/uc.py +8 -5
  36. {ltbams-0.9.10 → ltbams-0.9.11}/ams/shared.py +31 -8
  37. {ltbams-0.9.10 → ltbams-0.9.11}/ams/system.py +6 -6
  38. ltbams-0.9.11/ams/utils/__init__.py +59 -0
  39. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/api.rst +4 -2
  40. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/conf.py +1 -1
  41. ltbams-0.9.11/docs/source/genmodelref.py +61 -0
  42. ltbams-0.9.11/docs/source/genroutineref.py +47 -0
  43. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/getting_started/install.rst +2 -2
  44. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/modeling/example.rst +1 -1
  45. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/modeling/routine.rst +5 -12
  46. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/release-notes.rst +21 -1
  47. ltbams-0.9.11/ltbams.egg-info/PKG-INFO +11 -0
  48. {ltbams-0.9.10 → ltbams-0.9.11}/ltbams.egg-info/SOURCES.txt +17 -7
  49. ltbams-0.9.11/pyproject.toml +73 -0
  50. ltbams-0.9.11/requirements-extra.txt +19 -0
  51. {ltbams-0.9.10 → ltbams-0.9.11}/requirements.txt +2 -1
  52. ltbams-0.9.11/setup.py +17 -0
  53. ltbams-0.9.11/tests/test_andes_mats.py +61 -0
  54. ltbams-0.9.11/tests/test_benchmarks.py +149 -0
  55. {ltbams-0.9.10 → ltbams-0.9.11}/tests/test_case.py +2 -2
  56. ltbams-0.9.10/tests/test_andes.py → ltbams-0.9.11/tests/test_interop.py +7 -60
  57. ltbams-0.9.11/tests/test_io.py +32 -0
  58. ltbams-0.9.11/tests/test_jumper.py +27 -0
  59. ltbams-0.9.10/tests/test_mats.py → ltbams-0.9.11/tests/test_matp.py +4 -0
  60. {ltbams-0.9.10 → ltbams-0.9.11}/tests/test_routine.py +3 -85
  61. ltbams-0.9.11/tests/test_rtn_dcopf.py +77 -0
  62. ltbams-0.9.11/tests/test_rtn_ed.py +184 -0
  63. ltbams-0.9.11/tests/test_rtn_pflow.py +219 -0
  64. ltbams-0.9.11/tests/test_rtn_rted.py +176 -0
  65. ltbams-0.9.11/tests/test_rtn_uc.py +165 -0
  66. ltbams-0.9.10/PKG-INFO +0 -153
  67. ltbams-0.9.10/ams/__init__.py +0 -20
  68. ltbams-0.9.10/ams/interop/__init__.py +0 -18
  69. ltbams-0.9.10/ams/utils/__init__.py +0 -13
  70. ltbams-0.9.10/ltbams.egg-info/PKG-INFO +0 -153
  71. ltbams-0.9.10/ltbams.egg-info/entry_points.txt +0 -3
  72. ltbams-0.9.10/ltbams.egg-info/requires.txt +0 -90
  73. ltbams-0.9.10/requirements-extra.txt +0 -23
  74. ltbams-0.9.10/setup.py +0 -108
  75. ltbams-0.9.10/tests/test_dctypes.py +0 -111
  76. {ltbams-0.9.10 → ltbams-0.9.11}/CONTRIBUTING.rst +0 -0
  77. {ltbams-0.9.10 → ltbams-0.9.11}/MANIFEST.in +0 -0
  78. {ltbams-0.9.10 → ltbams-0.9.11}/ams/__main__.py +0 -0
  79. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/5bus/pjm5bus_demo.xlsx +0 -0
  80. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/5bus/pjm5bus_uced.json +0 -0
  81. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/5bus/pjm5bus_uced.xlsx +0 -0
  82. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/5bus/pjm5bus_uced_ev.xlsx +0 -0
  83. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/ieee123/ieee123.xlsx +0 -0
  84. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/ieee123/ieee123_regcv1.xlsx +0 -0
  85. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/ieee14/ieee14.json +0 -0
  86. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/ieee14/ieee14.raw +0 -0
  87. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/ieee14/ieee14_uced.xlsx +0 -0
  88. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/ieee39/ieee39.xlsx +0 -0
  89. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/ieee39/ieee39_uced.xlsx +0 -0
  90. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/ieee39/ieee39_uced_esd1.xlsx +0 -0
  91. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/ieee39/ieee39_uced_pvd1.xlsx +0 -0
  92. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/ieee39/ieee39_uced_vis.xlsx +0 -0
  93. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/matpower/benchmark.json +0 -0
  94. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/matpower/case118.m +0 -0
  95. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/matpower/case14.m +0 -0
  96. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/matpower/case300.m +0 -0
  97. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/matpower/case39.m +0 -0
  98. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/matpower/case5.m +0 -0
  99. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/matpower/case_ACTIVSg2000.m +0 -0
  100. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/npcc/npcc.m +0 -0
  101. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/npcc/npcc_uced.xlsx +0 -0
  102. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/pglib/pglib_opf_case39_epri__api.m +0 -0
  103. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/wecc/wecc.m +0 -0
  104. {ltbams-0.9.10 → ltbams-0.9.11}/ams/cases/wecc/wecc_uced.xlsx +0 -0
  105. {ltbams-0.9.10 → ltbams-0.9.11}/ams/core/__init__.py +0 -0
  106. {ltbams-0.9.10 → ltbams-0.9.11}/ams/core/documenter.py +0 -0
  107. {ltbams-0.9.10 → ltbams-0.9.11}/ams/core/model.py +0 -0
  108. {ltbams-0.9.10 → ltbams-0.9.11}/ams/core/var.py +0 -0
  109. {ltbams-0.9.10 → ltbams-0.9.11}/ams/extension/__init__.py +0 -0
  110. {ltbams-0.9.10 → ltbams-0.9.11}/ams/extension/eva.py +0 -0
  111. {ltbams-0.9.10 → ltbams-0.9.11}/ams/io/psse.py +0 -0
  112. {ltbams-0.9.10 → ltbams-0.9.11}/ams/io/pypower.py +0 -0
  113. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/area.py +0 -0
  114. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/bus.py +0 -0
  115. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/cost.py +0 -0
  116. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/distributed/__init__.py +0 -0
  117. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/distributed/esd1.py +0 -0
  118. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/distributed/ev.py +0 -0
  119. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/distributed/pvd1.py +0 -0
  120. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/info.py +0 -0
  121. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/region.py +0 -0
  122. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/renewable/__init__.py +0 -0
  123. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/renewable/regc.py +0 -0
  124. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/shunt.py +0 -0
  125. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/static/__init__.py +0 -0
  126. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/static/pq.py +0 -0
  127. {ltbams-0.9.10 → ltbams-0.9.11}/ams/models/timeslot.py +0 -0
  128. {ltbams-0.9.10 → ltbams-0.9.11}/ams/opt/__init__.py +0 -0
  129. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/__init__.py +0 -0
  130. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/_compat.py +0 -0
  131. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/core/__init__.py +0 -0
  132. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/core/pips.py +0 -0
  133. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/core/ppoption.py +0 -0
  134. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/core/ppver.py +0 -0
  135. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/core/solver.py +0 -0
  136. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/eps.py +0 -0
  137. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/idx.py +0 -0
  138. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/io.py +0 -0
  139. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/make/__init__.py +0 -0
  140. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/make/matrices.py +0 -0
  141. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/make/pdv.py +0 -0
  142. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/routines/__init__.py +0 -0
  143. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/routines/cpf.py +0 -0
  144. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/routines/cpf_callbacks.py +0 -0
  145. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/routines/opf.py +0 -0
  146. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/routines/opffcns.py +0 -0
  147. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/routines/pflow.py +0 -0
  148. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/toggle.py +0 -0
  149. {ltbams-0.9.10 → ltbams-0.9.11}/ams/pypower/utils.py +0 -0
  150. {ltbams-0.9.10 → ltbams-0.9.11}/ams/routines/cpf.py +0 -0
  151. {ltbams-0.9.10 → ltbams-0.9.11}/ams/routines/dopf.py +0 -0
  152. {ltbams-0.9.10 → ltbams-0.9.11}/ams/routines/type.py +0 -0
  153. {ltbams-0.9.10 → ltbams-0.9.11}/ams/utils/paths.py +0 -0
  154. {ltbams-0.9.10 → ltbams-0.9.11}/docs/Makefile +0 -0
  155. {ltbams-0.9.10 → ltbams-0.9.11}/docs/make.bat +0 -0
  156. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/_templates/autosummary/base.rst +0 -0
  157. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/_templates/autosummary/class.rst +0 -0
  158. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/_templates/autosummary/module.rst +0 -0
  159. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/_templates/autosummary/module_toctree.rst +0 -0
  160. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/examples/index.rst +0 -0
  161. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/getting_started/copyright.rst +0 -0
  162. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/getting_started/formats/index.rst +0 -0
  163. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/getting_started/formats/matpower.rst +0 -0
  164. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/getting_started/formats/psse.rst +0 -0
  165. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/getting_started/formats/pypower.rst +0 -0
  166. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/getting_started/formats/xlsx.png +0 -0
  167. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/getting_started/formats/xlsx.rst +0 -0
  168. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/getting_started/index.rst +0 -0
  169. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/getting_started/overview.rst +0 -0
  170. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/getting_started/testcase.rst +0 -0
  171. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/getting_started/verification.rst +0 -0
  172. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/images/dcopf_time.png +0 -0
  173. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/images/sponsors/CURENT_Logo_NameOnTrans.png +0 -0
  174. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/images/sponsors/CURENT_Logo_Transparent.png +0 -0
  175. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/images/sponsors/CURENT_Logo_Transparent_Name.png +0 -0
  176. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/images/sponsors/doe.png +0 -0
  177. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/index.rst +0 -0
  178. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/modeling/index.rst +0 -0
  179. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/modeling/model.rst +0 -0
  180. {ltbams-0.9.10 → ltbams-0.9.11}/docs/source/modeling/system.rst +0 -0
  181. {ltbams-0.9.10 → ltbams-0.9.11}/ltbams.egg-info/dependency_links.txt +0 -0
  182. {ltbams-0.9.10 → ltbams-0.9.11}/ltbams.egg-info/top_level.txt +0 -0
  183. {ltbams-0.9.10 → ltbams-0.9.11}/setup.cfg +0 -0
  184. {ltbams-0.9.10 → ltbams-0.9.11}/tests/__init__.py +0 -0
  185. {ltbams-0.9.10 → ltbams-0.9.11}/tests/test_1st_system.py +0 -0
  186. {ltbams-0.9.10 → ltbams-0.9.11}/tests/test_addressing.py +1 -1
  187. {ltbams-0.9.10 → ltbams-0.9.11}/tests/test_cli.py +0 -0
  188. {ltbams-0.9.10 → ltbams-0.9.11}/tests/test_export_csv.py +0 -0
  189. {ltbams-0.9.10 → ltbams-0.9.11}/tests/test_group.py +0 -0
  190. {ltbams-0.9.10 → ltbams-0.9.11}/tests/test_known_good.py +0 -0
  191. {ltbams-0.9.10 → ltbams-0.9.11}/tests/test_model.py +0 -0
  192. {ltbams-0.9.10 → ltbams-0.9.11}/tests/test_paths.py +0 -0
  193. {ltbams-0.9.10 → ltbams-0.9.11}/tests/test_report.py +0 -0
  194. {ltbams-0.9.10 → ltbams-0.9.11}/tests/test_repr.py +0 -0
  195. {ltbams-0.9.10 → ltbams-0.9.11}/tests/test_service.py +0 -0
  196. {ltbams-0.9.10 → ltbams-0.9.11}/versioneer.py +0 -0
@@ -670,7 +670,7 @@ Also add information on how to contact you by electronic and paper mail.
670
670
  If the program does terminal interaction, make it output a short
671
671
  notice like this when it starts in an interactive mode:
672
672
 
673
- AMS Copyright (C) 2023 Jinning Wang
673
+ AMS Copyright (C) 2023 - 2024 Jinning Wang
674
674
  This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
675
675
  This is free software, and you are welcome to redistribute it
676
676
  under certain conditions; type `show c' for details.
ltbams-0.9.11/PKG-INFO ADDED
@@ -0,0 +1,11 @@
1
+ Metadata-Version: 2.1
2
+ Name: ltbams
3
+ Version: 0.9.11
4
+ Summary: UNKNOWN
5
+ Home-page: UNKNOWN
6
+ License: UNKNOWN
7
+ Platform: UNKNOWN
8
+ License-File: LICENSE
9
+
10
+ UNKNOWN
11
+
@@ -4,7 +4,7 @@ Python Software for Power System Scheduling Modeling and Co-Simulation with Dyna
4
4
 
5
5
  [![License: GPL-3.0](https://img.shields.io/badge/License-GPL--3.0-blue.svg)](https://github.com/CURENT/ams/blob/master/LICENSE)
6
6
  ![platforms](https://anaconda.org/conda-forge/ltbams/badges/platforms.svg)
7
- [![Python Versions](https://img.shields.io/badge/Python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12-blue)](https://www.python.org/)
7
+ [![Python Versions](https://img.shields.io/badge/Python-3.9%20%7C%203.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-blue)](https://www.python.org/)
8
8
  ![Repo Size](https://img.shields.io/github/repo-size/CURENT/ams)
9
9
  [![GitHub last commit (master)](https://img.shields.io/github/last-commit/CURENT/ams/master?label=last%20commit%20to%20master)](https://github.com/CURENT/ams/commits/master/)
10
10
  [![GitHub last commit (develop)](https://img.shields.io/github/last-commit/CURENT/ams/develop?label=last%20commit%20to%20develop)](https://github.com/CURENT/ams/commits/develop/)
@@ -82,6 +82,19 @@ Install from GitHub source:
82
82
  pip install git+https://github.com/CURENT/ams.git
83
83
  ```
84
84
 
85
+ # Example Usage
86
+
87
+ Using AMS to run a Real-Time Economic Dispatch (RTED) simulation:
88
+
89
+ ```python
90
+ import ams
91
+
92
+ ss = ams.load(ams.get_case('ieee14_uced.xlsx'))
93
+ ss.RTED.run()
94
+
95
+ print(ss.RTED.pg.v)
96
+ ```
97
+
85
98
  # Sponsors and Contributors
86
99
  AMS is the scheduling simulation engine for the CURENT Largescale Testbed (LTB).
87
100
  More information about CURENT LTB can be found at the [LTB Repository][LTB Repository].
@@ -0,0 +1,13 @@
1
+ from . import _version
2
+ __version__ = _version.get_versions()['version']
3
+
4
+ from ams import benchmarks # NOQA
5
+
6
+ from ams.main import config_logger, load, run # NOQA
7
+ from ams.system import System # NOQA
8
+ from ams.utils.paths import get_case, list_cases # NOQA
9
+ from ams.shared import ppc2df # NOQA
10
+
11
+ __author__ = 'Jining Wang'
12
+
13
+ __all__ = ['System', 'get_case', 'System']
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2024-09-03T22:41:38-0400",
11
+ "date": "2024-11-14T16:34:57-0500",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "8bc9504a8281c16236c73decd8e7365b682c706c",
15
- "version": "0.9.10"
14
+ "full-revisionid": "9dcd290dc6532149fcd0b4f26fb5e9af4bf4bf36",
15
+ "version": "0.9.11"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -0,0 +1,302 @@
1
+ """
2
+ Benchmark functions.
3
+ """
4
+
5
+ import datetime
6
+ import sys
7
+ import importlib.metadata as importlib_metadata
8
+ import logging
9
+
10
+ try:
11
+ import pandapower as pdp
12
+ PANDAPOWER_AVAILABLE = True
13
+ except ImportError:
14
+ PANDAPOWER_AVAILABLE = False
15
+ logging.warning("pandapower is not available. Some functionalities will be disabled.")
16
+
17
+ from andes.utils.misc import elapsed
18
+
19
+ import ams
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+ _failed_time = -1
24
+ _failed_obj = -1
25
+
26
+ cols_pre = ['ams_mats', 'ams_parse', 'ams_eval', 'ams_final', 'ams_postinit']
27
+
28
+
29
+ def get_tool_versions(tools=None):
30
+ """
31
+ Get the current time, Python version, and versions of specified tools.
32
+
33
+ Parameters
34
+ ----------
35
+ tools : list of str, optional
36
+ List of tool names to check versions. If None, a default list of tools is used.
37
+
38
+ Returns
39
+ -------
40
+ dict
41
+ A dictionary containing the tool names and their versions.
42
+ """
43
+ if tools is None:
44
+ tools = ['ltbams', 'andes', 'cvxpy',
45
+ 'gurobipy', 'mosek', 'piqp',
46
+ 'pandapower', 'numba']
47
+
48
+ # Get current time and Python version
49
+ last_run_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
50
+ python_version = sys.version
51
+
52
+ # Collect tool versions
53
+ tool_versions = {}
54
+ for tool in tools:
55
+ try:
56
+ version = importlib_metadata.version(tool)
57
+ tool_versions[tool] = version
58
+ except importlib_metadata.PackageNotFoundError:
59
+ logger.error(f"Package {tool} not found.")
60
+ tool_versions[tool] = "Not installed"
61
+
62
+ # Print the results in a formatted way
63
+ logger.warning(f"Last run time: {last_run_time}")
64
+ logger.warning(f"Python: {python_version}\n")
65
+
66
+ # Calculate the width of the columns
67
+ max_tool_length = max(len(tool) for tool in tool_versions)
68
+ max_version_length = max(len(version) for version in tool_versions.values())
69
+
70
+ # Print the header
71
+ logger.warning(f"{'Tool':<{max_tool_length}} {'Version':<{max_version_length}}")
72
+ logger.warning(f"{'-' * max_tool_length} {'-' * max_version_length}")
73
+
74
+ # Print each tool and its version
75
+ for tool, version in tool_versions.items():
76
+ logger.warning(f"{tool:<{max_tool_length}} {version:<{max_version_length}}")
77
+
78
+ return tool_versions
79
+
80
+
81
+ def time_routine_solve(system, routine='DCOPF', **kwargs):
82
+ """
83
+ Run the specified routine with the given solver and method.
84
+
85
+ Parameters
86
+ ----------
87
+ system : ams.System
88
+ The system object containing the routine.
89
+ routine : str, optional
90
+ The name of the routine to run. Defaults to 'DCOPF'.
91
+
92
+ Other Parameters
93
+ ----------------
94
+ solver : str, optional
95
+ The solver to use.
96
+ ignore_dpp : bool, optional
97
+ Whether to ignore DPP. Defaults to True.
98
+
99
+ Returns
100
+ -------
101
+ tuple
102
+ A tuple containing the elapsed time (s) and the objective value ($).
103
+ """
104
+ rtn = system.routines[routine]
105
+ solver = kwargs.get('solver', None)
106
+ try:
107
+ t, _ = elapsed()
108
+ rtn.run(**kwargs)
109
+ _, s0 = elapsed(t)
110
+ elapsed_time = float(s0.split(' ')[0])
111
+ obj_value = rtn.obj.v
112
+ except Exception as e:
113
+ logger.error(f"Error running routine {routine} with solver {solver}: {e}")
114
+ elapsed_time = _failed_time
115
+ obj_value = _failed_obj
116
+ return elapsed_time, obj_value
117
+
118
+
119
+ def pre_solve(system, routine):
120
+ """
121
+ Time the routine preparation process.
122
+
123
+ Parameters
124
+ ----------
125
+ system : ams.System
126
+ The system object containing the routine.
127
+ routine : str
128
+ The name of the routine to prepare
129
+
130
+ Returns
131
+ -------
132
+ dict
133
+ A dictionary containing the preparation times in seconds for each step:
134
+ 'mats', 'parse', 'evaluate', 'finalize', 'postinit'.
135
+ """
136
+ rtn = system.routines[routine]
137
+
138
+ # Initialize AMS
139
+ # --- matrices build ---
140
+ t_mats, _ = elapsed()
141
+ system.mats.build(force=True)
142
+ _, s_mats = elapsed(t_mats)
143
+
144
+ # --- code generation ---
145
+ t_parse, _ = elapsed()
146
+ rtn.om.parse(force=True)
147
+ _, s_parse = elapsed(t_parse)
148
+
149
+ # --- code evaluation ---
150
+ t_evaluate, _ = elapsed()
151
+ rtn.om.evaluate(force=True)
152
+ _, s_evaluate = elapsed(t_evaluate)
153
+
154
+ # --- problem finalization ---
155
+ t_finalize, _ = elapsed()
156
+ rtn.om.finalize(force=True)
157
+ _, s_finalize = elapsed(t_finalize)
158
+
159
+ # --- rest init process ---
160
+ t_postinit, _ = elapsed()
161
+ rtn.init()
162
+ _, s_postinit = elapsed(t_postinit)
163
+
164
+ s_float = [float(s.split(' ')[0]) for s in [s_mats, s_parse, s_evaluate, s_finalize, s_postinit]]
165
+
166
+ pre_time = dict(zip(cols_pre, s_float))
167
+ return pre_time
168
+
169
+
170
+ def time_pdp_dcopf(ppn):
171
+ """
172
+ Test the execution time of DCOPF using pandapower.
173
+
174
+ Parameters
175
+ ----------
176
+ ppn : pandapowerNet
177
+ The pandapower network object.
178
+
179
+ Returns
180
+ -------
181
+ tuple
182
+ A tuple containing the elapsed time (s) and the objective value ($).
183
+ """
184
+ try:
185
+ t_pdp, _ = elapsed()
186
+ pdp.rundcopp(ppn)
187
+ _, s_pdp = elapsed(t_pdp)
188
+ elapsed_time = float(s_pdp.split(' ')[0])
189
+ obj_value = ppn.res_cost
190
+ except Exception as e:
191
+ logger.error(f"Error running pandapower: {e}")
192
+ elapsed_time = _failed_time
193
+ obj_value = _failed_obj
194
+ return elapsed_time, obj_value
195
+
196
+
197
+ def time_routine(system, routine='DCOPF', solvers=['CLARABEL'],
198
+ **kwargs):
199
+ """
200
+ Time the specified routine with the given solvers.
201
+
202
+ Parameters
203
+ ----------
204
+ system : ams.System
205
+ The system object containing the routine.
206
+ routine : str, optional
207
+ The name of the routine to run. Defaults to 'DCOPF'.
208
+ solvers : list of str, optional
209
+ List of solvers to use. Defaults to ['CLARABEL'].
210
+
211
+ Other Parameters
212
+ ----------------
213
+ ignore_dpp : bool, optional
214
+ Whether to ignore DPP. Defaults to True.
215
+
216
+ Returns
217
+ -------
218
+ tuple
219
+ A tuple containing the preparation times and the solution times in
220
+ seconds for each solver.
221
+ """
222
+ pre_time = pre_solve(system, routine)
223
+ sol = {f'{solver}': {'time': 0, 'obj': 0} for solver in solvers}
224
+
225
+ for solver in solvers:
226
+ if solver != 'pandapower':
227
+ s, obj = time_routine_solve(system, routine, solver=solver, **kwargs)
228
+ sol[solver]['time'] = s
229
+ sol[solver]['obj'] = obj
230
+ elif solver == 'pandapower' and PANDAPOWER_AVAILABLE and routine == 'DCOPF':
231
+ ppc = ams.io.pypower.system2ppc(system)
232
+ ppn = pdp.converter.from_ppc(ppc, f_hz=system.config.freq)
233
+ s, obj = time_pdp_dcopf(ppn)
234
+ sol[solver]['time'] = s
235
+ sol[solver]['obj'] = obj
236
+ else:
237
+ sol[solver]['time'] = _failed_time
238
+ sol[solver]['obj'] = _failed_obj
239
+
240
+ return pre_time, sol
241
+
242
+
243
+ def time_dcopf_with_lf(system, solvers=['CLARABEL'], load_factors=[1], ignore_dpp=False):
244
+ """
245
+ Time the execution of DCOPF with varying load factors.
246
+
247
+ Parameters
248
+ ----------
249
+ system : ams.System
250
+ The system object containing the routine.
251
+ solvers : list of str, optional
252
+ List of solvers to use. Defaults to ['CLARABEL'].
253
+ load_factors : list of float, optional
254
+ List of load factors to apply. Defaults to None.
255
+ ignore_dpp : bool, optional
256
+ Whether to ignore DPP.
257
+
258
+ Returns
259
+ -------
260
+ tuple
261
+ A tuple containing the list of times and the list of objective values.
262
+ """
263
+ pre_time = pre_solve(system, 'DCOPF')
264
+ sol = {f'{solver}': {'time': 0, 'obj': 0} for solver in solvers}
265
+
266
+ pd0 = system.PQ.p0.v.copy()
267
+ pq_idx = system.PQ.idx.v
268
+
269
+ for solver in solvers:
270
+ if solver != 'pandapower':
271
+ obj_all = 0
272
+ t_all, _ = elapsed()
273
+ for lf_k in load_factors:
274
+ system.PQ.set(src='p0', attr='v', idx=pq_idx, value=lf_k * pd0)
275
+ system.DCOPF.update(params=['pd'])
276
+ _, obj = time_routine_solve(system, 'DCOPF',
277
+ solver=solver, ignore_dpp=ignore_dpp)
278
+ obj_all += obj
279
+ _, s_all = elapsed(t_all)
280
+ system.PQ.set(src='p0', attr='v', idx=pq_idx, value=pd0)
281
+ s = float(s_all.split(' ')[0])
282
+ sol[solver]['time'] = s
283
+ sol[solver]['obj'] = obj_all
284
+ elif solver == 'pandapower' and PANDAPOWER_AVAILABLE:
285
+ ppc = ams.io.pypower.system2ppc(system)
286
+ ppn = pdp.converter.from_ppc(ppc, f_hz=system.config.freq)
287
+ p_mw0 = ppn.load['p_mw'].copy()
288
+ t_all, _ = elapsed()
289
+ obj_all = 0
290
+ for lf_k in load_factors:
291
+ ppn.load['p_mw'] = lf_k * p_mw0
292
+ _, obj = time_pdp_dcopf(ppn)
293
+ obj_all += obj
294
+ _, s_all = elapsed(t_all)
295
+ s = float(s_all.split(' ')[0])
296
+ sol[solver]['time'] = s
297
+ sol[solver]['obj'] = obj_all
298
+ else:
299
+ sol[solver]['time'] = _failed_time
300
+ sol[solver]['obj'] = _failed_obj
301
+
302
+ return pre_time, sol
@@ -29,6 +29,12 @@ def create_parser():
29
29
  -------
30
30
  argparse.ArgumentParser
31
31
  Parser with all AMS options
32
+
33
+ Notes
34
+ -----
35
+ Revised from the ANDES project (https://github.com/CURENT/andes).
36
+ Original author: Hantao Cui
37
+ License: GPL3
32
38
  """
33
39
 
34
40
  parser = argparse.ArgumentParser()
@@ -10,11 +10,11 @@ from typing import Optional
10
10
  import numpy as np
11
11
 
12
12
  from andes.thirdparty.npfunc import safe_div
13
- from andes.shared import pd, tqdm, tqdm_nb
13
+ from andes.shared import tqdm, tqdm_nb
14
14
  from andes.utils.misc import elapsed, is_notebook
15
15
 
16
16
  from ams.opt.omodel import Param
17
- from ams.shared import sps
17
+ from ams.shared import pd, sps
18
18
 
19
19
  logger = logging.getLogger(__name__)
20
20
 
@@ -186,19 +186,33 @@ class MatProcessor:
186
186
  info='Line outage distribution factor',
187
187
  v=None, sparse=False, owner=self)
188
188
 
189
- def build(self):
189
+ def build(self, force=False):
190
190
  """
191
191
  Build the system matrices.
192
192
  It build connectivity matrices first: Cg, Cl, Csh, Cft, and CftT.
193
193
  Then build bus matrices: Bf, Bbus, Pfinj, and Pbusinj.
194
194
 
195
+ Parameters
196
+ ----------
197
+ force : bool, optional
198
+ If True, force to rebuild the matrices. Default is False.
199
+
200
+ Notes
201
+ -----
202
+ Generator online status is NOT considered in its connectivity matrix.
203
+ The same applies for load, line, and shunt.
204
+
195
205
  Returns
196
206
  -------
197
207
  initialized : bool
198
208
  True if the matrices are built successfully.
199
209
  """
200
- t_mat, _ = elapsed()
210
+ if not force and self.initialized:
211
+ logger.debug("System matrices are already built.")
212
+ return self.initialized
201
213
 
214
+ t_mat, _ = elapsed()
215
+ logger.warning("Building system matrices")
202
216
  # --- connectivity matrices ---
203
217
  _ = self.build_cg()
204
218
  _ = self.build_cl()
@@ -212,7 +226,7 @@ class MatProcessor:
212
226
  _ = self.build_pbusinj()
213
227
  _, s_mat = elapsed(t_mat)
214
228
 
215
- logger.debug(f"Built system matrices in {s_mat}.")
229
+ logger.debug(f" -> System matrices built in {s_mat}")
216
230
  self.initialized = True
217
231
  return self.initialized
218
232
 
@@ -139,7 +139,6 @@ class RParam(Param):
139
139
  self.expand_dims = expand_dims
140
140
  self.no_parse = no_parse
141
141
  self.owner = None # instance of the owner model or group
142
- self.rtn = None # instance of the owner routine
143
142
  self.is_ext = False # indicate if the value is set externally
144
143
  self._v = None # external value
145
144
  if v is not None:
@@ -197,7 +196,12 @@ class RParam(Param):
197
196
  """
198
197
  Return the shape of the parameter.
199
198
  """
200
- return np.shape(self.v)
199
+ if self.is_ext:
200
+ return np.shape(self._v)
201
+ elif self.no_parse:
202
+ return None
203
+ else:
204
+ return np.shape(self.v)
201
205
 
202
206
  @property
203
207
  def dtype(self):
@@ -178,7 +178,7 @@ class ROperationService(RBaseService):
178
178
 
179
179
  class LoadScale(ROperationService):
180
180
  """
181
- Return load.
181
+ Get zonal load by scale nodal load given the corresponding load scale factor.
182
182
 
183
183
  Parameters
184
184
  ----------
@@ -218,11 +218,12 @@ class LoadScale(ROperationService):
218
218
  def v(self):
219
219
  sys = self.rtn.system
220
220
  u_idx = self.u.get_idx()
221
+ ue = self.u.owner.get(src='u', attr='v', idx=u_idx)
221
222
  u_bus = self.u.owner.get(src='bus', attr='v', idx=u_idx)
222
223
  u_zone = sys.Bus.get(src='zone', attr='v', idx=u_bus)
223
224
  u_yloc = np.array(sys.Region.idx2uid(u_zone))
224
225
  p0s = np.multiply(self.sd.v[:, u_yloc].transpose(),
225
- self.u.v[:, np.newaxis])
226
+ (ue * self.u.v)[:, np.newaxis])
226
227
  if self.sparse:
227
228
  return spr.csr_matrix(p0s)
228
229
  return p0s
@@ -9,6 +9,7 @@ from collections import OrderedDict
9
9
 
10
10
  import sympy as sp
11
11
 
12
+ from andes.utils.misc import elapsed
12
13
  from ams.core.matprocessor import MatProcessor
13
14
 
14
15
  logger = logging.getLogger(__name__)
@@ -85,6 +86,8 @@ class SymProcessor:
85
86
 
86
87
  # mapping dict for evaluating expressions
87
88
  self.val_map = OrderedDict([
89
+ (r'(== 0|<= 0)$', ''), # remove the comparison operator
90
+ (r'cp\.(Minimize|Maximize)', r'float'), # remove cp.Minimize/Maximize
88
91
  (r'\bcp.\b', 'np.'),
89
92
  ])
90
93
 
@@ -107,9 +110,12 @@ class SymProcessor:
107
110
  """
108
111
  Generate symbols for all variables.
109
112
  """
110
- if not force_generate and self.parent._syms:
113
+ logger.debug(f'Entering symbol generation for <{self.parent.class_name}>')
114
+
115
+ if (not force_generate) and self.parent._syms:
116
+ logger.debug(' - Symbols already generated')
111
117
  return True
112
- logger.debug(f'- Generating symbols for {self.parent.class_name}')
118
+ t, _ = elapsed()
113
119
 
114
120
  # process tex_names defined in routines
115
121
  # -----------------------------------------------------------
@@ -186,8 +192,10 @@ class SymProcessor:
186
192
  self.inputs_dict['sys_mva'] = sp.symbols('sys_mva')
187
193
 
188
194
  self.parent._syms = True
195
+ _, s = elapsed(t)
189
196
 
190
- return True
197
+ logger.debug(f' - Symbols generated in {s}')
198
+ return self.parent._syms
191
199
 
192
200
  def _check_expr_symbols(self, expr):
193
201
  """