ltbams 1.0.6__py3-none-any.whl → 1.0.7__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/cases/5bus/pjm5bus_demo.xlsx +0 -0
  3. ams/cases/5bus/pjm5bus_ev.xlsx +0 -0
  4. ams/cases/5bus/pjm5bus_jumper.xlsx +0 -0
  5. ams/cases/ieee14/ieee14_uced.xlsx +0 -0
  6. ams/cases/ieee39/ieee39_uced.xlsx +0 -0
  7. ams/cases/ieee39/ieee39_uced_esd1.xlsx +0 -0
  8. ams/cases/ieee39/ieee39_uced_pvd1.xlsx +0 -0
  9. ams/cases/ieee39/ieee39_uced_vis.xlsx +0 -0
  10. ams/core/matprocessor.py +7 -16
  11. ams/core/service.py +4 -3
  12. ams/interface.py +17 -4
  13. ams/models/__init__.py +1 -1
  14. ams/models/group.py +2 -2
  15. ams/models/line.py +2 -2
  16. ams/models/renewable/regc.py +1 -5
  17. ams/models/reserve.py +2 -2
  18. ams/models/static/gen.py +2 -2
  19. ams/models/static/pq.py +2 -2
  20. ams/models/timeslot.py +1 -1
  21. ams/routines/dcopf.py +1 -1
  22. ams/routines/dopf.py +10 -10
  23. ams/routines/ed.py +3 -4
  24. ams/routines/pflow.py +9 -10
  25. ams/routines/rted.py +20 -29
  26. ams/routines/uc.py +1 -1
  27. ams/system.py +11 -18
  28. docs/source/api.rst +2 -0
  29. docs/source/release-notes.rst +12 -0
  30. {ltbams-1.0.6.dist-info → ltbams-1.0.7.dist-info}/METADATA +1 -1
  31. {ltbams-1.0.6.dist-info → ltbams-1.0.7.dist-info}/RECORD +41 -44
  32. tests/test_1st_system.py +31 -0
  33. tests/test_andes_mats.py +1 -1
  34. tests/test_case.py +27 -19
  35. tests/test_rtn_ed.py +4 -4
  36. tests/test_rtn_rted.py +4 -4
  37. tests/test_rtn_uc.py +4 -4
  38. tests/test_service.py +2 -2
  39. ams/cases/5bus/pjm5bus_uced.json +0 -1062
  40. ams/cases/5bus/pjm5bus_uced.xlsx +0 -0
  41. ams/cases/5bus/pjm5bus_uced_esd1.xlsx +0 -0
  42. ams/cases/5bus/pjm5bus_uced_ev.xlsx +0 -0
  43. {ltbams-1.0.6.dist-info → ltbams-1.0.7.dist-info}/WHEEL +0 -0
  44. {ltbams-1.0.6.dist-info → ltbams-1.0.7.dist-info}/entry_points.txt +0 -0
  45. {ltbams-1.0.6.dist-info → ltbams-1.0.7.dist-info}/top_level.txt +0 -0
ams/_version.py CHANGED
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2025-04-10T23:17:16-0400",
11
+ "date": "2025-04-14T02:15:15-0400",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "3dbdbfee9ce8361b7975c9333179b88c01560137",
15
- "version": "1.0.6"
14
+ "full-revisionid": "ba5d62c3b3d080ab5ffe03e04883a3492dc121eb",
15
+ "version": "1.0.7"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
ams/core/matprocessor.py CHANGED
@@ -492,11 +492,8 @@ class MatProcessor:
492
492
 
493
493
  References
494
494
  ----------
495
- [1] PowerWorld Documentation, Power Transfer Distribution Factors, [Online]
496
-
497
- Available:
498
-
499
- https://www.powerworld.com/WebHelp/Content/MainDocumentation_HTML/Power_Transfer_Distribution_Factors.htm
495
+ 1. PowerWorld Documentation, Power Transfer Distribution Factors,
496
+ https://www.powerworld.com/WebHelp/Content/MainDocumentation_HTML/Power_Transfer_Distribution_Factors.htm
500
497
  """
501
498
  system = self.system
502
499
 
@@ -616,11 +613,8 @@ class MatProcessor:
616
613
 
617
614
  References
618
615
  ----------
619
- [1] PowerWorld Documentation, Line Outage Distribution Factors, [Online]
620
-
621
- Available:
622
-
623
- https://www.powerworld.com/WebHelp/Content/MainDocumentation_HTML/Line_Outage_Distribution_Factors_LODFs.htm
616
+ 1. PowerWorld Documentation, Line Outage Distribution Factors,
617
+ https://www.powerworld.com/WebHelp/Content/MainDocumentation_HTML/Line_Outage_Distribution_Factors_LODFs.htm
624
618
  """
