ltbams 0.9.9__py3-none-any.whl → 1.0.2a1__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 +203 -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 +234 -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.2a1.dist-info/METADATA +210 -0
  158. ltbams-1.0.2a1.dist-info/RECORD +188 -0
  159. {ltbams-0.9.9.dist-info → ltbams-1.0.2a1.dist-info}/WHEEL +1 -1
  160. ltbams-1.0.2a1.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.2a1.dist-info}/entry_points.txt +0 -0
docs/source/index.rst ADDED
@@ -0,0 +1,108 @@
1
+ .. AMS documentation master file, created by
2
+ sphinx-quickstart on Thu Jan 26 15:32:32 2023.
3
+ You can adapt this file completely to your liking, but it should at least
4
+ contain the root `toctree` directive.
5
+
6
+ ==================
7
+ AMS documentation
8
+ ==================
9
+ **Useful Links**: `Source Repository`_ | `Report Issues`_ | `Q&A`_ | `LTB Repository`_
10
+ | `ANDES Repository`_
11
+
12
+ .. _`Source Repository`: https://github.com/CURENT/ams
13
+ .. _`Report Issues`: https://github.com/CURENT/ams/issues
14
+ .. _`Q&A`: https://github.com/CURENT/ams/discussions
15
+ .. _`ANDES Repository`: https://github.com/CURENT/andes
16
+ .. _`LTB Repository`: https://github.com/CURENT/
17
+
18
+ LTB AMS is an open-source packages for scheduling modeling, serving as the market
19
+ simulator for the CURENT Large scale Testbed (LTB).
20
+
21
+ AMS enables **flexible** scheduling modeling and **interoprability** with the in-house
22
+ dynamic simulator ANDES.
23
+
24
+ .. panels::
25
+ :card: + intro-card text-center
26
+ :column: col-lg-6 col-md-6 col-sm-6 col-xs-12 d-flex
27
+
28
+ ---
29
+
30
+ Getting started
31
+ ^^^^^^^^^^^^^^^
32
+
33
+ New to AMS? Check out the getting started guides.
34
+
35
+ +++
36
+
37
+ .. link-button:: getting-started
38
+ :type: ref
39
+ :text: To the getting started guides
40
+ :classes: btn-block btn-secondary stretched-link
41
+
42
+ ---
43
+
44
+ Examples
45
+ ^^^^^^^^
46
+
47
+ The examples of using AMS for power system scheduling study.
48
+
49
+ +++
50
+
51
+ .. link-button:: scripting_examples
52
+ :type: ref
53
+ :text: To the examples
54
+ :classes: btn-block btn-secondary stretched-link
55
+
56
+ ---
57
+
58
+ Model development guide
59
+ ^^^^^^^^^^^^^^^^^^^^^^^
60
+
61
+ New scheduling modeling in AMS.
62
+
63
+ +++
64
+
65
+ .. link-button:: development
66
+ :type: ref
67
+ :text: To the development guide
68
+ :classes: btn-block btn-secondary stretched-link
69
+ ---
70
+
71
+ API reference
72
+ ^^^^^^^^^^^^^
73
+
74
+ The API reference of AMS.
75
+
76
+ +++
77
+
78
+ .. link-button:: api_reference
79
+ :type: ref
80
+ :text: To the API reference
81
+ :classes: btn-block btn-secondary stretched-link
82
+
83
+ ---
84
+ :column: col-12 p-3
85
+
86
+ Using AMS for Research?
87
+ ^^^^^^^^^^^^^^^^^^^^^^^^^
88
+ Please cite our paper [Wang2025]_ if AMS is used in your research for
89
+ publication.
90
+
91
+
92
+ .. [Wang2025] J. Wang et al., "Dynamics-incorporated Modeling Framework for Stability
93
+ Constrained Scheduling Under High-penetration of Renewable Energy," in IEEE
94
+ Transactions on Sustainable Energy, doi: 10.1109/TSTE.2025.3528027.
95
+
96
+
97
+ .. toctree::
98
+ :maxdepth: 3
99
+ :caption: AMS Manual
100
+ :hidden:
101
+
102
+ getting_started/index
103
+ examples/index
104
+ modeling/index
105
+ release-notes
106
+ routineref
107
+ modelref
108
+ api
@@ -0,0 +1,159 @@
1
+ Examples
2
+ ========
3
+
4
+ One example is provided to demonstrate descriptive scheduling modeling.
5
+
6
+ DCOPF
7
+ ----------
8
+
9
+
10
+ DC optimal power flow (DCOPF) is a fundamental routine used in power system analysis.
11
+ In this example, we demonstrate how to implement a DCOPF routine in a descriptive
12
+ manner using AMS. Below is a simplified DCOPF code snippet.
13
+ The full code can be found in :py:mod:`ams.routines.dcopf.DCOPF`.
14
+
15
+ Data Section
16
+ ^^^^^^^^^^^^
17
+
18
+ .. code-block:: python
19
+ :linenos:
20
+
21
+ class DCOPF(RoutineBase):
22
+
23
+ def __init__(self, system, config):
24
+ RoutineBase.__init__(self, system, config)
25
+ self.info = 'DC Optimal Power Flow'
26
+ self.type = 'DCED'
27
+ # --- Data Section ---
28
+ # --- generator cost ---
29
+ self.c1 = RParam(info='Gen cost coefficient 1',
30
+ name='c1', tex_name=r'c_{1}', unit=r'$/(p.u.)',
31
+ model='GCost', src='c1',
32
+ indexer='gen', imodel='StaticGen',)
33
+ # --- generator ---
34
+ self.ug = RParam(info='Gen connection status',
35
+ name='ug', tex_name=r'u_{g}',
36
+ model='StaticGen', src='u',
37
+ no_parse=True)
38
+ self.ctrl = RParam(info='Gen controllability',
39
+ name='ctrl', tex_name=r'c_{trl}',
40
+ model='StaticGen', src='ctrl',
41
+ no_parse=True)
42
+ self.ctrle = NumOpDual(info='Effective Gen controllability',
43
+ name='ctrle', tex_name=r'c_{trl, e}',
44
+ u=self.ctrl, u2=self.ug,
45
+ fun=np.multiply, no_parse=True)
46
+ # --- load ---
47
+ self.pd = RParam(info='active demand',
48
+ name='pd', tex_name=r'p_{d}',
49
+ model='StaticLoad', src='p0',
50
+ unit='p.u.',)
51
+ # --- line ---
52
+ self.rate_a = RParam(info='long-term flow limit',
53
+ name='rate_a', tex_name=r'R_{ATEA}',
54
+ unit='MVA', model='Line',)
55
+ # --- line angle difference ---
56
+ self.amax = NumOp(u=self.rate_a, fun=np.ones_like,
57
+ rfun=np.dot, rargs=dict(b=np.pi),
58
+ name='amax', tex_name=r'\theta_{max}',
59
+ info='max line angle difference',
60
+ no_parse=True,)
61
+ # --- connection matrix ---
62
+ self.Cg = RParam(info='Gen connection matrix',
63
+ name='Cg', tex_name=r'C_{g}',
64
+ model='mats', src='Cg',
65
+ no_parse=True, sparse=True,)
66
+ # --- system matrix ---
67
+ self.Bbus = RParam(info='Bus admittance matrix',
68
+ name='Bbus', tex_name=r'B_{bus}',
69
+ model='mats', src='Bbus',
70
+ no_parse=True, sparse=True,)
71
+
72
+ Lines 1-4: Derive subclass ``DCOPF`` from ``RoutineBase``.
73
+
74
+ Lines 5-6: Define routine information and type.
75
+
76
+ Lines 9-12: Define linear generator cost coefficients ``c1``, where it
77
+ sources from ``GCost.c1`` and sorted by ``StaticGen.gen``.
78
+
79
+ Lines 22-24: Define effective controllability as service ``ctrle``,
80
+ where it multiplies ``ctrl`` and ``ug``.
81
+
82
+ Lines 42-45: Define generator connection matrix ``Cg``, where it sources from
83
+ matrix processor ``mats.Cg`` and is sparse.
84
+
85
+ Model Section
86
+ ^^^^^^^^^^^^^
87
+
88
+ .. code-block:: python
89
+ :linenos:
90
+ :lineno-start: 51
91
+
92
+ # --- Model Section ---
93
+ # --- generation ---
94
+ self.pg = Var(info='Gen active power',
95
+ unit='p.u.',
96
+ name='pg', tex_name=r'p_g',
97
+ model='StaticGen', src='p',
98
+ v0=self.pg0)
99
+ # --- bus ---
100
+ self.aBus = Var(info='Bus voltage angle',
101
+ unit='rad',
102
+ name='aBus', tex_name=r'\theta_{bus}',
103
+ model='Bus', src='a',)
104
+ # --- power balance ---
105
+ pb = 'Bbus@aBus + Pbusinj + Cl@pd + Csh@gsh - Cg@pg'
106
+ self.pb = Constraint(name='pb', info='power balance',
107
+ e_str=pb, is_eq=True,)
108
+ # --- line flow ---
109
+ self.plf = Var(info='Line flow',
110
+ unit='p.u.',
111
+ name='plf', tex_name=r'p_{lf}',
112
+ model='Line',)
113
+ self.plflb = Constraint(info='line flow lower bound',
114
+ name='plflb', type='uq',
115
+ e_str='-Bf@aBus - Pfinj - rate_a',)
116
+ self.plfub = Constraint(info='line flow upper bound',
117
+ name='plfub', type='uq',
118
+ e_str='Bf@aBus + Pfinj - rate_a',)
119
+ # --- objective ---
120
+ obj = 'sum(mul(c2, power(pg, 2)))'
121
+ obj += '+ sum(mul(c1, pg))'
122
+ obj += '+ sum(mul(ug, c0))'
123
+ self.obj = Objective(name='obj',
124
+ info='total cost', unit='$',
125
+ sense='min', e_str=obj,)
126
+
127
+ Continued from the above code.
128
+
129
+ Lines 53-57: Define variable ``pg``, where it links to ``StaticGen.p``
130
+ and initial value ``pg0``.
131
+
132
+ Lines 68-71: Define variable ``plf``, where it links to ``Line`` with
133
+ no target source variable nor initial value.
134
+
135
+ Lines 72-77: Define inequality constraints ``plflb`` and ``plfub``
136
+ for line flow limits.
137
+
138
+ Lines 79-84: Define objective function ``obj`` for minimizing total cost.
139
+
140
+ Finalize
141
+ ^^^^^^^^
142
+
143
+ Lastly, similar to finalize a device model, we need to finalize the routine
144
+ by adding the ``RTED`` to the routine list in ``$HOME/ams/ams/routines/__init__.py``,
145
+ where 'rted' is the file name, and 'RTED' is the routine name.
146
+
147
+ .. code-block:: python
148
+
149
+ all_routines = OrderedDict([
150
+ ... ...
151
+ ('dcopf', ['DCOPF']),
152
+ ('ed', ['ED', 'EDDG', 'EDES']),
153
+ ('rted', ['RTED', 'RTEDDG', 'RTEDES', 'RTEDVIS']),
154
+ ... ...
155
+ ])
156
+
157
+ .. note::
158
+ Refer to the documentation "Example - Customize Formulation"
159
+ for API customization that does not require modification of the source code.
@@ -0,0 +1,17 @@
1
+ .. _development:
2
+
3
+ ===========
4
+ Development
5
+ ===========
6
+
7
+ This chapter introduces advanced topics on modeling with AMS.
8
+ It aims to give an in-depth explanation of flexible dispatch mdoeling
9
+ framework and the interoperation with dynamic simulation.
10
+
11
+ .. toctree::
12
+ :maxdepth: 2
13
+
14
+ system
15
+ model
16
+ routine
17
+ example
@@ -0,0 +1,210 @@
1
+ Device
2
+ =========
3
+
4
+ This section introduces the modeling of power system devices. Here the term
5
+ "model" refers to the descriptive model of a device, which is used to
6
+ hold the device-level data and variables, such as ``Bus``, ``Line``, and ``PQ``.
7
+
8
+ AMS employs a similar model organization manner as ANDES, where the class
9
+ ``model`` is used to hold the device-level parameters and variables.
10
+
11
+ .. note::
12
+
13
+ One major difference here is, in ANDES, two classes, ``ModelData`` and
14
+ ``Model``, are used to hold the device-level parameters and equations.
15
+
16
+ Parameters
17
+ ------------
18
+ Parameter is an atom element in building a power system model. Most parameters
19
+ are read from an input file, and other parameters are calculated from the existing
20
+ parameters.
21
+
22
+ AMS leverages the parameter definition in ANDES, where four classes,
23
+ ``DataParam``, ``IdxParam``, ``NumParam``, and ``ExtParam`` are used.
24
+ More details can be found in ANDES documentation
25
+ `Development - Parameters <https://docs.andes.app/en/latest/modeling/parameters.html>`_.
26
+
27
+ Variables
28
+ -----------
29
+
30
+ In AMS, the definition of variables ``Algeb`` is simplified from ANDES. The
31
+ ``Algeb`` class is used to define algebraic variables in the model level, which are used to
32
+ exchange data with dynamic simulator.
33
+
34
+ .. autoclass:: ams.core.var.Algeb
35
+ :noindex:
36
+
37
+ Algeb
38
+
39
+ .. note::
40
+
41
+ The ``Algeb`` class here is not directly used for optimization purpose, we will discuss
42
+ its role further in the Routine section.
43
+
44
+ Model
45
+ --------------
46
+
47
+ Encapsulating the parameters and variables, the ``Model`` class is used to define the
48
+ device model.
49
+
50
+ .. autoclass:: ams.core.model.Model
51
+ :noindex:
52
+
53
+ Model
54
+
55
+ Examples
56
+ ------------
57
+
58
+ The following two examples demonstrate how to define a device model in AMS.
59
+
60
+
61
+ PV model
62
+ ^^^^^^^^^^^^^^
63
+
64
+ In this example, we define a PV generator model ``PV`` in three steps, data
65
+ definition, model definition, and manufacturing.
66
+
67
+ First, we need to define the parameters needed in a ``PV``.
68
+ not included in ANDES ``PVData``. In this example, we hold the parameters in
69
+ a separate class ``GenParam``.
70
+
71
+ .. code-block:: python
72
+
73
+ from andes.core.param import NumParam, ExtParam
74
+
75
+ class GenParam:
76
+ def __init__(self) -> None:
77
+ self.ctrl = NumParam(default=1,
78
+ info="generator controllability",
79
+ tex_name=r'c_{trl}',)
80
+ self.Pc1 = NumParam(default=0.0,
81
+ info="lower real power output of PQ capability curve",
82
+ tex_name=r'P_{c1}',
83
+ unit='p.u.')
84
+ self.Pc2 = NumParam(default=0.0,
85
+ info="upper real power output of PQ capability curve",
86
+ tex_name=r'P_{c2}',
87
+ unit='p.u.')
88
+
89
+ ......
90
+
91
+ self.pg0 = NumParam(default=0.0,
92
+ info='real power start point',
93
+ tex_name=r'p_{g0}',
94
+ unit='p.u.',
95
+ )
96
+
97
+ Second, we define the ``PVModel`` model with two algebraic variables and an external parameter.
98
+
99
+ .. code-block:: python
100
+
101
+ from ams.core.model import Model
102
+ from ams.core.var import Algeb
103
+
104
+ class PVModel(Model):
105
+
106
+ def __init__(self, system=None, config=None):
107
+ super().__init__(system, config)
108
+ self.group = 'StaticGen'
109
+
110
+ self.zone = ExtParam(model='Bus', src='zone', indexer=self.bus, export=False,
111
+ info='Retrieved zone idx', vtype=str, default=None,
112
+ )
113
+ self.p = Algeb(info='actual active power generation',
114
+ unit='p.u.',
115
+ tex_name='p',
116
+ name='p',
117
+ )
118
+ self.q = Algeb(info='actual reactive power generation',
119
+ unit='p.u.',
120
+ tex_name='q',
121
+ name='q',
122
+ )
123
+
124
+ .. note::
125
+
126
+ The external parameter ``zone`` is added here to enable the zonal reserve dispatch,
127
+ but it is not included in ANDES ``PV``.
128
+
129
+ Third, we manufacture these classes together as the ``PV`` model.
130
+
131
+ .. code-block:: python
132
+
133
+ from andes.models.static.pv import PVData # NOQA
134
+
135
+ class PV(PVData, GenParam, PVModel):
136
+ """
137
+ PV generator model.
138
+ """
139
+
140
+ def __init__(self, system, config):
141
+ PVData.__init__(self)
142
+ GenParam.__init__(self)
143
+ PVModel.__init__(self, system, config)
144
+
145
+ Lastly, we need to finalize the model by adding the ``PV`` model to the model list in
146
+ ``$HOME/ams/ams/models/__init__.py``, where 'static' is the file name, and 'PV' is the
147
+ model name.
148
+
149
+ .. code-block:: python
150
+
151
+ ams_file_classes = list([
152
+ ('info', ['Summary']),
153
+ ('bus', ['Bus']),
154
+ ('static', ['PQ', 'PV', 'Slack']),
155
+ ... ...
156
+ ])
157
+
158
+ .. note::
159
+
160
+ The device-level model development procedures is similar to ANDES.
161
+ The only difference is that a device-level model for dispatch is much simpler
162
+ than that for dynamic simulation.
163
+ In AMS, we only defines the data and small amount of variables.
164
+ In contrast, ANDES defines the data, variables, and equations for dynamic simulation.
165
+ Mode details for device-level model development can be found in ANDES documentation
166
+ `Development - Examples <https://docs.andes.app/en/latest/modeling/examples.html>`_.
167
+
168
+ Line model
169
+ ^^^^^^^^^^^^^^
170
+
171
+ In this example, we define a ``Line`` model, where the data is extended from existing
172
+ ANDES ``LineData`` by including two extra parameters ``amin`` and ``amax``.
173
+
174
+ .. code-block:: python
175
+
176
+ from andes.models.line.line import LineData
177
+ from andes.core.param import NumParam
178
+ from andes.shared import deg2rad
179
+
180
+ from ams.core.model import Model
181
+
182
+
183
+ class Line(LineData, Model):
184
+ """
185
+ AC transmission line model.
186
+
187
+ The model is also used for two-winding transformer. Transformers can set the
188
+ tap ratio in ``tap`` and/or phase shift angle ``phi``.
189
+
190
+ Notes
191
+ -----
192
+ There is a known issue that adding Algeb ``ud`` will cause Line.algebs run into
193
+ AttributeError: 'NoneType' object has no attribute 'n'. Not figured out why yet.
194
+ """
195
+
196
+ def __init__(self, system=None, config=None) -> None:
197
+ LineData.__init__(self)
198
+ Model.__init__(self, system, config)
199
+ self.group = 'ACLine'
200
+
201
+ self.amin = NumParam(default=-360 * deg2rad,
202
+ info="minimum angle difference, from bus - to bus",
203
+ unit='rad',
204
+ tex_name=r'a_{min}',
205
+ )
206
+ self.amax = NumParam(default=360 * deg2rad,
207
+ info="maximum angle difference, from bus - to bus",
208
+ unit='rad',
209
+ tex_name=r'a_{max}',
210
+ )
@@ -0,0 +1,122 @@
1
+ Routine
2
+ ===========
3
+
4
+ Routine refers to scheduling-level model, and it includes two sectinos, namely,
5
+ Data Section and Model Section.
6
+
7
+ Data Section
8
+ ------------------
9
+
10
+ A simplified code snippet for RTED is shown below as an example.
11
+
12
+ .. code-block:: python
13
+
14
+ class RTED:
15
+
16
+ def __init__(self):
17
+ ... ...
18
+ self.R10 = RParam(info='10-min ramp rate',
19
+ name='R10', tex_name=r'R_{10}',
20
+ model='StaticGen', src='R10',
21
+ unit='p.u./h',)
22
+ self.gs = ZonalSum(u=self.zg, zone='Zone',
23
+ name='gs', tex_name=r'S_{g}',
24
+ info='Sum Gen vars vector in shape of zone',
25
+ no_parse=True, sparse=True)
26
+ ... ...
27
+ self.rbu = Constraint(name='rbu', is_eq=True,
28
+ info='RegUp reserve balance',
29
+ e_str = 'gs @ mul(ug, pru) - dud')
30
+ ... ...
31
+
32
+ Routine Parameter
33
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
34
+
35
+ As discussed in previous section, actual data parameters are stored in the device-level models.
36
+ Thus, in routines, parameters are retrieved from target devices given the device
37
+ name and the parameter name.
38
+ In the example above, ``R10`` is a 10-min ramp rate parameter for the static generator.
39
+ The parameter is retrieved from the devices ``StaticGen`` with the parameter name ``R10``.
40
+
41
+ Service
42
+ ^^^^^^^^^^^^
43
+
44
+ Services are developed to assit the formulations.
45
+ In the example above, ``ZonalSum`` is a service to sum the generator variables in a zone.
46
+ Later, in the constraint, ``gs`` is multiplied to the reserve variable ``pru``.
47
+
48
+ Model Section
49
+ -----------------
50
+
51
+ Descriptive Formulation
52
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
53
+ Scheduling routine is the descriptive model of the optimization problem.
54
+
55
+ Further, to facilitate the routine definition, AMS developed a class
56
+ :py:mod:`ams.core.param.RParam` to pass the model data to multiple routine modeling.
57
+
58
+ .. autoclass:: ams.core.param.RParam
59
+ :noindex:
60
+
61
+ Numerical Optimization
62
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
63
+
64
+ Optimization model is the optimization problem. ``Var``, ``Constraint``, and
65
+ ``Objective`` are the basic building blocks of the optimization model. ``OModel``
66
+ is the container of the optimization model.
67
+ A summary table is shown below.
68
+
69
+ .. currentmodule:: ams.opt
70
+ .. autosummary::
71
+ :recursive:
72
+ :toctree: _generated
73
+
74
+ Var
75
+ Constraint
76
+ Objective
77
+ OModel
78
+
79
+ Interoperation with ANDES
80
+ -----------------------------------
81
+
82
+ The interoperation with dynamic simulator invovles both file conversion and data exchange.
83
+ In AMS, the built-in interface with ANDES is implemented in :py:mod:`ams.interface`.
84
+
85
+
86
+ File Format Converter
87
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
88
+
89
+ Power flow data is the bridge between scheduling study and dynamics study,
90
+ where it defines grid topology and power flow.
91
+ An AMS case can be converted to an ANDES case, with the option to supply additional dynamic
92
+ data.
93
+
94
+ .. autofunction:: ams.interface.to_andes
95
+ :noindex:
96
+
97
+
98
+ Data Exchange in Simulation
99
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
100
+
101
+ To achieve scheduling-dynamics cosimulation, it requires bi-directional data exchange between
102
+ scheduling and dynamics study.
103
+ From the perspective of AMS, two functions, ``send`` and ``receive``, are developed.
104
+ The maping relationship for a specific routine is defined in the routine class as ``map1`` and
105
+ ``map2``.
106
+ Additionally, a link table for the ANDES case is used for the controller connections.
107
+
108
+ Module :py:mod:`ams.interface.Dynamic`, contains the necessary functions and classes for
109
+ file conversion and data exchange.
110
+
111
+ .. autoclass:: ams.interface.Dynamic
112
+ :noindex:
113
+ :members: send, receive
114
+
115
+ When you use this interface, it automatically picks either the dynamic or static model based on the TDS initialization status.
116
+ If the TDS is running, it selects the dynamic model; otherwise, it goes for the static model.
117
+ For more details, check out the full API reference or take a look at the source code.
118
+
119
+ .. note::
120
+ Check ANDES documentation
121
+ `StaticGen <https://docs.andes.app/en/latest/groupdoc/StaticGen.html#staticgen>`_
122
+ for more details about substituting static generators with dynamic generators.
@@ -0,0 +1,51 @@
1
+ System
2
+ ======
3
+
4
+
5
+ Overview
6
+ --------
7
+ System is the top-level class for organizing power system dispatch models
8
+ and routines. The full API reference of System is found at
9
+ :py:mod:`ams.system.System`.
10
+
11
+ Dynamic Imports
12
+ ```````````````
13
+ System dynamically imports groups, models, and routines at creation. To add new
14
+ models, groups or routines, edit the corresponding file by adding entries
15
+ following examples.
16
+
17
+ .. autofunction:: ams.system.System.import_models
18
+ :noindex:
19
+
20
+ .. autofunction:: ams.system.System.import_groups
21
+ :noindex:
22
+
23
+ .. autofunction:: ams.system.System.import_routines
24
+ :noindex:
25
+
26
+ .. autofunction:: ams.system.System.import_types
27
+ :noindex:
28
+
29
+
30
+ Device-level Models
31
+ ------------------------
32
+ AMS follows a similar device-level model organization of ANDES with a few differences.
33
+
34
+
35
+ Routine-level Models
36
+ ------------------------
37
+ In AMS, routines are responsible for collecting data, defining optimization
38
+ problems, and solving them.
39
+
40
+
41
+ Optimization
42
+ --------------------------------------------
43
+
44
+ Within the ``Routine``, the descriptive formulation are translated into
45
+ `CVXPY <https://www.cvxpy.org/>`_ optimization problem with
46
+ ``Vars``, ``Constraints``, and ``Objective``.
47
+ The full API reference of them can be found in :py:mod:`ams.opt.Var`,
48
+ :py:mod:`ams.opt.Constraint`, and :py:mod:`ams.opt.Objective`.
49
+
50
+ .. autoclass:: ams.opt.omodel.OModel
51
+ :noindex: