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
tests/test_model.py ADDED
@@ -0,0 +1,54 @@
1
+ import unittest
2
+ import numpy as np
3
+
4
+ import ams
5
+
6
+
7
+ class TestModelMethods(unittest.TestCase):
8
+ """
9
+ Test methods of Model.
10
+ """
11
+
12
+ def setUp(self):
13
+ self.ss = ams.run(
14
+ ams.get_case("ieee14/ieee14.json"),
15
+ default_config=True,
16
+ no_output=True,
17
+ )
18
+
19
+ def test_model_set(self):
20
+ """
21
+ Test `Model.set()` method.
22
+ """
23
+
24
+ # set a single value
25
+ self.ss.PQ.set("p0", "PQ_1", "v", 0.25)
26
+ self.assertEqual(self.ss.PQ.p0.v[0], 0.25)
27
+
28
+ # set a list of values
29
+ self.ss.PQ.set("p0", ["PQ_1", "PQ_2"], "v", [0.26, 0.51])
30
+ np.testing.assert_equal(self.ss.PQ.p0.v[[0, 1]], [0.26, 0.51])
31
+
32
+ # set a list of values
33
+ self.ss.PQ.set("p0", ["PQ_3", "PQ_5"], "v", [0.52, 0.16])
34
+ np.testing.assert_equal(self.ss.PQ.p0.v[[2, 4]], [0.52, 0.16])
35
+
36
+ # set a list of idxes with a single element to an array of values
37
+ self.ss.PQ.set("p0", ["PQ_4"], "v", np.array([0.086]))
38
+ np.testing.assert_equal(self.ss.PQ.p0.v[3], 0.086)
39
+
40
+ # set an array of idxes with a single element to an array of values
41
+ self.ss.PQ.set("p0", np.array(["PQ_4"]), "v", np.array([0.096]))
42
+ np.testing.assert_equal(self.ss.PQ.p0.v[3], 0.096)
43
+
44
+ # set an array of idxes with a list of single value
45
+ self.ss.PQ.set("p0", np.array(["PQ_4"]), "v", 0.097)
46
+ np.testing.assert_equal(self.ss.PQ.p0.v[3], 0.097)
47
+
48
+ def test_model_repr(self):
49
+ """
50
+ Test `Model.__repr__()` method.
51
+ """
52
+
53
+ for mdl in self.ss.models.items():
54
+ print(mdl.__repr__())
tests/test_omodel.py ADDED
@@ -0,0 +1,119 @@
1
+ import unittest
2
+
3
+ import ams
4
+
5
+
6
+ class TestOModelWrappers(unittest.TestCase):
7
+ """
8
+ Test wrappers in module `omodel`.
9
+ """
10
+
11
+ def setUp(self) -> None:
12
+ self.ss = ams.load(ams.get_case("matpower/case5.m"),
13
+ setup=True,
14
+ default_config=True,
15
+ no_output=True,
16
+ )
17
+
18
+ def test_ensure_symbols(self):
19
+ """
20
+ Test `ensure_symbols` wrapper.
21
+ """
22
+ self.assertFalse(self.ss.DCOPF._syms, "Symbols should not be ready before generation!")
23
+ self.ss.DCOPF.pd.parse()
24
+ self.assertTrue(self.ss.DCOPF._syms, "Symbols should be ready after generation!")
25
+
26
+ def test_ensure_mats_and_parsed(self):
27
+ """
28
+ Test `ensure_mats_and_parsed` wrapper.
29
+ """
30
+ self.assertFalse(self.ss.mats.initialized, "MatProcessor should not be initialized before initialization!")
31
+ self.assertFalse(self.ss.DCOPF.om.parsed, "OModel should be parsed after parsing!")
32
+ self.ss.DCOPF.pd.evaluate()
33
+ self.assertTrue(self.ss.mats.initialized, "MatProcessor should be initialized after parsing!")
34
+ self.assertTrue(self.ss.DCOPF.om.parsed, "OModle should be parsed after parsing!")
35
+
36
+
37
+ class TestOModel(unittest.TestCase):
38
+ """
39
+ Test class `OModel`.
40
+ """
41
+
42
+ def setUp(self) -> None:
43
+ self.ss = ams.load(ams.get_case("matpower/case5.m"),
44
+ setup=True,
45
+ default_config=True,
46
+ no_output=True,
47
+ )
48
+
49
+ def test_initialized(self):
50
+ """
51
+ Test `OModel` initialization.
52
+ """
53
+ self.assertFalse(self.ss.DCOPF.om.initialized, "OModel shoud not be initialized before initialziation!")
54
+ self.ss.DCOPF.om.init()
55
+ self.assertTrue(self.ss.DCOPF.om.initialized, "OModel should be initialized!")
56
+
57
+ def test_uninitialized_after_nonparametric_update(self):
58
+ """
59
+ Test `OModel` initialization after nonparametric update.
60
+ """
61
+ self.ss.DCOPF.om.init()
62
+ self.assertTrue(self.ss.DCOPF.om.initialized, "OModel should be initialized after initialization!")
63
+ self.ss.DCOPF.update('ug')
64
+ self.assertTrue(self.ss.DCOPF.om.initialized, "OModel should be initialized after nonparametric update!")
65
+
66
+
67
+ class TestOModelrepr(unittest.TestCase):
68
+ """
69
+ Test __repr__ in module `omodel`.
70
+ """
71
+
72
+ def setUp(self) -> None:
73
+ self.ss = ams.load(ams.get_case("5bus/pjm5bus_demo.xlsx"),
74
+ setup=True,
75
+ default_config=True,
76
+ no_output=True,
77
+ )
78
+
79
+ def test_dcopf(self):
80
+ """
81
+ Test `DCOPF.om` __repr__().
82
+ """
83
+ self.ss.DCOPF.om.parse()
84
+ self.assertIsInstance(self.ss.DCOPF.pg.__repr__(), str)
85
+ self.assertIsInstance(self.ss.DCOPF.pmax.__repr__(), str)
86
+ self.assertIsInstance(self.ss.DCOPF.pb.__repr__(), str)
87
+ self.assertIsInstance(self.ss.DCOPF.plflb.__repr__(), str)
88
+ self.assertIsInstance(self.ss.DCOPF.obj.__repr__(), str)
89
+
90
+ def test_rted(self):
91
+ """
92
+ Test `RTED.om` __repr__().
93
+ """
94
+ self.ss.RTED.om.parse()
95
+ self.assertIsInstance(self.ss.RTED.pru.__repr__(), str)
96
+ self.assertIsInstance(self.ss.RTED.R10.__repr__(), str)
97
+ self.assertIsInstance(self.ss.RTED.pru.__repr__(), str)
98
+ self.assertIsInstance(self.ss.RTED.rru.__repr__(), str)
99
+ self.assertIsInstance(self.ss.RTED.obj.__repr__(), str)
100
+
101
+ def test_ed(self):
102
+ """
103
+ Test `ED.om` __repr__().
104
+ """
105
+ self.ss.ED.om.parse()
106
+ self.assertIsInstance(self.ss.ED.prs.__repr__(), str)
107
+ self.assertIsInstance(self.ss.ED.R30.__repr__(), str)
108
+ self.assertIsInstance(self.ss.ED.prsb.__repr__(), str)
109
+ self.assertIsInstance(self.ss.ED.obj.__repr__(), str)
110
+
111
+ def test_uc(self):
112
+ """
113
+ Test `UC.om` __repr__().
114
+ """
115
+ self.ss.UC.om.parse()
116
+ self.assertIsInstance(self.ss.UC.prns.__repr__(), str)
117
+ self.assertIsInstance(self.ss.UC.cdp.__repr__(), str)
118
+ self.assertIsInstance(self.ss.UC.prnsb.__repr__(), str)
119
+ self.assertIsInstance(self.ss.UC.obj.__repr__(), str)
tests/test_paths.py ADDED
@@ -0,0 +1,22 @@
1
+ import unittest
2
+
3
+ import ams
4
+ from ams.utils.paths import list_cases
5
+
6
+
7
+ class TestPaths(unittest.TestCase):
8
+ def setUp(self) -> None:
9
+ self.npcc = 'npcc/'
10
+ self.matpower = 'matpower/'
11
+ self.ieee14 = ams.get_case("ieee14/ieee14.raw")
12
+
13
+ def test_tree(self):
14
+ list_cases(self.npcc, no_print=True)
15
+ list_cases(self.matpower, no_print=True)
16
+
17
+ def test_relative_path(self):
18
+ ss = ams.run('ieee14.raw',
19
+ input_path=ams.get_case('ieee14/', check=False),
20
+ no_output=True, default_config=True,
21
+ )
22
+ self.assertNotEqual(ss, None)
tests/test_report.py ADDED
@@ -0,0 +1,251 @@
1
+ """
2
+ Test system report.
3
+ """
4
+ import unittest
5
+ import os
6
+
7
+ import ams
8
+ from ams.shared import skip_unittest_without_MISOCP
9
+
10
+
11
+ import logging
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+
16
+ class TestReport(unittest.TestCase):
17
+ """
18
+ Tests for Report class.
19
+ """
20
+
21
+ def setUp(self) -> None:
22
+ self.ss = ams.main.load(
23
+ ams.get_case("5bus/pjm5bus_demo.xlsx"),
24
+ default_config=True,
25
+ no_output=True,
26
+ )
27
+ self.expected_report = 'pjm5bus_demo_out.txt'
28
+
29
+ def test_no_output(self):
30
+ """
31
+ Test no output.
32
+ """
33
+ self.assertTrue(self.ss.files.no_output)
34
+ self.assertFalse(self.ss.report())
35
+
36
+ def test_no_report(self):
37
+ """
38
+ Test report with no solved routine.
39
+ """
40
+ self.ss.files.no_output = False
41
+ self.assertTrue(self.ss.report())
42
+ self.assertTrue(os.path.exists(self.expected_report))
43
+
44
+ with open(self.expected_report, "r") as report_file:
45
+ file_contents = report_file.read()
46
+ self.assertNotIn("DCOPF", file_contents)
47
+
48
+ os.remove(self.expected_report)
49
+
50
+ def test_DCOPF_report(self):
51
+ """
52
+ Test report with DCOPF solved.
53
+ """
54
+ self.ss.files.no_output = False
55
+ self.ss.DCOPF.run(solver='CLARABEL')
56
+ self.assertTrue(self.ss.report())
57
+ self.assertTrue(os.path.exists(self.expected_report))
58
+
59
+ with open(self.expected_report, "r") as report_file:
60
+ file_contents = report_file.read()
61
+ self.assertIn("DCOPF", file_contents)
62
+ os.remove(self.expected_report)
63
+
64
+ self.ss.DCOPF.export_csv()
65
+ self.assertTrue(os.path.exists('pjm5bus_demo_DCOPF.csv'))
66
+ os.remove('pjm5bus_demo_DCOPF.csv')
67
+
68
+ def test_DCPF_report(self):
69
+ """
70
+ Test report with DCPF solved.
71
+ """
72
+ self.ss.files.no_output = False
73
+ self.ss.DCPF.run(solver='CLARABEL')
74
+ self.assertTrue(self.ss.report())
75
+ self.assertTrue(os.path.exists(self.expected_report))
76
+
77
+ with open(self.expected_report, "r") as report_file:
78
+ file_contents = report_file.read()
79
+ self.assertIn("DCPF", file_contents)
80
+ os.remove(self.expected_report)
81
+
82
+ self.ss.DCPF.export_csv()
83
+ self.assertTrue(os.path.exists('pjm5bus_demo_DCPF.csv'))
84
+ os.remove('pjm5bus_demo_DCPF.csv')
85
+
86
+ def test_RTED_report(self):
87
+ """
88
+ Test report with RTED solved.
89
+ """
90
+ self.ss.files.no_output = False
91
+ self.ss.RTED.run(solver='CLARABEL')
92
+ self.assertTrue(self.ss.report())
93
+ self.assertTrue(os.path.exists(self.expected_report))
94
+
95
+ with open(self.expected_report, "r") as report_file:
96
+ file_contents = report_file.read()
97
+ self.assertIn("RTED", file_contents)
98
+ os.remove(self.expected_report)
99
+
100
+ self.ss.RTED.export_csv()
101
+ self.assertTrue(os.path.exists('pjm5bus_demo_RTED.csv'))
102
+ os.remove('pjm5bus_demo_RTED.csv')
103
+
104
+ def test_RTEDDG_report(self):
105
+ """
106
+ Test report with RTEDDG solved.
107
+ """
108
+ self.ss.files.no_output = False
109
+ self.ss.RTEDDG.run(solver='CLARABEL')
110
+ self.assertTrue(self.ss.report())
111
+ self.assertTrue(os.path.exists(self.expected_report))
112
+
113
+ with open(self.expected_report, "r") as report_file:
114
+ file_contents = report_file.read()
115
+ self.assertIn("RTEDDG", file_contents)
116
+ os.remove(self.expected_report)
117
+
118
+ self.ss.RTEDDG.export_csv()
119
+ self.assertTrue(os.path.exists('pjm5bus_demo_RTEDDG.csv'))
120
+ os.remove('pjm5bus_demo_RTEDDG.csv')
121
+
122
+ @skip_unittest_without_MISOCP
123
+ def test_RTEDES_report(self):
124
+ """
125
+ Test report with RTEDES solved.
126
+ """
127
+ self.ss.files.no_output = False
128
+ self.ss.RTEDES.run()
129
+ self.assertTrue(self.ss.report())
130
+ self.assertTrue(os.path.exists(self.expected_report))
131
+
132
+ with open(self.expected_report, "r") as report_file:
133
+ file_contents = report_file.read()
134
+ self.assertIn("RTEDES", file_contents)
135
+ os.remove(self.expected_report)
136
+
137
+ self.ss.RTEDES.export_csv()
138
+ self.assertTrue(os.path.exists('pjm5bus_demo_RTEDES.csv'))
139
+ os.remove('pjm5bus_demo_RTEDES.csv')
140
+
141
+ def test_ED_report(self):
142
+ """
143
+ Test report with ED solved.
144
+ """
145
+ self.ss.files.no_output = False
146
+ self.ss.ED.run(solver='CLARABEL')
147
+ self.assertTrue(self.ss.report())
148
+ self.assertTrue(os.path.exists(self.expected_report))
149
+
150
+ with open(self.expected_report, "r") as report_file:
151
+ file_contents = report_file.read()
152
+ self.assertIn("ED", file_contents)
153
+ os.remove(self.expected_report)
154
+
155
+ self.ss.ED.export_csv()
156
+ self.assertTrue(os.path.exists('pjm5bus_demo_ED.csv'))
157
+ os.remove('pjm5bus_demo_ED.csv')
158
+
159
+ def test_EDDG_report(self):
160
+ """
161
+ Test report with EDDG solved.
162
+ """
163
+ self.ss.files.no_output = False
164
+ self.ss.EDDG.run(solver='CLARABEL')
165
+ self.assertTrue(self.ss.report())
166
+ self.assertTrue(os.path.exists(self.expected_report))
167
+
168
+ with open(self.expected_report, "r") as report_file:
169
+ file_contents = report_file.read()
170
+ self.assertIn("EDDG", file_contents)
171
+ os.remove(self.expected_report)
172
+
173
+ self.ss.EDDG.export_csv()
174
+ self.assertTrue(os.path.exists('pjm5bus_demo_EDDG.csv'))
175
+ os.remove('pjm5bus_demo_EDDG.csv')
176
+
177
+ @skip_unittest_without_MISOCP
178
+ def test_EDES_report(self):
179
+ """
180
+ Test report with EDES solved.
181
+ """
182
+ self.ss.files.no_output = False
183
+ self.ss.EDES.run()
184
+ self.assertTrue(self.ss.report())
185
+ self.assertTrue(os.path.exists(self.expected_report))
186
+
187
+ with open(self.expected_report, "r") as report_file:
188
+ file_contents = report_file.read()
189
+ self.assertIn("EDES", file_contents)
190
+ os.remove(self.expected_report)
191
+
192
+ self.ss.EDES.export_csv()
193
+ self.assertTrue(os.path.exists('pjm5bus_demo_EDES.csv'))
194
+ os.remove('pjm5bus_demo_EDES.csv')
195
+
196
+ @skip_unittest_without_MISOCP
197
+ def test_UC_report(self):
198
+ """
199
+ Test report with UC solved.
200
+ """
201
+ self.ss.files.no_output = False
202
+ self.ss.UC.run()
203
+ self.assertTrue(self.ss.report())
204
+ self.assertTrue(os.path.exists(self.expected_report))
205
+
206
+ with open(self.expected_report, "r") as report_file:
207
+ file_contents = report_file.read()
208
+ self.assertIn("UC", file_contents)
209
+ os.remove(self.expected_report)
210
+
211
+ self.ss.UC.export_csv()
212
+ self.assertTrue(os.path.exists('pjm5bus_demo_UC.csv'))
213
+ os.remove('pjm5bus_demo_UC.csv')
214
+
215
+ @skip_unittest_without_MISOCP
216
+ def test_UCDG_report(self):
217
+ """
218
+ Test report with UCDG solved.
219
+ """
220
+ self.ss.files.no_output = False
221
+ self.ss.UCDG.run()
222
+ self.assertTrue(self.ss.report())
223
+ self.assertTrue(os.path.exists(self.expected_report))
224
+
225
+ with open(self.expected_report, "r") as report_file:
226
+ file_contents = report_file.read()
227
+ self.assertIn("UCDG", file_contents)
228
+ os.remove(self.expected_report)
229
+
230
+ self.ss.UCDG.export_csv()
231
+ self.assertTrue(os.path.exists('pjm5bus_demo_UCDG.csv'))
232
+ os.remove('pjm5bus_demo_UCDG.csv')
233
+
234
+ @skip_unittest_without_MISOCP
235
+ def test_UCES_report(self):
236
+ """
237
+ Test report with UCES solved.
238
+ """
239
+ self.ss.files.no_output = False
240
+ self.ss.UCES.run()
241
+ self.assertTrue(self.ss.report())
242
+ self.assertTrue(os.path.exists(self.expected_report))
243
+
244
+ with open(self.expected_report, "r") as report_file:
245
+ file_contents = report_file.read()
246
+ self.assertIn("UCES", file_contents)
247
+ os.remove(self.expected_report)
248
+
249
+ self.ss.UCES.export_csv()
250
+ self.assertTrue(os.path.exists('pjm5bus_demo_UCES.csv'))
251
+ os.remove('pjm5bus_demo_UCES.csv')
tests/test_repr.py ADDED
@@ -0,0 +1,21 @@
1
+ import contextlib
2
+ import unittest
3
+
4
+ import ams
5
+
6
+
7
+ class TestRepr(unittest.TestCase):
8
+ """Test __repr__"""
9
+ def setUp(self):
10
+ self.ss = ams.run(ams.get_case("ieee39/ieee39_uced.xlsx"),
11
+ no_output=True,
12
+ default_config=True,
13
+ )
14
+
15
+ def test_print_model_repr(self):
16
+ """
17
+ Print out Model ``cache``'s fields and values.
18
+ """
19
+ with contextlib.redirect_stdout(None):
20
+ for model in self.ss.models.values():
21
+ print(model.cache.__dict__)
tests/test_routine.py ADDED
@@ -0,0 +1,178 @@
1
+ import unittest
2
+ import numpy as np
3
+
4
+
5
+ import ams
6
+ from ams.shared import pd
7
+
8
+
9
+ class TestRoutineMethods(unittest.TestCase):
10
+ """
11
+ Test methods of `Routine`.
12
+ """
13
+
14
+ def setUp(self) -> None:
15
+ self.ss = ams.load(ams.get_case("ieee39/ieee39_uced.xlsx"),
16
+ default_config=True,
17
+ no_output=True,
18
+ )
19
+
20
+ def test_data_check(self):
21
+ """
22
+ Test `Routine._data_check()` method.
23
+ """
24
+
25
+ self.assertTrue(self.ss.DCOPF._data_check())
26
+ self.assertFalse(self.ss.RTEDES._data_check())
27
+
28
+ def test_get_off_constrs(self):
29
+ """
30
+ Test `Routine._get_off_constrs()` method.
31
+ """
32
+
33
+ self.assertIsInstance(self.ss.DCOPF._get_off_constrs(), list)
34
+
35
+ def test_routine_set(self):
36
+ """
37
+ Test `Routine.set()` method.
38
+ """
39
+
40
+ self.ss.DCOPF.set('c2', 'GCost_1', 'v', 10)
41
+ np.testing.assert_equal(self.ss.GCost.get('c2', 'GCost_1', 'v'), 10)
42
+
43
+ def test_routine_get(self):
44
+ """
45
+ Test `Routine.get()` method.
46
+ """
47
+ # --- single period routine ---
48
+ # get an rparam value
49
+ np.testing.assert_equal(self.ss.DCOPF.get('ug', 'PV_30'), 1)
50
+
51
+ # get an unpacked var value
52
+ self.ss.DCOPF.run(solver='CLARABEL')
53
+ self.assertEqual(self.ss.DCOPF.exit_code, 0, "Exit code is not 0.")
54
+ np.testing.assert_equal(self.ss.DCOPF.get('pg', 'PV_30', 'v'),
55
+ self.ss.StaticGen.get('p', 'PV_30', 'v'))
56
+
57
+ # test input type
58
+ self.assertIsInstance(self.ss.DCOPF.get('pg', pd.Series(['PV_30']), 'v'), np.ndarray)
59
+
60
+ # test return type
61
+ self.assertIsInstance(self.ss.DCOPF.get('pg', 'PV_30', 'v'), float)
62
+ self.assertIsInstance(self.ss.DCOPF.get('pg', ['PV_30'], 'v'), np.ndarray)
63
+
64
+ # --- multi period routine ---
65
+ self.ss.ED.run(solver='CLARABEL')
66
+ self.assertEqual(self.ss.ED.exit_code, 0, "Exit code is not 0.")
67
+ np.testing.assert_equal(self.ss.ED.get('pg', 'PV_30', 'v').ndim, 1)
68
+ np.testing.assert_equal(self.ss.ED.get('pg', ['PV_30'], 'v').ndim, 2)
69
+
70
+ def test_rouine_init(self):
71
+ """
72
+ Test `Routine.init()` method.
73
+ """
74
+
75
+ self.assertTrue(self.ss.DCOPF.init(), "DCOPF initialization failed!")
76
+
77
+ def test_generate_symbols(self):
78
+ """
79
+ Test symbol generation.
80
+ """
81
+
82
+ self.ss.DCOPF.syms.generate_symbols()
83
+ self.assertTrue(self.ss.DCOPF._syms, "Symbol generation failed!")
84
+
85
+ def test_value_method(self):
86
+ """
87
+ Test Contraint and Objective values.
88
+ """
89
+
90
+ self.ss.DCOPF.run(solver='CLARABEL')
91
+ self.assertTrue(self.ss.DCOPF.converged, "DCOPF did not converge!")
92
+
93
+ # --- constraint values ---
94
+ for constr in self.ss.DCOPF.constrs.values():
95
+ np.testing.assert_almost_equal(constr.v, constr.e, decimal=6)
96
+
97
+ # --- objective value ---
98
+ self.assertAlmostEqual(self.ss.DCOPF.obj.v, self.ss.DCOPF.obj.e, places=6)
99
+
100
+
101
+ class TestSetOptzValueACOPF(unittest.TestCase):
102
+ """
103
+ Test value settings of `OptzBase` series in `ACOPF`.
104
+ """
105
+
106
+ def setUp(self) -> None:
107
+ self.ss = ams.load(ams.get_case("5bus/pjm5bus_demo.xlsx"),
108
+ setup=True,
109
+ default_config=True,
110
+ no_output=True,
111
+ )
112
+
113
+ def test_vset_before_init(self):
114
+ """
115
+ Test value setting before routine initialization.
116
+ """
117
+ # set values to `Var` before initialization is not doable
118
+ v_ext = np.ones(self.ss.ACOPF.pg.n)
119
+ self.ss.ACOPF.pg.v = v_ext
120
+ self.assertIsNone(self.ss.ACOPF.pg.v)
121
+ # set values to `Constraint` is not allowed
122
+ self.assertRaises(AttributeError, lambda: setattr(self.ss.ACOPF.plfub, 'v', 1))
123
+ # set values to `Objective` is not allowed
124
+ self.assertRaises(AttributeError, lambda: setattr(self.ss.ACOPF.obj, 'v', 1))
125
+
126
+ def test_vset_after_init(self):
127
+ """
128
+ Test value setting after routine initialization.
129
+ """
130
+ self.ss.ACOPF.init()
131
+ # set values to `Var` after initialization is allowed
132
+ v_ext = np.ones(self.ss.ACOPF.pg.n)
133
+ self.ss.ACOPF.pg.v = v_ext
134
+ np.testing.assert_equal(self.ss.ACOPF.pg.v, v_ext)
135
+ # set values to `Constraint` is not allowed
136
+ self.assertRaises(AttributeError, lambda: setattr(self.ss.ACOPF.plfub, 'v', 1))
137
+ # set values to `Objective` is not allowed
138
+ self.assertRaises(AttributeError, lambda: setattr(self.ss.ACOPF.obj, 'v', 1))
139
+
140
+
141
+ class TestSetOptzValueDCOPF(unittest.TestCase):
142
+ """
143
+ Test value settings of `OptzBase` series in `DCOPF`.
144
+ """
145
+
146
+ def setUp(self) -> None:
147
+ self.ss = ams.load(ams.get_case("5bus/pjm5bus_demo.xlsx"),
148
+ setup=True,
149
+ default_config=True,
150
+ no_output=True,
151
+ )
152
+
153
+ def test_vset_before_init(self):
154
+ """
155
+ Test value setting before routine initialization.
156
+ """
157
+ # set values to `Var` before initialization is not doable
158
+ v_ext = np.ones(self.ss.DCOPF.pg.n)
159
+ self.ss.DCOPF.pg.v = v_ext
160
+ self.assertIsNone(self.ss.DCOPF.pg.v)
161
+ # set values to `Constraint` is not allowed
162
+ self.assertRaises(AttributeError, lambda: setattr(self.ss.DCOPF.plfub, 'v', 1))
163
+ # set values to `Objective` is not allowed
164
+ self.assertRaises(AttributeError, lambda: setattr(self.ss.DCOPF.obj, 'v', 1))
165
+
166
+ def test_vset_after_init(self):
167
+ """
168
+ Test value setting after routine initialization.
169
+ """
170
+ self.ss.DCOPF.init()
171
+ # set values to `Var` after initialization is allowed
172
+ v_ext = np.ones(self.ss.DCOPF.pg.n)
173
+ self.ss.DCOPF.pg.v = v_ext
174
+ np.testing.assert_equal(self.ss.DCOPF.pg.v, v_ext)
175
+ # set values to `Constraint` is not allowed
176
+ self.assertRaises(AttributeError, lambda: setattr(self.ss.DCOPF.plfub, 'v', 1))
177
+ # set values to `Objective` is not allowed
178
+ self.assertRaises(AttributeError, lambda: setattr(self.ss.DCOPF.obj, 'v', 1))