ltbams 1.0.13__py3-none-any.whl → 1.0.15__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 (46) hide show
  1. ams/_version.py +3 -3
  2. ams/cli.py +2 -7
  3. ams/core/common.py +7 -3
  4. ams/core/documenter.py +2 -1
  5. ams/core/matprocessor.py +4 -4
  6. ams/core/model.py +14 -6
  7. ams/core/param.py +5 -3
  8. ams/core/symprocessor.py +8 -2
  9. ams/core/var.py +1 -1
  10. ams/extension/eva.py +11 -7
  11. ams/interface.py +7 -7
  12. ams/io/json.py +20 -16
  13. ams/io/matpower.py +6 -6
  14. ams/io/psse.py +2 -1
  15. ams/io/xlsx.py +21 -16
  16. ams/main.py +53 -45
  17. ams/models/distributed/esd1.py +4 -7
  18. ams/models/distributed/ev.py +10 -6
  19. ams/models/distributed/pvd1.py +4 -7
  20. ams/models/group.py +17 -18
  21. ams/models/renewable/regc.py +14 -22
  22. ams/models/timeslot.py +46 -1
  23. ams/models/zone.py +2 -4
  24. ams/opt/exprcalc.py +5 -3
  25. ams/opt/optzbase.py +4 -3
  26. ams/report.py +2 -7
  27. ams/routines/dcopf.py +7 -4
  28. ams/routines/dcopf2.py +46 -21
  29. ams/routines/dcpf.py +5 -0
  30. ams/routines/dopf.py +2 -2
  31. ams/routines/ed.py +5 -5
  32. ams/routines/pflow.py +1 -1
  33. ams/routines/routine.py +20 -4
  34. ams/routines/rted.py +5 -5
  35. ams/routines/uc.py +2 -2
  36. ams/shared.py +69 -0
  37. ams/system.py +93 -18
  38. ams/utils/paths.py +6 -10
  39. docs/source/examples/index.rst +1 -0
  40. docs/source/genroutineref.py +24 -0
  41. docs/source/release-notes.rst +15 -0
  42. {ltbams-1.0.13.dist-info → ltbams-1.0.15.dist-info}/METADATA +19 -22
  43. {ltbams-1.0.13.dist-info → ltbams-1.0.15.dist-info}/RECORD +46 -46
  44. {ltbams-1.0.13.dist-info → ltbams-1.0.15.dist-info}/WHEEL +0 -0
  45. {ltbams-1.0.13.dist-info → ltbams-1.0.15.dist-info}/entry_points.txt +0 -0
  46. {ltbams-1.0.13.dist-info → ltbams-1.0.15.dist-info}/top_level.txt +0 -0
@@ -12,13 +12,17 @@ class EV1(ModelData, Model):
12
12
  """
13
13
  Aggregated EV model for scheduling at transmission level.
14
14
 
15
- For co-simulation with ADNES, it is expected to be used in
15
+ For co-simulation with ANDES, it is expected to be used in
16
16
  conjunction with the dynamic models `EV1` or `EV2`.
17
17
 
18
- Reference:
19
-
20
- [1] J. Wang et al., "Electric Vehicles Charging Time Constrained Deliverable Provision of Secondary
21
- Frequency Regulation," in IEEE Transactions on Smart Grid, doi: 10.1109/TSG.2024.3356948.
18
+ References
19
+ ----------
20
+ 1. J. Wang et al., "Electric Vehicles Charging Time Constrained
21
+ Deliverable Provision of Secondary Frequency Regulation," in IEEE
22
+ Transactions on Smart Grid, vol. 15, no. 4, pp. 3892-3903, July
23
+ 2024, doi: 10.1109/TSG.2024.3356948.
24
+ 2. ANDES Documentation, EV1,
25
+ https://andes.readthedocs.io/en/stable/groupdoc/DG.html#ev1
22
26
  """
23
27
 
24
28
  def __init__(self, system, config):
@@ -53,7 +57,7 @@ class EV1(ModelData, Model):
53
57
 
