ltbams 1.0.12__py3-none-any.whl → 1.0.13__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 (45) hide show
  1. ams/_version.py +3 -3
  2. ams/core/matprocessor.py +170 -104
  3. ams/io/matpower.py +4 -0
  4. ams/io/psse.py +2 -0
  5. ams/opt/exprcalc.py +11 -0
  6. ams/routines/grbopt.py +2 -0
  7. ams/routines/pypower.py +8 -0
  8. ams/routines/routine.py +118 -1
  9. ams/shared.py +30 -2
  10. ams/system.py +10 -0
  11. docs/source/index.rst +4 -3
  12. docs/source/release-notes.rst +8 -0
  13. {ltbams-1.0.12.dist-info → ltbams-1.0.13.dist-info}/METADATA +4 -2
  14. {ltbams-1.0.12.dist-info → ltbams-1.0.13.dist-info}/RECORD +17 -45
  15. {ltbams-1.0.12.dist-info → ltbams-1.0.13.dist-info}/top_level.txt +0 -1
  16. tests/__init__.py +0 -0
  17. tests/test_1st_system.py +0 -64
  18. tests/test_addressing.py +0 -40
  19. tests/test_case.py +0 -301
  20. tests/test_cli.py +0 -34
  21. tests/test_export_csv.py +0 -89
  22. tests/test_group.py +0 -83
  23. tests/test_interface.py +0 -238
  24. tests/test_io.py +0 -190
  25. tests/test_jumper.py +0 -27
  26. tests/test_known_good.py +0 -267
  27. tests/test_matp.py +0 -437
  28. tests/test_model.py +0 -54
  29. tests/test_omodel.py +0 -119
  30. tests/test_paths.py +0 -89
  31. tests/test_report.py +0 -251
  32. tests/test_repr.py +0 -21
  33. tests/test_routine.py +0 -178
  34. tests/test_rtn_acopf.py +0 -75
  35. tests/test_rtn_dcopf.py +0 -121
  36. tests/test_rtn_dcopf2.py +0 -103
  37. tests/test_rtn_ed.py +0 -279
  38. tests/test_rtn_opf.py +0 -142
  39. tests/test_rtn_pflow.py +0 -147
  40. tests/test_rtn_pypower.py +0 -315
  41. tests/test_rtn_rted.py +0 -273
  42. tests/test_rtn_uc.py +0 -248
  43. tests/test_service.py +0 -73
  44. {ltbams-1.0.12.dist-info → ltbams-1.0.13.dist-info}/WHEEL +0 -0
  45. {ltbams-1.0.12.dist-info → ltbams-1.0.13.dist-info}/entry_points.txt +0 -0
tests/test_case.py DELETED
@@ -1,301 +0,0 @@
1
- import os
2
- import unittest
3
-
4
- import numpy as np
5
-
6
- import ams
7
- from ams.utils.paths import get_case
8
-
9
-
10
- class Test5Bus(unittest.TestCase):
11
- """
12
- Tests for the 5-bus system.
13
- """
14
-
15
- def setUp(self) -> None:
16
- self.ss = ams.main.load(
17
- get_case("5bus/pjm5bus_demo.json"),
18
- default_config=True,
19
- no_output=True,
20
- )
21
-
22
- def test_essential(self):
23
- """
24
- Test essential functionalities of Model and System.
25
- """
26
-
27
- # --- test model names
28
- self.assertTrue("Bus" in self.ss.models)
29
- self.assertTrue("PQ" in self.ss.models)
30
-
31
- nBus = 5
32
- nGen = 5
33
- nPQ = 3
34
- nArea = 3
35
- nZone = 5
36
- nDT = 24
37
- # --- test device counts
38
- self.assertEqual(self.ss.Bus.n, nBus)
39
- self.assertEqual(self.ss.PQ.n, nPQ)
40
- self.assertEqual(self.ss.PV.n, 4)
41
- self.assertEqual(self.ss.Slack.n, 1)
42
- self.assertEqual(self.ss.Line.n, 7)
43
- self.assertEqual(self.ss.Zone.n, nZone)
44
- self.assertEqual(self.ss.Area.n, nArea)
45
- self.assertEqual(self.ss.SFR.n, nArea)
46
- self.assertEqual(self.ss.SR.n, nArea)
47
- self.assertEqual(self.ss.NSR.n, nArea)
48
- self.assertEqual(self.ss.GCost.n, nGen)
49
- self.assertEqual(self.ss.DCost.n, nPQ)
50
- self.assertEqual(self.ss.SFRCost.n, nGen)
51
- self.assertEqual(self.ss.SRCost.n, nGen)
52
- self.assertEqual(self.ss.NSRCost.n, nGen)
53
- self.assertEqual(self.ss.EDTSlot.n, nDT)
54
- self.assertEqual(self.ss.UCTSlot.n, nDT)
55
-
56
- # test idx values
57
- self.assertSequenceEqual(self.ss.Bus.idx.v, [0, 1, 2, 3, 4])
58
- self.assertSequenceEqual(self.ss.Area.idx.v, [1, 2, 3])
59
-
60
- # test cache refreshing
61
- self.ss.Bus.cache.refresh() # used in ANDES but not in AMS
62
-
63
- # test conversion to dataframe
64
- self.ss.Bus.as_df()
65
- self.ss.Bus.as_df(vin=True)
66
-
67
- # test conversion to dataframe of ``Horizon`` model
68
- self.ss.EDTSlot.as_df()
69
- self.ss.EDTSlot.as_df(vin=True)
70
-
71
- self.ss.UCTSlot.as_df()
72
- self.ss.UCTSlot.as_df(vin=True)
73
-
74
- def test_pflow_reset(self):
75
- """
76
- Test resetting power flow.
77
- """
78
-
79
- self.ss.PFlow.run()
80
- self.ss.reset()
81
- self.ss.PFlow.run()
82
-
83
- def test_alter_param(self):
84
- """
85
- Test altering parameter for power flow.
86
- """
87
-
88
- self.ss.PV.alter("v0", "PV_3", 0.98)
89
- self.assertEqual(self.ss.PV.v0.v[1], 0.98)
90
- self.ss.PFlow.run()
91
-
92
- def test_alter_param_before_routine(self):
93
- """
94
- Test altering parameter before running routine.
95
- """
96
-
97
- self.ss.GCost.alter("c1", ['GCost_1', 'GCost_2'], [1500., 3100.])
98
- np.testing.assert_array_equal(self.ss.GCost.c1.v, [1500., 3100., 0.4, 0.1, 0.01])
99
- self.ss.ACOPF.run()
100
- np.testing.assert_array_equal(self.ss.GCost.c1.v, [1500., 3100., 0.4, 0.1, 0.01])
101
-
102
- def test_alter_param_after_routine(self):
103
- """
104
- Test altering parameter after running routine.
105
- """
106
-
107
- self.ss.ACOPF.run()
108
- self.ss.GCost.alter("c1", ['GCost_1', 'GCost_2'], [1500., 3100.])
109
- np.testing.assert_array_equal(self.ss.GCost.c1.v, [1500., 3100., 0.4, 0.1, 0.01])
110
- self.ss.ACOPF.run()
111
- np.testing.assert_array_equal(self.ss.GCost.c1.v, [1500., 3100., 0.4, 0.1, 0.01])
112
-
113
- # def test_multiple_disconnected_line(self):
114
- # """
115
- # Test connectivity check for systems with disconnected lines.
116
-
117
- # These disconnected lines (zeros) was not excluded when counting
118
- # connected buses, causing an out-of-bound error.
119
- # """
120
- # # TODO: need to add `connectivity` in `system`
121
- # pass
122
- # # self.ss.Line.u.v[[0, 6]] = 0
123
- # # self.ss.PFlow.run()
124
- # # self.assertEqual(len(self.ss.Bus.islands), 1)
125
- # # self.assertEqual(self.ss.Bus.n_islanded_buses, 0)
126
-
127
-
128
- class TestIEEE14RAW(unittest.TestCase):
129
- """
130
- Test IEEE14 system in the RAW format.
131
- """
132
-
133
- # TODO: after add `run` in `system`, improve this part
134
- def test_ieee14_raw(self):
135
- ss = ams.load(
136
- get_case("ieee14/ieee14.raw"),
137
- default_config=True,
138
- no_output=True,
139
- )
140
- ss.PFlow.run()
141
- self.assertEqual(ss.PFlow.exit_code, 0, "Exit code is not 0.")
142
-
143
- def test_ieee14_raw_convert(self):
144
- ss = ams.run(
145
- get_case("ieee14/ieee14.raw"),
146
- convert=True,
147
- default_config=True,
148
- )
149
- os.remove(ss.files.dump)
150
- self.assertEqual(ss.exit_code, 0, "Exit code is not 0.")
151
-
152
- def test_ieee14_raw2xlsx(self):
153
- ss = ams.load(
154
- get_case("ieee14/ieee14.raw"),
155
- setup=True,
156
- no_output=True,
157
- default_config=True,
158
- )
159
- ams.io.xlsx.write(ss, "ieee14.xlsx", overwrite=True)
160
- self.assertTrue(os.path.exists("ieee14.xlsx"))
161
- os.remove("ieee14.xlsx")
162
-
163
- def test_ieee14_raw2json(self):
164
- ss = ams.load(
165
- get_case("ieee14/ieee14.raw"),
166
- setup=True,
167
- no_output=True,
168
- default_config=True,
169
- )
170
- ams.io.json.write(ss, "ieee14.json", overwrite=True)
171
- self.assertTrue(os.path.exists("ieee14.json"))
172
- os.remove("ieee14.json")
173
-
174
- def test_ieee14_raw2json_convert(self):
175
- ss = ams.run(
176
- get_case("ieee14/ieee14.raw"),
177
- convert="json",
178
- default_config=True,
179
- )
180
-
181
- ss2 = ams.run(
182
- "ieee14.json",
183
- default_config=True,
184
- no_output=True,
185
- )
186
-
187
- os.remove(ss.files.dump)
188
- self.assertEqual(ss2.exit_code, 0, "Exit code is not 0.")
189
-
190
- def test_read_json_from_memory(self):
191
- fd = open(get_case("ieee14/ieee14.json"), "r")
192
-
193
- ss = ams.main.System(
194
- default_config=True,
195
- no_output=True,
196
- )
197
- ams.io.json.read(ss, fd)
198
- ss.setup()
199
- ss.PFlow.run()
200
-
201
- fd.close()
202
- self.assertEqual(ss.exit_code, 0, "Exit code is not 0.")
203
-
204
- def test_read_mpc_from_memory(self):
205
- fd = open(get_case("matpower/case14.m"), "r")
206
-
207
- ss = ams.main.System(
208
- default_config=True,
209
- no_output=True,
210
- )
211
- ams.io.matpower.read(ss, fd)
212
- ss.setup()
213
- ss.PFlow.run()
214
-
215
- fd.close()
216
- self.assertEqual(ss.exit_code, 0, "Exit code is not 0.")
217
-
218
- def test_read_psse_from_memory(self):
219
- fd_raw = open(get_case("ieee14/ieee14.raw"), "r")
220
-
221
- ss = ams.main.System(
222
- default_config=True,
223
- no_output=True,
224
- )
225
- # suppress out-of-normal info
226
- ss.config.warn_limits = 0
227
- ss.config.warn_abnormal = 0
228
-
229
- ams.io.psse.read(ss, fd_raw)
230
- ss.setup()
231
- ss.PFlow.run()
232
-
233
- fd_raw.close()
234
- self.assertEqual(ss.exit_code, 0, "Exit code is not 0.")
235
-
236
-
237
- class TestCaseInit(unittest.TestCase):
238
- """
239
- Test if initializations pass.
240
- """
241
-
242
- def test_ieee39_init(self):
243
- """
244
- Test if ieee39 initialization works.
245
- """
246
- ss = ams.load(
247
- get_case("ieee39/ieee39_uced.xlsx"),
248
- default_config=True,
249
- no_output=True,
250
- )
251
- ss.DCOPF.init()
252
- ss.RTED.init()
253
- ss.ED.init()
254
- ss.UC.init()
255
-
256
- self.assertEqual(ss.DCOPF.exit_code, 0, "Exit code is not 0.")
257
- self.assertEqual(ss.RTED.exit_code, 0, "Exit code is not 0.")
258
- self.assertEqual(ss.ED.exit_code, 0, "Exit code is not 0.")
259
- self.assertEqual(ss.UC.exit_code, 0, "Exit code is not 0.")
260
-
261
- def test_ieee39_esd1_init(self):
262
- """
263
- Test if ieee39 with ESD1 initialization works.
264
- """
265
- ss = ams.load(
266
- get_case("ieee39/ieee39_uced_esd1.xlsx"),
267
- default_config=True,
268
- no_output=True,
269
- )
270
- ss.EDES.init()
271
- ss.UCES.init()
272
-
273
- self.assertEqual(ss.EDES.exit_code, 0, "Exit code is not 0.")
274
- self.assertEqual(ss.UCES.exit_code, 0, "Exit code is not 0.")
275
-
276
-
277
- class TestCase14(unittest.TestCase):
278
- """
279
- Test parameter correction using case14.m
280
- """
281
-
282
- def test_parameter_correction(self):
283
- """
284
- Test if the parameter correction works.
285
- """
286
- mpc = ams.io.matpower.m2mpc(get_case("matpower/case14.m"))
287
- mpc['branch'][:, 11] = 0.0
288
- mpc['branch'][:, 12] = 0.0
289
-
290
- ss = ams.system.System()
291
- ams.io.matpower.mpc2system(mpc, ss)
292
- ss.setup()
293
-
294
- # line rate
295
- np.testing.assert_array_less(0.0, ss.Line.rate_a.v)
296
- np.testing.assert_array_less(0.0, ss.Line.rate_b.v)
297
- np.testing.assert_array_less(0.0, ss.Line.rate_c.v)
298
-
299
- # line angle difference
300
- np.testing.assert_array_less(0.0, ss.Line.amax.v)
301
- np.testing.assert_array_less(ss.Line.amin.v, 0.0)
tests/test_cli.py DELETED
@@ -1,34 +0,0 @@
1
- import unittest
2
- import os
3
-
4
- import ams.main
5
- import ams.cli
6
-
7
-
8
- class TestCLI(unittest.TestCase):
9
-
10
- def test_cli_parser(self):
11
- ams.cli.create_parser()
12
-
13
- def test_cli_preamble(self):
14
- ams.cli.preamble()
15
-
16
- def test_main_doc(self):
17
- ams.main.doc('Bus')
18
- ams.main.doc(list_supported=True)
19
-
20
- def test_versioninfo(self):
21
- ams.main.versioninfo()
22
-
23
- def test_misc(self):
24
- ams.main.misc(show_license=True)
25
- ams.main.misc(save_config=None, overwrite=True)
26
-
27
- def test_profile_run(self):
28
- _ = ams.main.run(ams.get_case('matpower/case5.m'),
29
- no_output=False,
30
- profile=True,)
31
- self.assertTrue(os.path.exists('case5_prof.prof'))
32
- self.assertTrue(os.path.exists('case5_prof.txt'))
33
- os.remove('case5_prof.prof')
34
- os.remove('case5_prof.txt')
tests/test_export_csv.py DELETED
@@ -1,89 +0,0 @@
1
- """
2
- Test routine export to CSV.
3
- """
4
- import unittest
5
- import os
6
- import csv
7
-
8
- import numpy as np
9
-
10
- import ams
11
-
12
-
13
- class TestExportCSV(unittest.TestCase):
14
- """
15
- Tests for Routine export to CSV.
16
- """
17
-
18
- def setUp(self) -> None:
19
- self.ss = ams.main.load(
20
- ams.get_case("5bus/pjm5bus_demo.json"),
21
- default_config=True,
22
- no_output=True,
23
- )
24
- self.expected_csv_DCOPF = 'pjm5bus_demo_DCOPF.csv'
25
- self.expected_csv_ED = 'pjm5bus_demo_ED.csv'
26
-
27
- def test_no_export(self):
28
- """
29
- Test no export when routine is not converged.
30
- """
31
- self.assertIsNone(self.ss.DCOPF.export_csv())
32
-
33
- def test_export_DCOPF(self):
34
- """
35
- Test export DCOPF to CSV.
36
- """
37
- self.ss.DCOPF.run(solver='CLARABEL')
38
- self.ss.DCOPF.export_csv()
39
- self.assertTrue(os.path.exists(self.expected_csv_DCOPF))
40
-
41
- n_rows = 0
42
- n_cols = 0
43
- with open(self.expected_csv_DCOPF, 'r') as csv_file:
44
- csv_reader = csv.reader(csv_file)
45
- for row in csv_reader:
46
- n_rows += 1
47
- # Check if this row has more columns than the previous rows
48
- if n_cols == 0 or len(row) > n_cols:
49
- n_cols = len(row)
50
-
51
- n_cols_expected = np.sum([v.owner.n for v in self.ss.DCOPF.vars.values()])
52
- n_cols_expected += np.sum([v.owner.n for v in self.ss.DCOPF.exprs.values()])
53
- n_cols_expected += np.sum([v.owner.n for v in self.ss.DCOPF.exprcs.values()])
54
- # cols number plus one for the index column
55
- self.assertEqual(n_cols, n_cols_expected + 1)
56
- # header row plus data row
57
- n_rows_expected = 2
58
- self.assertEqual(n_rows, n_rows_expected)
59
-
60
- os.remove(self.expected_csv_DCOPF)
61
-
62
- def test_export_ED(self):
63
- """
64
- Test export ED to CSV.
65
- """
66
- self.ss.ED.run(solver='CLARABEL')
67
- self.ss.ED.export_csv()
68
- self.assertTrue(os.path.exists(self.expected_csv_ED))
69
-
70
- n_rows = 0
71
- n_cols = 0
72
- with open(self.expected_csv_ED, 'r') as csv_file:
73
- csv_reader = csv.reader(csv_file)
74
- for row in csv_reader:
75
- n_rows += 1
76
- # Check if this row has more columns than the previous rows
77
- if n_cols == 0 or len(row) > n_cols:
78
- n_cols = len(row)
79
-
80
- n_cols_expected = np.sum([v.owner.n for v in self.ss.ED.vars.values()])
81
- n_cols_expected += np.sum([v.owner.n for v in self.ss.ED.exprs.values()])
82
- n_cols_expected += np.sum([v.owner.n for v in self.ss.ED.exprcs.values()])
83
- # cols number plus one for the index column
84
- self.assertEqual(n_cols, n_cols_expected + 1)
85
- # header row plus data row
86
- n_rows_expected = len(self.ss.ED.timeslot.v) + 1
87
- self.assertTrue(n_rows, n_rows_expected)
88
-
89
- os.remove(self.expected_csv_ED)
tests/test_group.py DELETED
@@ -1,83 +0,0 @@
1
- """
2
- Tests for group functions.
3
- """
4
- import unittest
5
-
6
- import numpy as np
7
-
8
- import ams
9
-
10
-
11
- class TestGroup(unittest.TestCase):
12
- """
13
- Test the group class functions.
14
- """
15
-
16
- def setUp(self):
17
- self.ss = ams.run(ams.get_case("ieee39/ieee39_uced_esd1.xlsx"),
18
- default_config=True,
19
- no_output=True,
20
- )
21
-
22
- def test_group_access(self):
23
- """
24
- Test methods such as `idx2model`
25
- """
26
- ss = self.ss
27
-
28
- # --- idx2uid ---
29
- self.assertIsNone(ss.DG.idx2uid(None))
30
- self.assertListEqual(ss.DG.idx2uid([None]), [None])
31
-
32
- # --- idx2model ---
33
- # what works
34
- self.assertIs(ss.DG.idx2model('ESD1_1'), ss.ESD1)
35
- self.assertListEqual(ss.DG.idx2model(['ESD1_1']), [ss.ESD1])
36
-
37
- # what does not work
38
- self.assertRaises(KeyError, ss.DG.idx2model, idx='1')
39
- self.assertRaises(KeyError, ss.DG.idx2model, idx=88)
40
- self.assertRaises(KeyError, ss.DG.idx2model, idx=[1, 88])
41
-
42
- # --- get ---
43
- self.assertRaises(KeyError, ss.DG.get, 'EtaC', 999)
44
-
45
- np.testing.assert_equal(ss.DG.get('EtaC', 'ESD1_1',), 1.0)
46
-
47
- np.testing.assert_equal(ss.DG.get('EtaC', ['ESD1_1'], allow_none=True,),
48
- [1.0])
49
- np.testing.assert_equal(ss.DG.get('EtaC', ['ESD1_1', None],
50
- allow_none=True, default=0.95),
51
- [1.0, 0.95])
52
-
53
- # --- set ---
54
- ss.DG.set('EtaC', 'ESD1_1', 'v', 0.95)
55
- np.testing.assert_equal(ss.DG.get('EtaC', 'ESD1_1',), 0.95)
56
-
57
- ss.DG.set('EtaC', ['ESD1_1'], 'v', 0.97)
58
- np.testing.assert_equal(ss.DG.get('EtaC', ['ESD1_1'],), [0.97])
59
-
60
- ss.DG.set('EtaC', ['ESD1_1'], 'v', [0.99])
61
- np.testing.assert_equal(ss.DG.get('EtaC', ['ESD1_1'],), [0.99])
62
-
63
- # --- find_idx ---
64
- self.assertListEqual(ss.DG.find_idx('name', ['ESD1_1']),
65
- ss.ESD1.find_idx('name', ['ESD1_1']),
66
- )
67
-
68
- self.assertListEqual(ss.DG.find_idx(['name', 'Sn'],
69
- [('ESD1_1',),
70
- (100.0,)]),
71
- ss.ESD1.find_idx(['name', 'Sn'],
72
- [('ESD1_1',),
73
- (100.0,)]),)
74
-
75
- # --- get group idx ---
76
- self.assertListEqual(ss.DG.get_all_idxes(), ss.ESD1.idx.v)
77
-
78
- def test_group_repr(self):
79
- """
80
- Test `Group.__repr__()` method.
81
- """
82
- for grp in self.ss.groups.items():
83
- print(grp.__repr__())