625
619
  system = self.system
626
620
 
@@ -716,7 +710,7 @@ class MatProcessor:
716
710
  def build_otdf(self, line=None):
717
711
  """
718
712
  Build the Outrage Transfer Distribution Factor (OTDF) matrix for line
719
- k outage: :math:`OTDF_k = PTDF + LODF[:, k] @ PTDF[k, ]`.
713
+ k outage: $OTDF_k = PTDF + LODF[:, k] @ PTDF[k, ]$.
720
714
 
721
715
  OTDF_k[m, n] means the increased line flow on line `m` when there is
722
716
  1 p.u. power injection at bus `n` when line `k` is outage.
@@ -737,11 +731,8 @@ class MatProcessor:
737
731
 
738
732
  References
739
733
  ----------
740
- [1] PowerWorld Documentation, Line Outage Distribution Factors, [Online]
741
-
742
- Available:
743
-
744
- https://www.powerworld.com/WebHelp/Content/MainDocumentation_HTML/Line_Outage_Distribution_Factors_LODFs.htm
734
+ 1. PowerWorld Documentation, Line Outage Distribution Factors,
735
+ https://www.powerworld.com/WebHelp/Content/MainDocumentation_HTML/Line_Outage_Distribution_Factors_LODFs.htm
745
736
  """
746
737
  if (self.PTDF._v is None) or (self.LODF._v is None):
747
738
  raise ValueError("Internal PTDF and LODF are not available. Please build them first.")
ams/core/service.py CHANGED
@@ -176,7 +176,8 @@ class ROperationService(RBaseService):
176
176
 
177
177
  class LoadScale(ROperationService):
178
178
  """
179
- Get zonal load by scale nodal load given the corresponding load scale factor.
179
+ Retrieve zonal load by scaling nodal load using the specified load scale factor.
180
+ The load scale factor is defined for each "Area".
180
181
 
181
182
  Parameters
182
183
  ----------
@@ -220,8 +221,8 @@ class LoadScale(ROperationService):
220
221
  u_idx = self.u.get_all_idxes()
221
222
  ue = self.u.owner.get(src='u', attr='v', idx=u_idx)
222
223
  u_bus = self.u.owner.get(src='bus', attr='v', idx=u_idx)
223
- u_zone = sys.Bus.get(src='zone', attr='v', idx=u_bus)
224
- u_yloc = np.array(sys.Zone.idx2uid(u_zone))
224
+ u_area = sys.Bus.get(src='area', attr='v', idx=u_bus)
225
+ u_yloc = np.array(sys.Area.idx2uid(u_area))
225
226
  p0s = np.multiply(self.sd.v[:, u_yloc].transpose(),
226
227
  (ue * self.u.v)[:, np.newaxis])
227
228
  if self.sparse:
ams/interface.py CHANGED
@@ -56,6 +56,8 @@ def sync_adsys(amsys, adsys):
56
56
  """
57
57
  Sync parameters value of PFlow models between AMS and ANDES systems.
58
58
 
59
+ This function should be used carefully when per unit conversion is involved.
60
+
59
61
  Parameters
60
62
  ----------
61
63
  amsys : AMS.system.System
@@ -84,10 +86,23 @@ def sync_adsys(amsys, adsys):
84
86
  return True
85
87
 
86
88
 
87
- def _to_andes_pflow(system, no_output=False, default_config=True, **kwargs):
89
+ def to_andes_pflow(system, no_output=False, default_config=True, **kwargs):
88
90
  """
89
91
  Helper function to convert the AMS system to an ANDES system with only
90
92
  power flow models.
93
+
94
+ The returned ANDES system is ***not*** setup.
95
+
96
+ Parameters
97
+ ----------
98
+ system: System
99
+ The AMS system to be converted to ANDES format.
100
+ no_output: bool, optional
101
+ To ANDES system.
102
+ default_config: bool, optional
103
+ To ANDES system.
104
+ kwargs:
105
+ Additional arguments to be passed to ``andes.system.System()``.
91
106
  """
92
107
 
93
108
  adsys = andes_System(no_outpu=no_output, default_config=default_config, **kwargs)
@@ -101,8 +116,6 @@ def _to_andes_pflow(system, no_output=False, default_config=True, **kwargs):
101
116
  for row in mdl.cache.df_in[mdl_cols].to_dict(orient='records'):
102
117
  adsys.add(mdl_name, row)
103
118
 
104
- sync_adsys(amsys=system, adsys=adsys)
105
-
106
119
  return adsys
107
120
 
108
121
 
@@ -169,7 +182,7 @@ def to_andes(system, addfile=None,
169
182
  t0, _ = elapsed()
170
183
 
171
184
  # --- convert power flow models ---
172
- adsys = _to_andes_pflow(system, no_output=no_output, default_config=default_config, **kwargs)
185
+ adsys = to_andes_pflow(system, no_output=no_output, default_config=default_config, **kwargs)
173
186
 
174
187
  _, s = elapsed(t0)
175
188
 
ams/models/__init__.py CHANGED
@@ -18,7 +18,7 @@ ams_file_classes = list([
18
18
  ('reserve', ['SFR', 'SR', 'NSR', 'VSGR']),
19
19
  ('cost', ['GCost', 'SFRCost', 'SRCost', 'NSRCost', 'VSGCost']),
20
20
  ('cost', ['DCost']),
21
- ('timeslot', ['TimeSlot', 'EDTSlot', 'UCTSlot']),
21
+ ('timeslot', ['EDTSlot', 'UCTSlot']),
22
22
  ])
23
23
 
24
24
  file_classes = ams_file_classes
ams/models/group.py CHANGED
@@ -188,7 +188,7 @@ class StaticGen(GroupBase):
188
188
  super().__init__()
189
189
  self.common_params.extend(('bus', 'Sn', 'Vn', 'p0', 'q0', 'ra', 'xs', 'subidx',
190
190
  'pmax', 'pmin', 'pg0', 'ctrl', 'R10', 'td1', 'td2',
191
- 'zone'))
191
+ 'area', 'zone'))
192
192
  self.common_vars.extend(('p', 'q'))
193
193
 
194
194
 
@@ -211,7 +211,7 @@ class StaticLoad(GroupBase):
211
211
 
212
212
  def __init__(self):
213
213
  super().__init__()
214
- self.common_params.extend(('bus', 'p0', 'q0', 'ctrl', 'zone'))
214
+ self.common_params.extend(('bus', 'p0', 'q0', 'ctrl', 'area', 'zone'))
215
215
 
216
216
 
217
217
  class StaticShunt(GroupBase):
ams/models/line.py CHANGED
@@ -18,8 +18,8 @@ class Line(LineData, Model):
18
18
 
19
19
  Notes
20
20
  -----
21
- There is a known issue that adding Algeb ``ud`` will cause Line.algebs run into
22
- AttributeError: 'NoneType' object has no attribute 'n'. Not figured out why yet.
21
+ 1. Adding Algeb ``ud`` causes Line.algebs to encounter an AttributeError: 'NoneType'
22
+ object has no attribute 'n'. The root cause is still under investigation.
23
23
  """
24
24
 
25
25
  def __init__(self, system=None, config=None) -> None:
@@ -2,7 +2,7 @@
2
2
  RenGen scheduling model.
3
3
  """
4
4
 
5
- from andes.core.param import NumParam, IdxParam, ExtParam
5
+ from andes.core.param import NumParam, IdxParam
6
6
  from andes.core.model import ModelData
7
7
  from ams.core.model import Model
8
8
 
@@ -80,10 +80,6 @@ class REGCV1(REGCData, Model):
80
80
  REGCData.__init__(self)
81
81
  Model.__init__(self, system, config)
82
82
  self.group = 'VSG'