54
58
  class EV2(EV1):
55
59
  """
56
- EV aggregation model at transmission level, identical to :ref:`EV1`.
60
+ Alias for EV1.
57
61
  """
58
62
 
59
63
  def __init__(self, system=None, config=None) -> None:
@@ -52,13 +52,10 @@ class PVD1(PVD1Data, Model):
52
52
  ``vt3``, ``vrflag``, ``ft0``, ``ft1``, ``ft2``, ``ft3``, ``frflag``,
53
53
  ``tip``, ``tiq``, ``recflag``.
54
54
 
55
- Reference:
56
-
57
- [1] ANDES Documentation, PVD1
58
-
59
- Available:
60
-
61
- https://docs.andes.app/en/latest/groupdoc/DG.html#pvd1
55
+ References
56
+ ----------
57
+ 1. ANDES Documentation, PVD1,
58
+ https://andes.readthedocs.io/en/stable/groupdoc/DG.html#pvd1
62
59
  """
63
60
 
64
61
  def __init__(self, system, config):
ams/models/group.py CHANGED
@@ -3,22 +3,24 @@ import logging
3
3
  from andes.models.group import GroupBase as adGroupBase
4
4
  from andes.core.service import BackRef
5
5
 
6
+ from ams.utils.misc import deprec_get_idx
7
+
6
8
  logger = logging.getLogger(__name__)
7
9
 
8
10
 
9
11
  class GroupBase(adGroupBase):
10
12
  """
11
- Base class for groups.
13
+ Base class for groups, revised from
14
+ `andes.models.group.GroupBase`.
12
15
 
13
16
  Add common_vars and common_params to the group class.
14
-
15
- This class is revised from ``andes.models.group.GroupBase``.
16
17
  """
17
18
 
18
19
  def __init__(self):
19
20
  super().__init__()
20
21
  self.common_params.extend(('idx',))
21
22
 
23
+ @deprec_get_idx
22
24
  def get_idx(self):
23
25
  """
24
26
  Return the value of group idx sorted in a human-readable style.
@@ -27,6 +29,9 @@ class GroupBase(adGroupBase):
27
29
  -----
28
30
  This function sorts the idx values using a custom sorting key,
29
31
  which handles varying length strings with letters and numbers.
32
+
33
+ .. deprecated:: 1.0.0
34
+ Use ``get_all_idxes`` instead.
30
35
  """
31
36
  all_idx = [mdl.idx.v for mdl in self.models.values()]
32
37
  flat_list = [item for sublist in all_idx for item in sublist]
@@ -94,13 +99,10 @@ class RenGen(GroupBase):
94
99
  See ANDES Documentation SynGen here for the notes on replacing StaticGen and setting the power
95
100
  ratio parameters.
96
101
 
97
- Reference:
98
-
99
- [1] ANDES Documentation, RenGen, [Online]
100
-
101
- Available:
102
-
103
- https://docs.andes.app/en/latest/groupdoc/RenGen.html#rengen
102
+ References
103
+ ----------
104
+ 1. ANDES Documentation, RenGen,
105
+ https://andes.readthedocs.io/en/stable/groupdoc/RenGen.html#rengen
104
106
  """
105
107
 
106
108
  def __init__(self):
@@ -129,13 +131,10 @@ class DG(GroupBase):
129
131
  See ANDES Documentation SynGen here for the notes on replacing StaticGen and setting the power
130
132
  ratio parameters.
131
133
 
132
- Reference:
133
-
134
- [1] ANDES Documentation, SynGen, [Online]
135
-
136
- Available:
137
-
138
- https://docs.andes.app/en/latest/groupdoc/SynGen.html#syngen
134
+ References
135
+ ----------
136
+ 1. ANDES Documentation, SynGen,
137
+ https://andes.readthedocs.io/en/stable/groupdoc/SynGen.html#syngen
139
138
  """
140
139
 
141
140
  def __init__(self):
@@ -182,7 +181,7 @@ class StaticGen(GroupBase):
182
181
  Notes
183
182
  -----
184
183
  For co-simulation with ANDES, refer to the `ANDES StaticGen Documentation
185
- <https://docs.andes.app/en/latest/groupdoc/StaticGen.html#staticgen>`_ for
184
+ <https://andes.readthedocs.io/en/stable/groupdoc/StaticGen.html#staticgen>`_ for
186
185
  replacing static generators with dynamic generators.
187
186
  """
188
187
 
@@ -39,12 +39,10 @@ class REGCA1(REGCData, Model):
39
39
  """
40
40
  Renewable generator scheduling model.
41
41
 
42
- Reference:
43
-
44
- [1] ANDES Documentation, REGCA1
45
-
46
- Available:
47
- https://docs.andes.app/en/latest/groupdoc/RenGen.html#regca1
42
+ References
43
+ ----------
44
+ 1. ANDES Documentation, REGCA1,
45
+ https://andes.readthedocs.io/en/stable/groupdoc/RenGen.html#regca1
48
46
  """
49
47
 
50
48
  def __init__(self, system=None, config=None) -> None:
@@ -56,7 +54,7 @@ class REGCA1(REGCData, Model):
56
54
  class REGCV1(REGCData, Model):
57
55
  """
58
56
  Voltage-controlled converter model (virtual synchronous generator) with
59
- inertia emulation.
57
+ inertia emulation, for scheduling purposes.
60
58
 
61
59
  Here Mmax and Dmax are assumed to be constant, but they might subject to
62
60
  the operating condition of the converter.
@@ -67,13 +65,10 @@ class REGCV1(REGCData, Model):
67
65
  - Generation cost is defined by model :ref:`GCost`
68
66
  - Inertia emulation cost is defined by model :ref:`VSGCost`
69
67
 
70
- Reference:
71
-
72
- [1] ANDES Documentation, REGCV1
73
-
74
- Available:
75
-
76
- https://docs.andes.app/en/latest/groupdoc/RenGen.html#regcv1
68
+ References
69
+ ----------
70
+ 1. ANDES Documentation, REGCV1,
71
+ https://andes.readthedocs.io/en/stable/groupdoc/RenGen.html#regcv1
77
72
  """
78
73
 
79
74
  def __init__(self, system=None, config=None) -> None:
@@ -100,15 +95,12 @@ class REGCV1(REGCData, Model):
100
95
 
101
96
  class REGCV2(REGCV1):
102
97
  """
103
- Voltage-controlled VSC, identical to :ref:`REGCV1`.
104
-
105
- Reference:
106
-
107
- [1] ANDES Documentation, REGCV2
108
-
109
- Available:
98
+ Alias for REGCV1, for scheduling purposes.
110
99
 
111
- https://docs.andes.app/en/latest/groupdoc/RenGen.html#regcv2
100
+ References
101
+ ----------
102
+ 1. ANDES Documentation, REGCV2,
103
+ https://andes.readthedocs.io/en/stable/groupdoc/RenGen.html#regcv2
112
104
  """
113
105
 
114
106
  def __init__(self, system=None, config=None) -> None:
ams/models/timeslot.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """
2
- Model for rolling horizon used in scheduling.
2
+ Models for multi-period scheduling.
3
3
  """
4
4
 
5
5
  from andes.core import ModelData, NumParam
@@ -10,12 +10,43 @@ from ams.core.model import Model
10
10
  def str_list_oconv(x):
11
11
  """
12
12
  Convert list into a list literal.
13
+
14
+ Revised from `andes.models.timeseries.str_list_oconv`, where
15
+ the output type is converted to a list of strings.
13
16
  """
14
17
  # NOTE: convert elements to string from number first, then join them
15
18
  str_x = [str(i) for i in x]
16
19
  return ','.join(str_x)
17
20
 
18
21
 
22
+ class GCommit(ModelData, Model):
23
+ """
24
+ UNDER DEVELOPMENT!
25
+ Time slot model for generator commitment decisions.
26
+
27
+ This class holds commitment decisions for generators,
28
+ and should be used in multi-period scheduling routines that need
29
+ generator commitment decisions.
30
+
31
+ For example, in Unit Commitment (UC) problems, there is a variable
32
+ `ugd` representing the unit commitment decisions for each generator.
33
+ After solving the UC problem, the `ugd` values can be used for
34
+ Economic Dispatch (ED) as a parameter.
35
+ """
36
+
37
+ # TODO: .. versionadded:: 1.0.13
38
+ def __init__(self, system=None, config=None):
39
+ ModelData.__init__(self)
40
+ Model.__init__(self, system, config)
41
+
42
+ # TODO: add IdxParam of generator
43
+ self.ug = NumParam(info='unit commitment decisions',
44
+ tex_name=r'u_{g}',
45
+ iconvert=str_list_iconv,
46
+ oconvert=str_list_oconv,
47
+ vtype=int)
48
+
49
+
19
50
  class TimeSlot(ModelData, Model):
20
51
  """
21
52
  Base model for time slot data used in multi-interval scheduling.
@@ -44,6 +75,13 @@ class EDTSlot(TimeSlot):
44
75
  `ug` is the unit commitment decisions.
45
76
  Cells in `ug` should have `ng` values seperated by comma,
46
77
  where `ng` is the number of `StaticGen` in the system.
78
+
79
+ Warnings
80
+ --------
81
+ The order of generators in `ug` is determined by the input
82
+ file, not by explicit mapping. This may cause misinterpretation
83
+ if the loaded data order changes.
84
+ Involved routines include: `ED` `UC` and their derivatives.
47
85
  """
48
86
 
49
87
  def __init__(self, system=None, config=None):
@@ -63,6 +101,13 @@ class UCTSlot(TimeSlot):
63
101
  `sd` is the zonal load scaling factor.
64
102
  Cells in `sd` should have `nz` values seperated by comma,
65
103
  where `nz` is the number of `Zone` in the system.
104
+
105
+ Warnings
106
+ --------
107
+ The order of generators in `ug` is determined by the input
108
+ file, not by explicit mapping. This may cause misinterpretation
109
+ if the loaded data order changes.
110
+ Involved routines include: `ED` `UC` and their derivatives.
66
111
  """
67
112
 
68
113
  def __init__(self, system=None, config=None):
ams/models/zone.py CHANGED
@@ -17,9 +17,8 @@ class Zone(ModelData, Model):
17
17
 
18
18
  Notes
19
19
  -----
20
- 1. Zone is a collection of buses.
21
- 2. Model ``Zone`` is not actually defined in ANDES.
22
-
20
+ - A zone is a collection of buses.
21
+ - The ``Zone`` model is not defined in ANDES up to version 1.9.3.
23
22
  """
24
23
 
25
24
  def __init__(self, system, config):
@@ -39,7 +38,6 @@ class Zone(ModelData, Model):
39
38
  -------
40
39
  str
41
40
  Formatted table
42
-
43
41
  """
44
42
  if self.n:
45
43
  header = ['Zone ID', 'Bus ID']
ams/opt/exprcalc.py CHANGED
@@ -24,9 +24,11 @@ class ExpressionCalc(OptzBase):
24
24
  """
25
25
  Class for calculating expressions.
26
26
 
27
- Note that `ExpressionCalc` is not a CVXPY expression, and it should not be used
28
- in the optimization model.
29
- It is used to calculate expression values **after** successful optimization.
27
+ This class is useful for performing post-solve calculations, but it does not
28
+ participate in the optimization model itself.
29
+
30
+ Note: `ExpressionCalc` is not a CVXPY expression and should NOT be referenced
31
+ in `e_str` by any other components, including other instances of `ExpressionCalc`.
30
32
  """
31
33
 
32
34
  def __init__(self,
ams/opt/optzbase.py CHANGED
@@ -174,13 +174,14 @@ class OptzBase:
174
174
  """
175
175
  Return all the indexes of this item.
176
176
 
177
- .. note::
178
- New in version 1.0.0.
179
-
180
177
  Returns
181
178
  -------
182
179
  list
183
180
  A list of indexes.
181
+
182
+ Notes
183
+ -----
184
+ .. versionadded:: 1.0.0
184
185
  """
185
186
 
186
187
  if self.is_group:
ams/report.py CHANGED
@@ -30,13 +30,8 @@ def report_info(system) -> list:
30
30
 
31
31
  class Report:
32
32
  """
33
- Report class to store routine analysis reports.
34
-
35
- Notes
36
- -----
37
- Revised from the ANDES project (https://github.com/CURENT/andes).
38
- Original author: Hantao Cui
39
- License: GPL3
33
+ Report class to store routine analysis reports,
34
+ revised from `andes.report.Report`.
40
35
  """
41
36
 
42
37
  def __init__(self, system):
ams/routines/dcopf.py CHANGED
@@ -17,19 +17,22 @@ logger = logging.getLogger(__name__)
17
17
 
18
18
  class DCOPF(DCPFBase):
19
19
  """
20
- DC optimal power flow (DCOPF).
20
+ DC optimal power flow (DCOPF) using B-theta formulation.
21
21
 
22
22
  Notes
23
23
  -----
24
- 1. The nodal price is calculated as ``pi`` in ``pic``.
25
- 2. Devices online status of ``StaticGen``, ``StaticLoad``, and ``Shunt`` are considered in the connectivity
26
- matrices ``Cft``, ``Cg``, ``Cl``, and ``Csh``.
24
+ - The nodal price is calculated as ``pi`` in ``pic``.
25
+ - Devices online status of ``StaticGen``, ``StaticLoad``, and ``Shunt`` are considered in the connectivity
26
+ matrices ``Cft``, ``Cg``, ``Cl``, and ``Csh``.
27
27
 
28
28
  References
29
29
  ----------
30
30
  1. R. D. Zimmerman, C. E. Murillo-Sanchez, and R. J. Thomas, “MATPOWER: Steady-State
31
31
  Operations, Planning, and Analysis Tools for Power Systems Research and Education,” IEEE
32
32
  Trans. Power Syst., vol. 26, no. 1, pp. 12-19, Feb. 2011
33
+ 2. Y. Chen et al., "Security-Constrained Unit Commitment for Electricity Market: Modeling,
34
+ Solution Methods, and Future Challenges," in IEEE Transactions on Power Systems, vol. 38, no. 5,
35
+ pp. 4668-4681, Sept. 2023
33
36
  """
34
37
 
35
38
  def __init__(self, system, config):
ams/routines/dcopf2.py CHANGED
@@ -18,15 +18,35 @@ logger = logging.getLogger(__name__)
18
18
 
19
19
  class DCOPF2(DCOPF):
20
20
  """
21
- DC optimal power flow (DCOPF) using PTDF.
21
+ DC optimal power flow (DCOPF) using PTDF formulation.
22
+
22
23
  For large cases, it is recommended to build the PTDF first, especially when incremental
23
24
  build is necessary.
24
25
 
25
26
  Notes
26
27
  -----
27
- 1. This routine requires PTDF matrix.
28
- 2. Nodal price ``pi`` is calculated with three parts.
29
- 3. Bus angle ``aBus`` is calculated after solving the problem.
28
+ - This routine requires PTDF matrix.
29
+ - LMP ``pi`` is calculated with two parts, energy price and congestion price.
30
+ - Bus angle ``aBus`` is calculated after solving the problem.
31
+ - In export results, ``pi`` and ``pic`` are kept for each bus, while ``pie``
32
+ can be restored manually by ``pie = pi - pic`` if needed.
33
+
34
+ Warning
35
+ -------
36
+ In this implementation, the dual variables for constraints have opposite signs compared
37
+ to the mathematical formulation: 1. The dual of `pb` returns a negative value, so energy
38
+ price is computed as `-pb.dual_variables[0]`. 2. Similarly, a minus sign is applied to
39
+ the duals of `plfub` and `plflb` when calculating congestion price. The reason for this
40
+ sign difference is not yet fully understood.
41
+
42
+ References
43
+ ----------
44
+ 1. R. D. Zimmerman, C. E. Murillo-Sanchez, and R. J. Thomas, “MATPOWER: Steady-State
45
+ Operations, Planning, and Analysis Tools for Power Systems Research and Education,” IEEE
46
+ Trans. Power Syst., vol. 26, no. 1, pp. 12-19, Feb. 2011
47
+ 2. Y. Chen et al., "Security-Constrained Unit Commitment for Electricity Market: Modeling,
48
+ Solution Methods, and Future Challenges," in IEEE Transactions on Power Systems, vol. 38, no. 5,
49
+ pp. 4668-4681, Sept. 2023
30
50
  """
31
51
 
32
52
  def __init__(self, system, config):
@@ -51,29 +71,34 @@ class DCOPF2(DCOPF):
51
71
  name='PTDF', tex_name=r'P_{TDF}',
52
72
  model='mats', src='PTDF',
53
73
  no_parse=True, sparse=True)
74
+ self.PTDFt = NumOp(u=self.PTDF,
75
+ name='PTDFt', tex_name=r'P_{TDF}^T',
76
+ info='PTDF transpose',
77
+ fun=np.transpose, no_parse=True)
78
+
79
+ # --- rewrite Constraint pb: power balance ---
80
+ self.pb.e_str = 'sum(pg) - sum(pd)'
54
81
 
55
82
  # --- rewrite Expression plf: line flow---
56
83
  self.plf.e_str = 'PTDF @ (Cg@pg - Cl@pd - Csh@gsh - Pbusinj)'
57
84
 
58
85
  # --- rewrite nodal price ---
59
- self.Cft = RParam(info='Line connection matrix',
60
- name='Cft', tex_name=r'C_{ft}',
61
- model='mats', src='Cft',
62
- no_parse=True, sparse=True,)
63
- self.pilb = ExpressionCalc(info='Congestion price, dual of <plflb>',
64
- name='pilb',
65
- model='Line', src=None,
66
- e_str='plflb.dual_variables[0]')
67
- self.piub = ExpressionCalc(info='Congestion price, dual of <plfub>',
68
- name='piub',
69
- model='Line', src=None,
70
- e_str='plfub.dual_variables[0]')
71
- self.pib = ExpressionCalc(info='Energy price, dual of <pb>',
72
- name='pib',
73
- model='Bus', src=None,
74
- e_str='pb.dual_variables[0]')
75
- pi = 'pb.dual_variables[0] + Cft@(plfub.dual_variables[0] - plflb.dual_variables[0])'
86
+ self.pie = ExpressionCalc(info='Energy price',
87
+ name='pie', unit='$/p.u.',
88
+ e_str='-pb.dual_variables[0]')
89
+ pic = '-PTDFt@(plfub.dual_variables[0] - plflb.dual_variables[0])'
90
+ self.pic = ExpressionCalc(info='Congestion price',
91
+ name='pic', unit='$/p.u.',
92
+ e_str=pic,
93
+ model='Bus', src=None)
94
+
95
+ # NOTE: another implementation of self.pi.e_str can be:
96
+ # self.pi.e_str = self.pie.e_str + self.pic.e_str
97
+ # but it is less intuitive to read, as this implementation is not likely
98
+ # to be used again in other routines.
99
+ pi = '-pb.dual_variables[0] - PTDFt@(plfub.dual_variables[0] - plflb.dual_variables[0])'
76
100
  self.pi.e_str = pi
101
+ self.pi.info = 'locational marginal price (LMP)'
77
102
 
78
103
  def _post_solve(self):
79
104
  """Calculate aBus"""
ams/routines/dcpf.py CHANGED
@@ -3,6 +3,8 @@ Power flow routines.
3
3
  """
4
4
  import logging
5
5
 
6
+ import numpy as np
7
+
6
8
  from ams.opt import Var, Constraint, Expression, Objective
7
9
  from ams.routines.routine import RoutineBase
8
10
 
@@ -173,6 +175,9 @@ class DCPFBase(RoutineBase):
173
175
  """
174
176
  Post-solve calculations.
175
177
  """
178
+ # NOTE: for DC type routines, set vBus to 1.0 p.u. as placeholder
179
+ self.vBus.v = np.ones(self.vBus.shape)
180
+
176
181
  # NOTE: unpack Expressions if owner and arc are available
177
182
  for expr in self.exprs.values():
178
183
  if expr.owner and expr.src:
ams/routines/dopf.py CHANGED
@@ -17,7 +17,7 @@ class DOPF(DCOPF):
17
17
  UNDER DEVELOPMENT!
18
18
 
19
19
  References
20
- -----------------
20
+ ----------
21
21
  1. L. Bai, J. Wang, C. Wang, C. Chen, and F. Li, “Distribution Locational Marginal Pricing (DLMP)
22
22
  for Congestion Management and Voltage Support,” IEEE Trans. Power Syst., vol. 33, no. 4,
23
23
  pp. 4061-4073, Jul. 2018, doi: 10.1109/TPWRS.2017.2767632.
@@ -116,7 +116,7 @@ class DOPFVIS(DOPF):
116
116
  UNDER DEVELOPMENT!
117
117
 
118
118
  References
119
- -----------------
119
+ ----------
120
120
  1. L. Bai, J. Wang, C. Wang, C. Chen, and F. Li, “Distribution Locational Marginal Pricing (DLMP)
121
121
  for Congestion Management and Voltage Support,” IEEE Trans. Power Syst., vol. 33, no. 4,
122
122
  pp. 4061-4073, Jul. 2018, doi: 10.1109/TPWRS.2017.2767632.
ams/routines/ed.py CHANGED
@@ -120,11 +120,11 @@ class ED(RTED, MPBase, SRBase):
120
120
 
121
121
  Notes
122
122
  -----
123
- 1. Formulations has been adjusted with interval ``config.t``
124
- 2. The tie-line flow is not implemented in this model.
125
- 3. ``EDTSlot.ug`` is used instead of ``StaticGen.u`` for generator commitment.
126
- 4. Following reserves are balanced for each "Area": RegUp reserve ``rbu``,
127
- RegDn reserve ``rbd``, and Spinning reserve ``rsr``.
123
+ - Formulations has been adjusted with interval ``config.t``
124
+ - The tie-line flow is not implemented in this model.
125
+ - ``EDTSlot.ug`` is used instead of ``StaticGen.u`` for generator commitment.
126
+ - Following reserves are balanced for each "Area": RegUp reserve ``rbu``,
127
+ RegDn reserve ``rbd``, and Spinning reserve ``rsr``.
128
128
  """
129
129
 
130
130
  def __init__(self, system, config):
ams/routines/pflow.py CHANGED
@@ -30,7 +30,7 @@ class PFlow(RoutineBase):
30
30
  ----------
31
31
  1. M. L. Crow, Computational methods for electric power systems. 2015.
32
32
  2. ANDES Documentation - Simulation and Plot.
33
- https://docs.andes.app/en/latest/_examples/ex1.html
33
+ https://andes.readthedocs.io/en/stable/_examples/ex1.html
34
34
  """
35
35
 
36
36
  def __init__(self, system, config):
ams/routines/routine.py CHANGED
@@ -21,7 +21,7 @@ from ams.opt import Param, Var, Constraint, Objective, ExpressionCalc, Expressio
21
21
 
22
22
  from ams.utils.paths import get_export_path
23
23
 
24
- from ams.shared import pd
24
+ from ams.shared import pd, summary_row, summary_name
25
25
 
26
26
  logger = logging.getLogger(__name__)
27
27
 
@@ -445,6 +445,8 @@ class RoutineBase:
445
445
  -------
446
446
  bool
447
447
  True if the loading is successful, False otherwise.
448
+
449
+ .. versionadded:: 1.0.13
448
450
  """
449
451
  try:
450
452
  with open(path, 'r') as f:
@@ -496,15 +498,26 @@ class RoutineBase:
496
498
  -------
497
499
  str
498
500
  The exported json file name
501
+
502
+ .. versionadded:: 1.0.13
499
503
  """
500
504
  if not self.converged:
501
505
  logger.warning("Routine did not converge, aborting export.")
502
506
  return None
503
507
 
504
- path, file_name = get_export_path(self.system, self.class_name,
508
+ path, file_name = get_export_path(self.system,
509
+ self.class_name + '_out',
505
510
  path=path, fmt='json')
506
511
 
507
- data_dict = dict()
512
+ data_dict = OrderedDict()
513
+
514
+ # insert summary
515
+ df = pd.DataFrame([summary_row])
516
+ df.index.name = "uid"
517
+ data_dict.update({summary_name: df.to_dict(orient='records')})
518
+
519
+ # insert objective value
520
+ data_dict.update(OrderedDict(Objective=self.obj.v))
508
521
 
509
522
  group_data(self, data_dict, self.vars, 'v')
510
523
  group_data(self, data_dict, self.exprs, 'v')
@@ -1111,7 +1124,8 @@ def collect_data(rtn: RoutineBase, data_dict: Dict, items: Dict, attr: str):
1111
1124
 
1112
1125
  def group_data(rtn: RoutineBase, data_dict: Dict, items: Dict, attr: str):
1113
1126
  """
1114
- Collect data for export from grouped items.
1127
+ Collect data for export by groups, adding device idx in each group.
1128
+ This is useful when exporting to dictionary formats like JSON.
1115
1129
 
1116
1130
  Parameters
1117
1131
  ----------
@@ -1123,6 +1137,8 @@ def group_data(rtn: RoutineBase, data_dict: Dict, items: Dict, attr: str):
1123
1137
  Dictionary of items to collect data from.
1124
1138
  attr : str
1125
1139
  Attribute to collect data for.
1140
+
1141
+ .. versionadded:: 1.0.13
1126
1142
  """
1127
1143
  for key, item in items.items():
1128
1144
  if item.owner is None:
ams/routines/rted.py CHANGED
@@ -125,10 +125,10 @@ class RTED(DCOPF, RTEDBase, SFRBase):
125
125
 
126
126
  Notes
127
127
  -----
128
- 1. Formulations has been adjusted with interval ``config.t``, 5/60 [Hour] by default.
129
- 2. The tie-line flow related constraints are ommited in this formulation.
130
- 3. The power balance is solved for the entire system.
131
- 4. The SFR is solved for each area.
128
+ - Formulations has been adjusted with interval ``config.t``, 5/60 [Hour] by default.
129
+ - The tie-line flow related constraints are ommited in this formulation.
130
+ - Power generation is balanced for the entire system.
131
+ - SFR is balanced for each area.
132
132
  """
133
133
 
134
134
  def __init__(self, system, config):
@@ -487,7 +487,7 @@ class RTEDVIS(RTED, VISBase):
487
487
  Please ensure that the parameters `dvm` and `dvd` are set according to the system base.
488
488
 
489
489
  References
490
- -----------------
490
+ ----------
491
491
  1. B. She, F. Li, H. Cui, J. Wang, Q. Zhang and R. Bo, "Virtual Inertia Scheduling (VIS) for
492
492
  Real-Time Economic Dispatch of IBR-Penetrated Power Systems," in IEEE Transactions on
493
493
  Sustainable Energy, vol. 15, no. 2, pp. 938-951, April 2024, doi: 10.1109/TSTE.2023.3319307.
ams/routines/uc.py CHANGED
@@ -69,8 +69,8 @@ class UC(DCOPF, RTEDBase, MPBase, SRBase, NSRBase):
69
69
 
70
70
  Notes
71
71
  -----
72
- 1. Formulations has been adjusted with interval ``config.t``
73
- 2. The tie-line flow has not been implemented in formulations.
72
+ - The formulations has been adjusted with interval ``config.t``
73
+ - The tie-line flow has not been implemented in formulations.
74
74
 
75
75
  References
76
76
  ----------