ltbams 0.9.5__tar.gz → 0.9.6__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 (174) hide show
  1. {ltbams-0.9.5/ltbams.egg-info → ltbams-0.9.6}/PKG-INFO +1 -1
  2. {ltbams-0.9.5 → ltbams-0.9.6}/ams/_version.py +3 -3
  3. ltbams-0.9.6/ams/core/matprocessor.py +518 -0
  4. {ltbams-0.9.5 → ltbams-0.9.6}/ams/interop/andes.py +81 -15
  5. {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/group.py +3 -3
  6. ltbams-0.9.6/ams/models/line.py +210 -0
  7. {ltbams-0.9.5 → ltbams-0.9.6}/ams/opt/omodel.py +10 -13
  8. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/routines/pflow.py +1 -2
  9. {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/acopf.py +51 -89
  10. {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/dcopf.py +66 -0
  11. {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/dcpf.py +29 -32
  12. {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/pflow.py +3 -11
  13. {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/routine.py +54 -34
  14. {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/rted.py +27 -16
  15. {ltbams-0.9.5 → ltbams-0.9.6}/ams/system.py +5 -0
  16. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/release-notes.rst +20 -0
  17. {ltbams-0.9.5 → ltbams-0.9.6/ltbams.egg-info}/PKG-INFO +1 -1
  18. {ltbams-0.9.5 → ltbams-0.9.6}/ltbams.egg-info/SOURCES.txt +1 -0
  19. {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_andes.py +93 -12
  20. ltbams-0.9.6/tests/test_mats.py +183 -0
  21. ltbams-0.9.6/tests/test_routine.py +175 -0
  22. {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_service.py +1 -43
  23. ltbams-0.9.5/ams/core/matprocessor.py +0 -281
  24. ltbams-0.9.5/ams/models/line.py +0 -41
  25. ltbams-0.9.5/tests/test_routine.py +0 -95
  26. {ltbams-0.9.5 → ltbams-0.9.6}/CONTRIBUTING.rst +0 -0
  27. {ltbams-0.9.5 → ltbams-0.9.6}/LICENSE +0 -0
  28. {ltbams-0.9.5 → ltbams-0.9.6}/MANIFEST.in +0 -0
  29. {ltbams-0.9.5 → ltbams-0.9.6}/README.md +0 -0
  30. {ltbams-0.9.5 → ltbams-0.9.6}/ams/__init__.py +0 -0
  31. {ltbams-0.9.5 → ltbams-0.9.6}/ams/__main__.py +0 -0
  32. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/5bus/pjm5bus_demo.xlsx +0 -0
  33. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/5bus/pjm5bus_uced.json +0 -0
  34. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/5bus/pjm5bus_uced.xlsx +0 -0
  35. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/5bus/pjm5bus_uced_esd1.xlsx +0 -0
  36. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee123/ieee123.xlsx +0 -0
  37. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee123/ieee123_regcv1.xlsx +0 -0
  38. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee14/ieee14.json +0 -0
  39. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee14/ieee14.raw +0 -0
  40. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee14/ieee14_uced.xlsx +0 -0
  41. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee39/ieee39.xlsx +0 -0
  42. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee39/ieee39_uced.xlsx +0 -0
  43. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee39/ieee39_uced_esd1.xlsx +0 -0
  44. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee39/ieee39_uced_pvd1.xlsx +0 -0
  45. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/ieee39/ieee39_uced_vis.xlsx +0 -0
  46. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/matpower/case118.m +0 -0
  47. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/matpower/case14.m +0 -0
  48. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/matpower/case300.m +0 -0
  49. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/matpower/case39.m +0 -0
  50. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/matpower/case5.m +0 -0
  51. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/matpower/case_ACTIVSg2000.m +0 -0
  52. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/npcc/npcc.m +0 -0
  53. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/npcc/npcc_uced.xlsx +0 -0
  54. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/pglib/pglib_opf_case39_epri__api.m +0 -0
  55. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/wecc/wecc.m +0 -0
  56. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cases/wecc/wecc_uced.xlsx +0 -0
  57. {ltbams-0.9.5 → ltbams-0.9.6}/ams/cli.py +0 -0
  58. {ltbams-0.9.5 → ltbams-0.9.6}/ams/core/__init__.py +0 -0
  59. {ltbams-0.9.5 → ltbams-0.9.6}/ams/core/documenter.py +0 -0
  60. {ltbams-0.9.5 → ltbams-0.9.6}/ams/core/model.py +0 -0
  61. {ltbams-0.9.5 → ltbams-0.9.6}/ams/core/param.py +0 -0
  62. {ltbams-0.9.5 → ltbams-0.9.6}/ams/core/service.py +0 -0
  63. {ltbams-0.9.5 → ltbams-0.9.6}/ams/core/symprocessor.py +0 -0
  64. {ltbams-0.9.5 → ltbams-0.9.6}/ams/core/var.py +0 -0
  65. {ltbams-0.9.5 → ltbams-0.9.6}/ams/interop/__init__.py +0 -0
  66. {ltbams-0.9.5 → ltbams-0.9.6}/ams/io/__init__.py +0 -0
  67. {ltbams-0.9.5 → ltbams-0.9.6}/ams/io/json.py +0 -0
  68. {ltbams-0.9.5 → ltbams-0.9.6}/ams/io/matpower.py +0 -0
  69. {ltbams-0.9.5 → ltbams-0.9.6}/ams/io/psse.py +0 -0
  70. {ltbams-0.9.5 → ltbams-0.9.6}/ams/io/pypower.py +0 -0
  71. {ltbams-0.9.5 → ltbams-0.9.6}/ams/io/xlsx.py +0 -0
  72. {ltbams-0.9.5 → ltbams-0.9.6}/ams/main.py +0 -0
  73. {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/__init__.py +0 -0
  74. {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/area.py +0 -0
  75. {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/bus.py +0 -0
  76. {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/cost.py +0 -0
  77. {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/distributed/__init__.py +0 -0
  78. {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/distributed/esd1.py +0 -0
  79. {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/distributed/pvd1.py +0 -0
  80. {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/info.py +0 -0
  81. {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/region.py +0 -0
  82. {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/renewable/__init__.py +0 -0
  83. {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/renewable/regc.py +0 -0
  84. {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/reserve.py +0 -0
  85. {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/shunt.py +0 -0
  86. {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/static/__init__.py +0 -0
  87. {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/static/gen.py +0 -0
  88. {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/static/pq.py +0 -0
  89. {ltbams-0.9.5 → ltbams-0.9.6}/ams/models/timeslot.py +0 -0
  90. {ltbams-0.9.5 → ltbams-0.9.6}/ams/opt/__init__.py +0 -0
  91. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/__init__.py +0 -0
  92. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/_compat.py +0 -0
  93. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/core/__init__.py +0 -0
  94. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/core/pips.py +0 -0
  95. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/core/ppoption.py +0 -0
  96. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/core/ppver.py +0 -0
  97. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/core/solver.py +0 -0
  98. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/eps.py +0 -0
  99. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/idx.py +0 -0
  100. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/io.py +0 -0
  101. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/make/__init__.py +0 -0
  102. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/make/matrices.py +0 -0
  103. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/make/pdv.py +0 -0
  104. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/routines/__init__.py +0 -0
  105. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/routines/cpf.py +0 -0
  106. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/routines/cpf_callbacks.py +0 -0
  107. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/routines/opf.py +0 -0
  108. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/routines/opffcns.py +0 -0
  109. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/toggle.py +0 -0
  110. {ltbams-0.9.5 → ltbams-0.9.6}/ams/pypower/utils.py +0 -0
  111. {ltbams-0.9.5 → ltbams-0.9.6}/ams/report.py +0 -0
  112. {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/__init__.py +0 -0
  113. {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/cpf.py +0 -0
  114. {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/dopf.py +0 -0
  115. {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/ed.py +0 -0
  116. {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/type.py +0 -0
  117. {ltbams-0.9.5 → ltbams-0.9.6}/ams/routines/uc.py +0 -0
  118. {ltbams-0.9.5 → ltbams-0.9.6}/ams/shared.py +0 -0
  119. {ltbams-0.9.5 → ltbams-0.9.6}/ams/utils/__init__.py +0 -0
  120. {ltbams-0.9.5 → ltbams-0.9.6}/ams/utils/paths.py +0 -0
  121. {ltbams-0.9.5 → ltbams-0.9.6}/docs/Makefile +0 -0
  122. {ltbams-0.9.5 → ltbams-0.9.6}/docs/make.bat +0 -0
  123. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/_templates/autosummary/base.rst +0 -0
  124. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/_templates/autosummary/class.rst +0 -0
  125. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/_templates/autosummary/module.rst +0 -0
  126. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/_templates/autosummary/module_toctree.rst +0 -0
  127. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/api.rst +0 -0
  128. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/conf.py +0 -0
  129. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/examples/index.rst +0 -0
  130. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/copyright.rst +0 -0
  131. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/formats/index.rst +0 -0
  132. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/formats/matpower.rst +0 -0
  133. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/formats/psse.rst +0 -0
  134. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/formats/pypower.rst +0 -0
  135. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/formats/xlsx.png +0 -0
  136. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/formats/xlsx.rst +0 -0
  137. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/index.rst +0 -0
  138. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/install.rst +0 -0
  139. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/overview.rst +0 -0
  140. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/testcase.rst +0 -0
  141. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/getting_started/verification.rst +0 -0
  142. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/images/dcopf_time.png +0 -0
  143. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/images/sponsors/CURENT_Logo_NameOnTrans.png +0 -0
  144. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/images/sponsors/CURENT_Logo_Transparent.png +0 -0
  145. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/images/sponsors/CURENT_Logo_Transparent_Name.png +0 -0
  146. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/images/sponsors/doe.png +0 -0
  147. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/index.rst +0 -0
  148. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/modeling/example.rst +0 -0
  149. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/modeling/index.rst +0 -0
  150. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/modeling/model.rst +0 -0
  151. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/modeling/routine.rst +0 -0
  152. {ltbams-0.9.5 → ltbams-0.9.6}/docs/source/modeling/system.rst +0 -0
  153. {ltbams-0.9.5 → ltbams-0.9.6}/ltbams.egg-info/dependency_links.txt +0 -0
  154. {ltbams-0.9.5 → ltbams-0.9.6}/ltbams.egg-info/entry_points.txt +0 -0
  155. {ltbams-0.9.5 → ltbams-0.9.6}/ltbams.egg-info/requires.txt +0 -0
  156. {ltbams-0.9.5 → ltbams-0.9.6}/ltbams.egg-info/top_level.txt +0 -0
  157. {ltbams-0.9.5 → ltbams-0.9.6}/requirements-extra.txt +0 -0
  158. {ltbams-0.9.5 → ltbams-0.9.6}/requirements.txt +0 -0
  159. {ltbams-0.9.5 → ltbams-0.9.6}/setup.cfg +0 -0
  160. {ltbams-0.9.5 → ltbams-0.9.6}/setup.py +0 -0
  161. {ltbams-0.9.5 → ltbams-0.9.6}/tests/__init__.py +0 -0
  162. {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_1st_system.py +0 -0
  163. {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_addressing.py +0 -0
  164. {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_case.py +0 -0
  165. {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_cli.py +0 -0
  166. {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_dctypes.py +0 -0
  167. {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_export_csv.py +0 -0
  168. {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_group.py +0 -0
  169. {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_known_good.py +0 -0
  170. {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_model.py +0 -0
  171. {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_paths.py +0 -0
  172. {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_report.py +0 -0
  173. {ltbams-0.9.5 → ltbams-0.9.6}/tests/test_repr.py +0 -0
  174. {ltbams-0.9.5 → ltbams-0.9.6}/versioneer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ltbams
3
- Version: 0.9.5
3
+ Version: 0.9.6
4
4
  Summary: Python software for dispatch modeling and co-simulation with dynanic.
5
5
  Home-page: https://github.com/CURENT/ams
6
6
  Author: Jinning Wang
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2024-03-25T22:06:15-0400",
11
+ "date": "2024-04-21T17:14:28-0400",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "90e045b3cde4ad6b5bd3b3eb1a9302a1918d5199",
15
- "version": "0.9.5"
14
+ "full-revisionid": "fcc7e579c8f7453fae3ddebbd0eedbe4e463c1c9",
15
+ "version": "0.9.6"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -0,0 +1,518 @@
1
+ """
2
+ Module for system matrix make.
3
+ """
4
+
5
+ import logging
6
+ from typing import Optional
7
+
8
+ import numpy as np
9
+
10
+ from scipy.sparse import csr_matrix as c_sparse
11
+ from scipy.sparse import csc_matrix as csc_sparse
12
+ from scipy.sparse import lil_matrix as l_sparse
13
+
14
+ from andes.utils.misc import elapsed
15
+ from andes.thirdparty.npfunc import safe_div
16
+
17
+ from ams.opt.omodel import Param
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+
22
+ class MParam(Param):
23
+ """
24
+ Class for matrix parameters built from the system.
25
+
26
+ MParam is designed to be a subclass of RParam for routine parameters
27
+ management.
28
+
29
+ Parameters
30
+ ----------
31
+ name : str, optional
32
+ Name of this parameter. If not provided, `name` will be set
33
+ to the attribute name.
34
+ tex_name : str, optional
35
+ LaTeX-formatted parameter name. If not provided, `tex_name`
36
+ will be assigned the same as `name`.
37
+ info : str, optional
38
+ A description of this parameter
39
+ unit : str, optional
40
+ Unit of the parameter.
41
+ v : np.ndarray, optional
42
+ Matrix value of the parameter.
43
+ owner : object, optional
44
+ Owner of the MParam, usually the MatProcessor instance.
45
+ """
46
+
47
+ def __init__(self,
48
+ name: Optional[str] = None,
49
+ tex_name: Optional[str] = None,
50
+ info: Optional[str] = None,
51
+ unit: Optional[str] = None,
52
+ v: Optional[np.ndarray] = None,
53
+ sparse: Optional[bool] = False,
54
+ ):
55
+ self.name = name
56
+ self.tex_name = tex_name if (tex_name is not None) else name
57
+ self.info = info
58
+ self.unit = unit
59
+ self._v = v
60
+ self.sparse = sparse
61
+ self.owner = None
62
+
63
+ @property
64
+ def v(self):
65
+ """
66
+ Return the value of the parameter.
67
+ """
68
+ # NOTE: scipy.sparse matrix will return 2D array
69
+ # so we squeeze it here if only one row
70
+ if isinstance(self._v, (c_sparse, l_sparse, csc_sparse)):
71
+ out = self._v.toarray()
72
+ if out.shape[0] == 1:
73
+ return np.squeeze(out)
74
+ else:
75
+ return out
76
+ return self._v
77
+
78
+ @property
79
+ def shape(self):
80
+ """
81
+ Return the shape of the parameter.
82
+ """
83
+ return self.v.shape
84
+
85
+ @property
86
+ def n(self):
87
+ """
88
+ Return the szie of the parameter.
89
+ """
90
+ return len(self.v)
91
+
92
+ @property
93
+ def class_name(self):
94
+ """
95
+ Return the class name
96
+ """
97
+ return self.__class__.__name__
98
+
99
+
100
+ class MatProcessor:
101
+ """
102
+ Class for matrix processing in AMS system.
103
+ """
104
+
105
+ def __init__(self, system):
106
+ self.system = system
107
+ self.initialized = False
108
+
109
+ self.Cft = MParam(name='Cft', tex_name=r'C_{ft}',
110
+ info='Line connectivity matrix',
111
+ v=None, sparse=True)
112
+ self.CftT = MParam(name='CftT', tex_name=r'C_{ft}^{T}',
113
+ info='Line connectivity matrix transpose',
114
+ v=None, sparse=True)
115
+ self.Cg = MParam(name='Cg', tex_name=r'C_g',
116
+ info='Generator connectivity matrix',
117
+ v=None, sparse=True)
118
+ self.Cl = MParam(name='Cl', tex_name=r'Cl',
119
+ info='Load connectivity matrix',
120
+ v=None, sparse=True)
121
+ self.Csh = MParam(name='Csh', tex_name=r'C_{sh}',
122
+ info='Shunt connectivity matrix',
123
+ v=None, sparse=True)
124
+
125
+ self.Bbus = MParam(name='Bbus', tex_name=r'B_{bus}',
126
+ info='Bus admittance matrix',
127
+ v=None, sparse=True)
128
+ self.Bf = MParam(name='Bf', tex_name=r'B_{f}',
129
+ info='Bf matrix',
130
+ v=None, sparse=True)
131
+ self.Pbusinj = MParam(name='Pbusinj', tex_name=r'P_{bus}^{inj}',
132
+ info='Bus power injection vector',
133
+ v=None,)
134
+ self.Pfinj = MParam(name='Pfinj', tex_name=r'P_{f}^{inj}',
135
+ info='Line power injection vector',
136
+ v=None,)
137
+
138
+ self.PTDF = MParam(name='PTDF', tex_name=r'P_{TDF}',
139
+ info='Power transfer distribution factor',
140
+ v=None)
141
+ self.LODF = MParam(name='LODF', tex_name=r'O_{TDF}',
142
+ info='Line outage distribution factor',
143
+ v=None)
144
+
145
+ def build(self):
146
+ """
147
+ Build the system matrices.
148
+ It build connectivity matrices first: Cg, Cl, Csh, Cft, and CftT.
149
+ Then build bus matrices: Bf, Bbus, Pfinj, and Pbusinj.
150
+
151
+ Returns
152
+ -------
153
+ initialized : bool
154
+ True if the matrices are built successfully.
155
+ """
156
+ t_mat, _ = elapsed()
157
+
158
+ # --- connectivity matrices ---
159
+ _ = self.build_cg()
160
+ _ = self.build_cl()
161
+ _ = self.build_csh()
162
+ _ = self.build_cft()
163
+
164
+ # --- bus matrices ---
165
+ _ = self.build_bf()
166
+ _ = self.build_bbus()
167
+ _ = self.build_pfinj()
168
+ _ = self.build_pbusinj()
169
+ _, s_mat = elapsed(t_mat)
170
+
171
+ logger.debug(f"Built system matrices in {s_mat}.")
172
+ self.initialized = True
173
+ return self.initialized
174
+
175
+ @property
176
+ def class_name(self):
177
+ """
178
+ Return the class name
179
+ """
180
+ return self.__class__.__name__
181
+
182
+ @property
183
+ def n(self):
184
+ """
185
+ To fit the RParam style.
186
+ """
187
+ return 2
188
+
189
+ def build_cg(self):
190
+ """
191
+ Build generator connectivity matrix Cg, and store it in the MParam `Cg`.
192
+
193
+ Returns
194
+ -------
195
+ Cg : scipy.sparse.csr_matrix
196
+ Generator connectivity matrix.
197
+ """
198
+ system = self.system
199
+
200
+ # common variables
201
+ nb = system.Bus.n
202
+ ng = system.StaticGen.n
203
+
204
+ # bus indices: idx -> uid
205
+ idx_gen = system.StaticGen.get_idx()
206
+ u_gen = system.StaticGen.get(src='u', attr='v', idx=idx_gen)
207
+ on_gen = np.flatnonzero(u_gen) # uid of online generators
208
+ on_gen_idx = [idx_gen[i] for i in on_gen] # idx of online generators
209
+ on_gen_bus = system.StaticGen.get(src='bus', attr='v', idx=on_gen_idx)
210
+
211
+ row = np.array([system.Bus.idx2uid(x) for x in on_gen_bus])
212
+ col = np.array([idx_gen.index(x) for x in on_gen_idx])
213
+ self.Cg._v = c_sparse((np.ones(len(on_gen_idx)), (row, col)), (nb, ng))
214
+ return self.Cg._v
215
+
216
+ def build_cl(self):
217
+ """
218
+ Build load connectivity matrix Cl, and store it in the MParam `Cl`.
219
+
220
+ Returns
221
+ -------
222
+ Cl : scipy.sparse.csr_matrix
223
+ Load connectivity matrix.
224
+ """
225
+ system = self.system
226
+
227
+ # common variables
228
+ nb = system.Bus.n
229
+ npq = system.PQ.n
230
+
231
+ # load indices: idx -> uid
232
+ idx_load = system.PQ.idx.v
233
+ u_load = system.PQ.get(src='u', attr='v', idx=idx_load)
234
+ on_load = np.flatnonzero(u_load)
235
+ on_load_idx = [idx_load[i] for i in on_load]
236
+ on_load_bus = system.PQ.get(src='bus', attr='v', idx=on_load_idx)
237
+
238
+ row = np.array([system.Bus.idx2uid(x) for x in on_load_bus])
239
+ col = np.array([system.PQ.idx2uid(x) for x in on_load_idx])
240
+ self.Cl._v = c_sparse((np.ones(len(on_load_idx)), (row, col)), (nb, npq))
241
+ return self.Cl._v
242
+
243
+ def build_csh(self):
244
+ """
245
+ Build shunt connectivity matrix Csh, and store it in the MParam `Csh`.
246
+
247
+ Returns
248
+ -------
249
+ Csh : spmatrix
250
+ Shunt connectivity matrix.
251
+ """
252
+ system = self.system
253
+
254
+ # common variables
255
+ nb = system.Bus.n
256
+ nsh = system.Shunt.n
257
+
258
+ # shunt indices: idx -> uid
259
+ idx_shunt = system.Shunt.idx.v
260
+ u_shunt = system.Shunt.get(src='u', attr='v', idx=idx_shunt)
261
+ on_shunt = np.flatnonzero(u_shunt)
262
+ on_shunt_idx = [idx_shunt[i] for i in on_shunt]
263
+ on_shunt_bus = system.Shunt.get(src='bus', attr='v', idx=on_shunt_idx)
264
+
265
+ row = np.array([system.Bus.idx2uid(x) for x in on_shunt_bus])
266
+ col = np.array([system.Shunt.idx2uid(x) for x in on_shunt_idx])
267
+ self.Csh._v = c_sparse((np.ones(len(on_shunt_idx)), (row, col)), (nb, nsh))
268
+ return self.Csh._v
269
+
270
+ def build_cft(self):
271
+ """
272
+ Build line connectivity matrix Cft and its transpose CftT.
273
+ The Cft and CftT are stored in the MParam `Cft` and `CftT`, respectively.
274
+
275
+ Returns
276
+ -------
277
+ Cft : scipy.sparse.csr_matrix
278
+ Line connectivity matrix.
279
+ """
280
+ system = self.system
281
+
282
+ # common variables
283
+ nb = system.Bus.n
284
+ nl = system.Line.n
285
+
286
+ # line indices: idx -> uid
287
+ idx_line = system.Line.idx.v
288
+ u_line = system.Line.get(src='u', attr='v', idx=idx_line)
289
+ on_line = np.flatnonzero(u_line)
290
+ on_line_idx = [idx_line[i] for i in on_line]
291
+ on_line_bus1 = system.Line.get(src='bus1', attr='v', idx=on_line_idx)
292
+ on_line_bus2 = system.Line.get(src='bus2', attr='v', idx=on_line_idx)
293
+
294
+ data_line = np.ones(2*len(on_line_idx))
295
+ data_line[len(on_line_idx):] = -1
296
+ row_line = np.array([system.Bus.idx2uid(x) for x in on_line_bus1 + on_line_bus2])
297
+ col_line = np.array([system.Line.idx2uid(x) for x in on_line_idx + on_line_idx])
298
+ self.Cft._v = c_sparse((data_line, (row_line, col_line)), (nb, nl))
299
+ self.CftT._v = self.Cft._v.T
300
+ return self.Cft._v
301
+
302
+ def build_bf(self):
303
+ """
304
+ Build DC Bf matrix and store it in the MParam `Bf`.
305
+
306
+ Returns
307
+ -------
308
+ Bf : scipy.sparse.csr_matrix
309
+ Bf matrix.
310
+ """
311
+ system = self.system
312
+
313
+ # common variables
314
+ nb = system.Bus.n
315
+ nl = system.Line.n
316
+
317
+ # line parameters
318
+ idx_line = system.Line.idx.v
319
+ b = self._calc_b()
320
+
321
+ # build Bf such that Bf * Va is the vector of real branch powers injected
322
+ # at each branch's "from" bus
323
+ f = system.Bus.idx2uid(system.Line.get(src='bus1', attr='v', idx=idx_line))
324
+ t = system.Bus.idx2uid(system.Line.get(src='bus2', attr='v', idx=idx_line))
325
+ ir = np.r_[range(nl), range(nl)] # double set of row indices
326
+ self.Bf._v = c_sparse((np.r_[b, -b], (ir, np.r_[f, t])), (nl, nb))
327
+ return self.Bf._v
328
+
329
+ def build_bbus(self):
330
+ """
331
+ Build Bdc matrix and store it in the MParam `Bbus`.
332
+
333
+ Returns
334
+ -------
335
+ Bdc : scipy.sparse.csr_matrix
336
+ DC bus admittance matrix.
337
+ """
338
+ self.Bbus._v = self.Cft._v * self.Bf._v
339
+ return self.Bbus._v
340
+
341
+ def build_pfinj(self):
342
+ """
343
+ Build DC Pfinj vector and store it in the MParam `Pfinj`.
344
+
345
+ Returns
346
+ -------
347
+ Pfinj : np.ndarray
348
+ Line power injection vector.
349
+ """
350
+ idx_line = self.system.Line.idx.v
351
+ b = self._calc_b()
352
+ phi = self.system.Line.get(src='phi', attr='v', idx=idx_line)
353
+ self.Pfinj._v = b * (-phi)
354
+ return self.Pfinj._v
355
+
356
+ def build_pbusinj(self):
357
+ """
358
+ Build DC Pbusinj vector and store it in the MParam `Pbusinj`.
359
+
360
+ Returns
361
+ -------
362
+ Pbusinj : np.ndarray
363
+ Bus power injection vector.
364
+ """
365
+ self.Pbusinj._v = self.Cft._v * self.Pfinj._v
366
+ return self.Pbusinj._v
367
+
368
+ def _calc_b(self):
369
+ """
370
+ Calculate DC series susceptance for each line.
371
+
372
+ Returns
373
+ -------
374
+ b : np.ndarray
375
+ Series susceptance for each line.
376
+ """
377
+ system = self.system
378
+ nl = system.Line.n
379
+
380
+ # line parameters
381
+ idx_line = system.Line.idx.v
382
+ x = system.Line.get(src='x', attr='v', idx=idx_line)
383
+ u_line = system.Line.get(src='u', attr='v', idx=idx_line)
384
+ b = u_line / x # series susceptance
385
+
386
+ # in DC, tap is assumed to be 1
387
+ tap0 = system.Line.get(src='tap', attr='v', idx=idx_line)
388
+ tap = np.ones(nl)
389
+ i = np.flatnonzero(tap0)
390
+ tap[i] = tap0[i] # assign non-zero tap ratios
391
+ b = b / tap # adjusted series susceptance
392
+
393
+ return b
394
+
395
+ def build_ptdf(self):
396
+ """
397
+ Build the DC PTDF matrix and store it in the MParam `PTDF`.
398
+
399
+ `PTDF[m, n]` means the increased line flow on line `m` when there is
400
+ 1 p.u. power injection at bus `n`.
401
+
402
+ It requires DC Bbus and Bf.
403
+
404
+ Note that there is discrepency between the PTDF-based line flow and
405
+ DCOPF calcualted line flow. The gap is ignorable for small cases.
406
+
407
+ Returns
408
+ -------
409
+ PTDF : np.ndarray
410
+ Power transfer distribution factor.
411
+ """
412
+ system = self.system
413
+
414
+ # common variables
415
+ nb = system.Bus.n
416
+ nl = system.Line.n
417
+
418
+ # use first slack bus as reference slack bus
419
+ slack = system.Slack.bus.v[0]
420
+
421
+ # use first bus for voltage angle reference
422
+ noref_idx = system.Bus.idx.v[1:]
423
+ noref = system.Bus.idx2uid(noref_idx)
424
+
425
+ noslack = [system.Bus.idx2uid(bus) for bus in system.Bus.idx.v if bus != slack]
426
+
427
+ # build other matrices if not built
428
+ if not self.initialized:
429
+ logger.debug("System matrices are not built. Building now.")
430
+ self.build()
431
+ # use dense representation
432
+ Bbus, Bf = self.Bbus.v, self.Bf.v
433
+
434
+ # initialize PTDF matrix
435
+ H = np.zeros((nl, nb))
436
+ # calculate PTDF
437
+ H[:, noslack] = np.linalg.solve(Bbus[np.ix_(noslack, noref)].T, Bf[:, noref].T).T
438
+ # store PTDF
439
+ self.PTDF._v = H
440
+
441
+ return self.PTDF._v
442
+
443
+ def build_lodf(self):
444
+ """
445
+ Build the DC LODF matrix and store it in the MParam `LODF`.
446
+
447
+ `LODF[m, n]` means the increased line flow on line `m` when there is
448
+ 1 p.u. line flow decrease on line `n` due to line `n` outage.
449
+
450
+ It requires DC PTDF and Cft.
451
+
452
+ Returns
453
+ -------
454
+ LODF : np.ndarray
455
+ Line outage distribution factor.
456
+ """
457
+ system = self.system
458
+
459
+ # common variables
460
+ nl = system.Line.n
461
+
462
+ # build PTDF if not built
463
+ if self.PTDF._v is None:
464
+ self.build_ptdf()
465
+
466
+ H = self.PTDF._v * self.Cft._v
467
+ h = np.diag(H, 0)
468
+ LODF = safe_div(H, np.ones((nl, nl)) - np.ones((nl, 1)) * h.T)
469
+ LODF = LODF - np.diag(np.diag(LODF)) - np.eye(nl, nl)
470
+
471
+ self.LODF._v = LODF
472
+ return self.LODF._v
473
+
474
+ def build_otdf(self, line=None):
475
+ """
476
+ Build the DC OTDF matrix.
477
+
478
+ `OTDF_k[m, n]` means the PTDF[m, n] with line `k` outage.
479
+
480
+ It requires ... ...
481
+
482
+ Parameters
483
+ ----------
484
+ line : int, str, optional
485
+ Outage line idx to build the OTDF. If not provided, use the
486
+ first line `System.Line.idx.v[0]`.
487
+
488
+ Returns
489
+ -------
490
+ OTDF : np.ndarray
491
+ Line outage distribution factor.
492
+ """
493
+ system = self.system
494
+
495
+ if line is None:
496
+ line = system.Line.idx.v[0]
497
+ elif isinstance(line, list):
498
+ logger.warning("Multiple line is given, only the first one is used.")
499
+ line = line[0]
500
+ line_uid = system.Line.idx2uid(line)
501
+
502
+ # build LODF if not built
503
+ if self.LODF._v is None:
504
+ self.build_lodf()
505
+
506
+ # common variables
507
+ nb = system.Bus.n
508
+ nl = system.Line.n
509
+
510
+ # initialize OTDF matrix
511
+ OTDF = np.zeros((nl, nb))
512
+
513
+ line_lodf = self.LODF._v[:, line_uid] # LODF for the outage line
514
+ line_ptdf = self.PTDF._v[line_uid, :] # PTDF for the outage line
515
+ OTDF += self.PTDF._v # Add PTDF to OTDF
516
+ OTDF += line_lodf[:, np.newaxis] * line_ptdf # Add LODF * PTDF for the outage line
517
+
518
+ return OTDF