83
- self.zone = ExtParam(model='Bus', src='zone',
84
- indexer=self.bus, export=False,
85
- info='Retrieved zone idx',
86
- vtype=str, default=None)
87
83
  self.M = NumParam(default=10, tex_name='M',
88
84
  info='Inertia emulation',
89
85
  unit='s',
ams/models/reserve.py CHANGED
@@ -10,8 +10,8 @@ from ams.core.model import Model
10
10
  class ReserveData(ModelData):
11
11
  def __init__(self):
12
12
  super().__init__()
13
- self.zone = IdxParam(model='Zone',
14
- default=None, info="Zone code",)
13
+ self.area = IdxParam(model='Area',
14
+ default=None, info="Area idx",)
15
15
 
16
16
 
17
17
  class SFR(ReserveData, Model):
ams/models/static/gen.py CHANGED
@@ -120,8 +120,8 @@ class PVModel(Model):
120
120
  err_tol=r"\epsilon_{tol}"
121
121
  )
122
122
 
123
- self.zone = ExtParam(model='Bus', src='zone', indexer=self.bus, export=False,
124
- info='Retrieved zone idx', vtype=str, default=None,
123
+ self.area = ExtParam(model='Bus', src='area', indexer=self.bus, export=False,
124
+ info='Retrieved area idx', vtype=str, default=None,
125
125
  )
126
126
 
127
127
  self.ud = Algeb(info='commitment decision',
ams/models/static/pq.py CHANGED
@@ -53,8 +53,8 @@ class PQ(PQData, Model):
53
53
  q2z=r"\gamma_{q2z}",
54
54
  )
55
55
 
56
- self.zone = ExtParam(model='Bus', src='zone', indexer=self.bus, export=False,
57
- info='Retrieved zone idx', vtype=str, default=None,
56
+ self.area = ExtParam(model='Bus', src='area', indexer=self.bus, export=False,
57
+ info='Retrieved area idx', vtype=str, default=None,
58
58
  )
59
59
  self.ctrl = NumParam(default=1,
60
60
  info="load controllability",
ams/models/timeslot.py CHANGED
@@ -18,7 +18,7 @@ def str_list_oconv(x):
18
18
 
19
19
  class TimeSlot(ModelData, Model):
20
20
  """
21
- Time slot data for rolling horizon.
21
+ Base model for time slot data used in multi-interval scheduling.
22
22
  """
23
23
 
24
24
  def __init__(self, system=None, config=None):
ams/routines/dcopf.py CHANGED
@@ -152,7 +152,7 @@ class DCOPF(DCPFBase):
152
152
 
153
153
  def dc2ac(self, kloss=1.0, **kwargs):
154
154
  """
155
- Convert the RTED results with ACOPF.
155
+ Convert the results using ACOPF.
156
156
 
157
157
  Parameters
158
158
  ----------
ams/routines/dopf.py CHANGED
@@ -16,11 +16,11 @@ class DOPF(DCOPF):
16
16
 
17
17
  UNDER DEVELOPMENT!
18
18
 
19
- Reference:
20
-
21
- [1] L. Bai, J. Wang, C. Wang, C. Chen, and F. Li, “Distribution Locational Marginal Pricing (DLMP)
22
- for Congestion Management and Voltage Support,” IEEE Trans. Power Syst., vol. 33, no. 4,
23
- pp. 40614073, Jul. 2018, doi: 10.1109/TPWRS.2017.2767632.
19
+ References
20
+ -----------------
21
+ 1. L. Bai, J. Wang, C. Wang, C. Chen, and F. Li, “Distribution Locational Marginal Pricing (DLMP)
22
+ for Congestion Management and Voltage Support,” IEEE Trans. Power Syst., vol. 33, no. 4,
23
+ pp. 4061-4073, Jul. 2018, doi: 10.1109/TPWRS.2017.2767632.
24
24
  """
25
25
 
26
26
  def __init__(self, system, config):
@@ -115,11 +115,11 @@ class DOPFVIS(DOPF):
115
115
 
116
116
  UNDER DEVELOPMENT!
117
117
 
118
- Reference:
119
-
120
- [1] L. Bai, J. Wang, C. Wang, C. Chen, and F. Li, “Distribution Locational Marginal Pricing (DLMP)
121
- for Congestion Management and Voltage Support,” IEEE Trans. Power Syst., vol. 33, no. 4,
122
- pp. 40614073, Jul. 2018, doi: 10.1109/TPWRS.2017.2767632.
118
+ References
119
+ -----------------
120
+ 1. L. Bai, J. Wang, C. Wang, C. Chen, and F. Li, “Distribution Locational Marginal Pricing (DLMP)
121
+ for Congestion Management and Voltage Support,” IEEE Trans. Power Syst., vol. 33, no. 4,
122
+ pp. 4061-4073, Jul. 2018, doi: 10.1109/TPWRS.2017.2767632.
123
123
  """
124
124
 
125
125
  def __init__(self, system, config):
ams/routines/ed.py CHANGED
@@ -109,8 +109,7 @@ class MPBase:
109
109
  class ED(RTED, MPBase, SRBase):
110
110
  """
111
111
  DC-based multi-period economic dispatch (ED).
112
- Dispath interval ``config.t`` (:math:``T_{cfg}``) is introduced, 1 [Hour] by default.
113
-
112
+ Dispatch interval ``config.t`` ($T_{cfg}$) is introduced, 1 [Hour] by default.
114
113
  ED extends DCOPF as follows:
115
114
 
116
115
  - Vars ``pg``, ``pru``, ``prd`` are extended to 2D
@@ -120,10 +119,10 @@ class ED(RTED, MPBase, SRBase):
120
119
  Notes
121
120
  -----
122
121
  1. Formulations has been adjusted with interval ``config.t``
123
-
124
122
  2. The tie-line flow is not implemented in this model.
125
-
126
123
  3. ``EDTSlot.ug`` is used instead of ``StaticGen.u`` for generator commitment.
124
+ 4. Following reserves are balanced for each "Area": RegUp reserve ``rbu``,
125
+ RegDn reserve ``rbd``, and Spinning reserve ``rsr``.
127
126
  """
128
127
 
129
128
  def __init__(self, system, config):
ams/routines/pflow.py CHANGED
@@ -12,7 +12,7 @@ from andes.utils.misc import elapsed
12
12
  from ams.core.param import RParam
13
13
  from ams.routines.routine import RoutineBase
14
14
  from ams.opt import Var, Expression, Objective
15
- from ams.interface import _to_andes_pflow, sync_adsys
15
+ from ams.interface import to_andes_pflow, sync_adsys
16
16
 
17
17
  logger = logging.getLogger(__name__)
18
18
 
@@ -28,10 +28,9 @@ class PFlow(RoutineBase):
28
28
 
29
29
  References
30
30
  ----------
31
- [1] M. L. Crow, Computational methods for electric power systems. 2015.
32
-
33
- [2] ANDES Documentation - Simulation and Plot. [Online]. Available:
34
- https://docs.andes.app/en/latest/_examples/ex1.html
31
+ 1. M. L. Crow, Computational methods for electric power systems. 2015.
32
+ 2. ANDES Documentation - Simulation and Plot.
33
+ https://docs.andes.app/en/latest/_examples/ex1.html
35
34
  """
36
35
 
37
36
  def __init__(self, system, config):
@@ -102,10 +101,10 @@ class PFlow(RoutineBase):
102
101
 
103
102
  kwargs go to andes.system.System().
104
103
  """
105
- self._adsys = _to_andes_pflow(self.system,
106
- no_output=self.system.files.no_output,
107
- config=self.config.as_dict(),
108
- **kwargs)
104
+ self._adsys = to_andes_pflow(self.system,
105
+ no_output=self.system.files.no_output,
106
+ config=self.config.as_dict(),
107
+ **kwargs)
109
108
  self._adsys.setup()
110
109
  self.om.init()
111
110
  self.initialized = True
@@ -132,7 +131,7 @@ class PFlow(RoutineBase):
132
131
  self.exec_time = float(s.split(" ")[0])
133
132
 
134
133
  self.unpack()
135
- return True
134
+ return self.converged
136
135
 
137
136
  def _post_solve(self):
138
137
  """
ams/routines/rted.py CHANGED
@@ -20,22 +20,22 @@ class RTEDBase:
20
20
  """
21
21
 
22
22
  def __init__(self):
23
- # --- zone ---
24
- self.zg = RParam(info='Gen zone',
23
+ # --- area ---
24
+ self.zg = RParam(info='Gen area',
25
25
  name='zg', tex_name='z_{one,g}',
26
- model='StaticGen', src='zone',
26
+ model='StaticGen', src='area',
27
27
  no_parse=True)
28
- self.zd = RParam(info='Load zone',
28
+ self.zd = RParam(info='Load area',
29
29
  name='zd', tex_name='z_{one,d}',
30
- model='StaticLoad', src='zone',
30
+ model='StaticLoad', src='area',
31
31
  no_parse=True)
32
- self.gs = ZonalSum(u=self.zg, zone='Zone',
32
+ self.gs = ZonalSum(u=self.zg, zone='Area',
33
33
  name='gs', tex_name=r'S_{g}',
34
- info='Sum Gen vars vector in shape of zone',
34
+ info='Sum Gen vars vector in shape of area',
35
35
  no_parse=True, sparse=True)
36
- self.ds = ZonalSum(u=self.zd, zone='Zone',
36
+ self.ds = ZonalSum(u=self.zd, zone='Area',
37
37
  name='ds', tex_name=r'S_{d}',
38
- info='Sum pd vector in shape of zone',
38
+ info='Sum pd vector in shape of area',
39
39
  no_parse=True,)
40
40
  self.pdz = NumOpDual(u=self.ds, u2=self.pd,
41
41
  fun=np.multiply,
@@ -110,10 +110,9 @@ class SFRBase:
110
110
  class RTED(DCOPF, RTEDBase, SFRBase):
111
111
  """
112
112
  DC-based real-time economic dispatch (RTED).
113
+
113
114
  RTED extends DCOPF with:
114
115
 
115
- - Mapping dicts to interface with ANDES
116
- - Function ``dc2ac`` to do the AC conversion
117
116
  - Vars for SFR reserve: ``pru`` and ``prd``
118
117
  - Param for linear SFR cost: ``cru`` and ``crd``
119
118
  - Param for SFR requirement: ``du`` and ``dd``
@@ -127,8 +126,9 @@ class RTED(DCOPF, RTEDBase, SFRBase):
127
126
  Notes
128
127
  -----
129
128
  1. Formulations has been adjusted with interval ``config.t``, 5/60 [Hour] by default.
130
-
131
- 2. The tie-line flow has not been implemented in formulations.
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.
132
132
  """
133
133
 
134
134
  def __init__(self, system, config):
@@ -176,14 +176,6 @@ class RTED(DCOPF, RTEDBase, SFRBase):
176
176
  self.obj.e_str = cost
177
177
 
178
178
  def dc2ac(self, kloss=1.0, **kwargs):
179
- """
180
- Convert the RTED results with ACOPF.
181
-
182
- Parameters
183
- ----------
184
- kloss : float, optional
185
- The loss factor for the conversion. Defaults to 1.2.
186
- """
187
179
  exec_time = self.exec_time
188
180
  if self.exec_time == 0 or self.exit_code != 0:
189
181
  logger.warning(f'{self.class_name} is not executed successfully, quit conversion.')
@@ -467,9 +459,9 @@ class VISBase:
467
459
  model='VSG', src='D',
468
460
  nonneg=True,)
469
461
 
470
- self.gvsg = ZonalSum(u=self.zvsg, zone='Zone',
462
+ self.gvsg = ZonalSum(u=self.zvsg, zone='Area',
471
463
  name='gvsg', tex_name=r'S_{g}',
472
- info='Sum VSG vars vector in shape of zone',
464
+ info='Sum VSG vars vector in shape of area',
473
465
  no_parse=True)
474
466
  self.Mub = Constraint(name='Mub', is_eq=False,
475
467
  info='M upper bound',
@@ -494,12 +486,11 @@ class RTEDVIS(RTED, VISBase):
494
486
  This class implements real-time economic dispatch with virtual inertia scheduling.
495
487
  Please ensure that the parameters `dvm` and `dvd` are set according to the system base.
496
488
 
497
- Reference:
498
-
499
- [1] B. She, F. Li, H. Cui, J. Wang, Q. Zhang and R. Bo, "Virtual
500
- Inertia Scheduling (VIS) for Real-time Economic Dispatch of
501
- IBRs-penetrated Power Systems," in IEEE Transactions on
502
- Sustainable Energy, doi: 10.1109/TSTE.2023.3319307.
489
+ References
490
+ -----------------
491
+ 1. B. She, F. Li, H. Cui, J. Wang, Q. Zhang and R. Bo, "Virtual Inertia Scheduling (VIS) for
492
+ Real-Time Economic Dispatch of IBR-Penetrated Power Systems," in IEEE Transactions on
493
+ Sustainable Energy, vol. 15, no. 2, pp. 938-951, April 2024, doi: 10.1109/TSTE.2023.3319307.
503
494
  """
504
495
 
505
496
  def __init__(self, system, config):
ams/routines/uc.py CHANGED
@@ -288,7 +288,7 @@ class UC(DCOPF, RTEDBase, MPBase, SRBase, NSRBase):
288
288
  gen['idx'] = self.system.PV.idx.v
289
289
  gen['pmax'] = self.system.PV.get(src='pmax', attr='v', idx=gen['idx'])
290
290
  gen['bus'] = self.system.PV.get(src='bus', attr='v', idx=gen['idx'])
291
- gen['zone'] = self.system.PV.get(src='zone', attr='v', idx=gen['idx'])
291
+ gen['area'] = self.system.PV.get(src='area', attr='v', idx=gen['idx'])
292
292
  gcost_idx = self.system.GCost.find_idx(keys='gen', values=gen['idx'])
293
293
  gen['c2'] = self.system.GCost.get(src='c2', attr='v', idx=gcost_idx)
294
294
  gen['c1'] = self.system.GCost.get(src='c1', attr='v', idx=gcost_idx)
ams/system.py CHANGED
@@ -410,25 +410,18 @@ class System(andes_System):
410
410
 
411
411
  # --- model parameters range check ---
412
412
  # TODO: there might be other parameters check?
413
- # Line rate
414
- adjust_rate = []
415
- default_rate = 999
416
- for rate in [self.Line.rate_a, self.Line.rate_b, self.Line.rate_c]:
417
- if np.any(rate.v == 0):
418
- adjust_rate.append(rate.name)
419
- rate.v[rate.v == 0] = default_rate
420
- if adjust_rate:
421
- adjusted_rate = ', '.join(adjust_rate)
422
- msg = f"Zero line rates detacted in {adjusted_rate}, "
423
- msg += f"adjusted to {default_rate}."
413
+ adjusted_params = []
414
+ param_to_check = ['rate_a', 'rate_b', 'rate_c', 'amax', 'amin']
415
+ for pname in param_to_check:
416
+ param = self.Line.params[pname]
417
+ if np.any(param.v == 0):
418
+ adjusted_params.append(pname)
419
+ param.v[param.v == 0] = param.default
420
+ if adjusted_params:
421
+ adjusted_params_str = ', '.join(adjusted_params)
422
+ msg = f"Zero Line parameters detected, adjusted to default values: {adjusted_params_str}."
424
423
  logger.info(msg)
425
- # Line max angle difference
426
- if np.any(self.Line.amax.v == 0):
427
- self.Line.amax.v[self.Line.amax.v == 0] = 2 * np.pi
428
- logger.info("Zero line amax detected, adjusted to 2*pi.")
429
- if np.any(self.Line.amin.v == 0):
430
- self.Line.amin.v[self.Line.amin.v == 0] = -2 * np.pi
431
- logger.info("Zero line amin detected, adjusted to -2*pi.")
424
+
432
425
  # === no device addition or removal after this point ===
433
426
  self.calc_pu_coeff() # calculate parameters in system per units
434
427
 
docs/source/api.rst CHANGED
@@ -30,7 +30,9 @@ Model
30
30
 
31
31
  ams.core.model
32
32
  ams.core.param
33
+ ams.core.var
33
34
  ams.core.service
35
+ ams.core.matprocessor
34
36
 
35
37
 
36
38
  Routines
@@ -9,6 +9,18 @@ The APIs before v3.0.0 are in beta and may change without prior notice.
9
9
  v1.0
10
10
  ==========
11
11
 
12
+ v1.0.7 (2024-04-14)
13
+ --------------------
14
+
15
+ - Address several wording issues in the documentation
16
+ - Switch to ``Area`` from ``Zone`` for zonal calculation
17
+ - Extend common parameters in groups ``StaticGen`` and ``StaticLoad`` with ``area``
18
+ - Set case ``pjm5bus_demo.xlsx`` as a all-inclusive case
19
+ - Include module ``MatProcessor`` in the API documentation
20
+ - Improve Line parameters correction in ``System.setup()``
21
+ - Make func ``interface._to_andes_pflow`` public
22
+ - Update case files
23
+
12
24
  v1.0.6 (2024-04-10)
13
25
  --------------------
14
26
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ltbams
3
- Version: 1.0.6
3
+ Version: 1.0.7
4
4
  Summary: Python software for scheduling modeling and co-simulation with dynamics.
5
5
  Home-page: https://github.com/CURENT/ams
6
6
  Author: Jinning Wang