ltbams 1.0.10__py3-none-any.whl → 1.0.11__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.
ams/_version.py CHANGED
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2025-05-23T00:18:06-0400",
11
+ "date": "2025-05-23T17:38:11-0400",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "f467fb0017c81d3946c1c566802adc4f411ad05e",
15
- "version": "1.0.10"
14
+ "full-revisionid": "6d7b555f5f48c751648594a535711b9fd21d2a85",
15
+ "version": "1.0.11"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
ams/core/documenter.py CHANGED
@@ -6,26 +6,12 @@ import re
6
6
 
7
7
  import logging
8
8
  from collections import OrderedDict
9
- from andes.core.documenter import Documenter as andes_Documenter
10
9
  from andes.utils.tab import make_doc_table, math_wrap
11
10
 
12
11
  logger = logging.getLogger(__name__)
13
12
 
14
13
 
15
- def disable_method(func):
16
- def wrapper(*args, **kwargs):
17
- msg = f"Method `{func.__name__}` is included in ANDES Documenter but not supported in AMS Documenter."
18
- logger.warning(msg)
19
- return None
20
- return wrapper
21
-
22
-
23
- def disable_methods(methods):
24
- for method in methods:
25
- setattr(Documenter, method, disable_method(getattr(Documenter, method)))
26
-
27
-
28
- class Documenter(andes_Documenter):
14
+ class Documenter:
29
15
  """
30
16
  Helper class for documenting models.
31
17
 
@@ -37,16 +23,6 @@ class Documenter(andes_Documenter):
37
23
 
38
24
  def __init__(self, parent):
39
25
  self.parent = parent
40
- self.system = parent.system
41
- self.class_name = parent.class_name
42
- self.config = parent.config
43
- self.params = parent.params
44
- self.algebs = parent.algebs
45
- self.services = parent.services
46
-
47
- func_to_disable = ['_init_doc', '_eq_doc',
48
- '_discrete_doc', '_block_doc']
49
- disable_methods(func_to_disable)
50
26
 
51
27
  def get(self, max_width=78, export='plain'):
52
28
  """
@@ -68,14 +44,15 @@ class Documenter(andes_Documenter):
68
44
  if export == 'rest':
69
45
  max_width = 0
70
46
  model_header = '-' * 80 + '\n'
71
- out += f'.. _{self.class_name}:\n\n'
47
+ out += f'.. _{self.parent.class_name}:\n\n'
72
48
  else:
73
49
  model_header = ''
74
50
 
75
51
  if export == 'rest':
76
- out += model_header + f'{self.class_name}\n' + model_header
52
+ out += model_header + f'{self.parent.class_name}\n' + model_header
77
53
  else:
78
- out += model_header + f'Model <{self.class_name}> in Group <{self.parent.group}>\n' + model_header
54
+ out += model_header + \
55
+ f'Model <{self.parent.class_name}> in Group <{self.parent.group}>\n' + model_header
79
56
 
80
57
  if self.parent.__doc__ is not None:
81
58
  out += inspect.cleandoc(self.parent.__doc__)
@@ -86,20 +63,35 @@ class Documenter(andes_Documenter):
86
63
  out += self._var_doc(max_width=max_width, export=export)
87
64
  out += self._service_doc(max_width=max_width, export=export)
88
65
  # TODO: fix and add the config doc later on
89
- # out += self.config.doc(max_width=max_width, export=export)
66
+ # out += self.parent.config.doc(max_width=max_width, export=export)
90
67
 
91
68
  return out
92
69
 
93
70
  def _var_doc(self, max_width=78, export='plain'):
71
+ """
72
+ Export formatted model variable documentation as a string.
73
+
74
+ Parameters
75
+ ----------
76
+ max_width : int, optional = 80
77
+ Maximum table width. If export format is ``rest`` it will be unlimited.
78
+ export : str, optional = 'plain'
79
+ Export format, 'plain' for plain text, 'rest' for restructuredText.
80
+
81
+ Returns
82
+ -------
83
+ str
84
+ Tabulated output in a string
85
+ """
94
86
  # variable documentation
95
- if len(self.algebs) == 0:
87
+ if len(self.parent.algebs) == 0:
96
88
  return ''
97
89
 
98
90
  names, symbols, units = list(), list(), list()
99
91
  info = list()
100
92
  units_rest, ty = list(), list()
101
93
 
102
- for p in self.algebs.values():
94
+ for p in self.parent.algebs.values():
103
95
  names.append(p.name)
104
96
  ty.append(p.class_name)
105
97
  info.append(p.info if p.info else '')
@@ -110,7 +102,7 @@ class Documenter(andes_Documenter):
110
102
 
111
103
  # replace with latex math expressions if export is ``rest``
112
104
  if export == 'rest':
113
- symbols = [item.tex_name for item in self.algebs.values()]
105
+ symbols = [item.tex_name for item in self.parent.algebs.values()]
114
106
  symbols = math_wrap(symbols, export=export)
115
107
  title = 'Variables\n---------'
116
108
 
@@ -132,14 +124,29 @@ class Documenter(andes_Documenter):
132
124
  rest_dict=rest_dict)
133
125
 
134
126
  def _service_doc(self, max_width=78, export='plain'):
135
- if len(self.services) == 0:
127
+ """
128
+ Export formatted model service documentation as a string.
129
+
130
+ Parameters
131
+ ----------
132
+ max_width : int, optional = 80
133
+ Maximum table width. If export format is ``rest`` it will be unlimited.
134
+ export : str, optional = 'plain'
135
+ Export format, 'plain' for plain text, 'rest' for restructuredText.
136
+
137
+ Returns
138
+ -------
139
+ str
140
+ Tabulated output in a string
141
+ """
142
+ if len(self.parent.services) == 0:
136
143
  return ''
137
144
 
138
145
  names, symbols = list(), list()
139
146
  info = list()
140
147
  class_names = list()
141
148
 
142
- for p in self.services.values():
149
+ for p in self.parent.services.values():
143
150
  names.append(p.name)
144
151
  class_names.append(p.class_name)
145
152
  info.append(p.info if p.info else '')
@@ -165,6 +172,74 @@ class Documenter(andes_Documenter):
165
172
  plain_dict=plain_dict,
166
173
  rest_dict=rest_dict)
167
174
 
175
+ def _param_doc(self, max_width=78, export='plain'):
176
+ """
177
+ Export formatted model parameter documentation as a string.
178
+
179
+ Parameters
180
+ ----------
181
+ max_width : int, optional = 80
182
+ Maximum table width. If export format is ``rest`` it will be unlimited.
183
+
184
+ export : str, optional = 'plain'
185
+ Export format, 'plain' for plain text, 'rest' for restructuredText.
186
+
187
+ Returns
188
+ -------
189
+ str
190
+ Tabulated output in a string
191
+ """
192
+ if len(self.parent.params) == 0:
193
+ return ''
194
+
195
+ # prepare temporary lists
196
+ names, units, class_names = list(), list(), list()
197
+ info, defaults, properties = list(), list(), list()
198
+ units_rest = list()
199
+
200
+ for p in self.parent.params.values():
201
+ names.append(p.name)
202
+ class_names.append(p.class_name)
203
+ info.append(p.info if p.info else '')
204
+ defaults.append(p.default if p.default is not None else '')
205
+ units.append(f'{p.unit}' if p.unit else '')
206
+ units_rest.append(f'*{p.unit}*' if p.unit else '')
207
+
208
+ plist = []
209
+ for key, val in p.property.items():
210
+ if val is True:
211
+ plist.append(key)
212
+ properties.append(','.join(plist))
213
+
214
+ # symbols based on output format
215
+ if export == 'rest':
216
+ symbols = [item.tex_name for item in self.parent.params.values()]
217
+ symbols = math_wrap(symbols, export=export)
218
+ title = 'Parameters\n----------'
219
+ else:
220
+ symbols = [item.name for item in self.parent.params.values()]
221
+ title = 'Parameters'
222
+
223
+ plain_dict = OrderedDict([('Name', names),
224
+ ('Description', info),
225
+ ('Default', defaults),
226
+ ('Unit', units),
227
+ ('Properties', properties)])
228
+
229
+ rest_dict = OrderedDict([('Name', names),
230
+ ('Symbol', symbols),
231
+ ('Description', info),
232
+ ('Default', defaults),
233
+ ('Unit', units_rest),
234
+ ('Properties', properties)])
235
+
236
+ # convert to rows and export as table
237
+ return make_doc_table(title=title,
238
+ max_width=max_width,
239
+ export=export,
240
+ plain_dict=plain_dict,
241
+ rest_dict=rest_dict)
242
+
168
243
 
169
244
  class RDocumenter:
170
245
  """
@@ -172,20 +247,12 @@ class RDocumenter:
172
247
 
173
248
  Parameters
174
249
  ----------
175
- parent : Model
176
- The `Model` instance to document
250
+ parent : ams.core.routine.RoutineBase
251
+ The `RoutineBase` instance to document
177
252
  """
178
253
 
179
254
  def __init__(self, parent):
180
255
  self.parent = parent
181
- self.system = parent.system
182
- self.class_name = parent.class_name
183
- self.config = parent.config
184
- self.services = parent.services
185
- self.rparams = parent.rparams
186
- self.vars = parent.vars
187
- self.constrs = parent.constrs
188
- self.obj = parent.obj
189
256
 
190
257
  def get(self, max_width=78, export='plain'):
191
258
  """
@@ -207,14 +274,15 @@ class RDocumenter:
207
274
  if export == 'rest':
208
275
  max_width = 0
209
276
  model_header = '-' * 80 + '\n'
210
- out += f'.. _{self.class_name}:\n\n'
277
+ out += f'.. _{self.parent.class_name}:\n\n'
211
278
  else:
212
279
  model_header = ''
213
280
 
214
281
  if export == 'rest':
215
- out += model_header + f'{self.class_name}\n' + model_header
282
+ out += model_header + f'{self.parent.class_name}\n' + model_header
216
283
  else:
217
- out += model_header + f'Routine <{self.class_name}> in Type <{self.parent.type}>\n' + model_header
284
+ out += model_header + \
285
+ f'Routine <{self.parent.class_name}> in Type <{self.parent.type}>\n' + model_header
218
286
 
219
287
  if self.parent.__doc__ is not None:
220
288
  out += inspect.cleandoc(self.parent.__doc__)
@@ -229,20 +297,20 @@ class RDocumenter:
229
297
  out += self._exprc_doc(max_width=max_width, export=export)
230
298
  out += self._service_doc(max_width=max_width, export=export)
231
299
  out += self._param_doc(max_width=max_width, export=export)
232
- out += self.config.doc(max_width=max_width, export=export)
300
+ out += self.parent.config.doc(max_width=max_width, export=export)
233
301
 
234
302
  return out
235
303
 
236
304
  def _service_doc(self, max_width=78, export='plain'):
237
305
  # routine service documentation
238
- if len(self.services) == 0:
306
+ if len(self.parent.services) == 0:
239
307
  return ''
240
308
 
241
309
  names, symbols = list(), list()
242
310
  info = list()
243
311
  class_names = list()
244
312
 
245
- for p in self.services.values():
313
+ for p in self.parent.services.values():
246
314
  names.append(p.name)
247
315
  info.append(p.info if p.info else '')
248
316
  class_names.append(p.class_name)
@@ -251,7 +319,7 @@ class RDocumenter:
251
319
 
252
320
  # replace with latex math expressions if export is ``rest``
253
321
  if export == 'rest':
254
- symbols = [item.tex_name for item in self.services.values()]
322
+ symbols = [item.tex_name for item in self.parent.services.values()]
255
323
  symbols = math_wrap(symbols, export=export)
256
324
  title = 'Services\n---------'
257
325
 
@@ -272,13 +340,13 @@ class RDocumenter:
272
340
 
273
341
  def _constr_doc(self, max_width=78, export='plain'):
274
342
  # constraint documentation
275
- if len(self.constrs) == 0:
343
+ if len(self.parent.constrs) == 0:
276
344
  return ''
277
345
 
278
346
  # prepare temporary lists
279
347
  names, class_names, info = list(), list(), list()
280
348
 
281
- for p in self.constrs.values():
349
+ for p in self.parent.constrs.values():
282
350
  names.append(p.name)
283
351
  class_names.append(p.class_name)
284
352
  info.append(p.info if p.info else '')
@@ -286,7 +354,7 @@ class RDocumenter:
286
354
  # expressions based on output format
287
355
  expressions = []
288
356
  if export == 'rest':
289
- for p in self.constrs.values():
357
+ for p in self.parent.constrs.values():
290
358
  expr = _tex_pre(self, p, self.parent.syms.tex_map)
291
359
  if p.is_eq:
292
360
  expr = f'{expr} = 0'
@@ -460,7 +528,7 @@ class RDocumenter:
460
528
  # NOTE: this is for the optimization variables
461
529
  # not the _var_doc for ANDES parameters
462
530
  # variable documentation
463
- if len(self.vars) == 0:
531
+ if len(self.parent.vars) == 0:
464
532
  return ''
465
533
 
466
534
  # prepare temporary lists
@@ -469,7 +537,7 @@ class RDocumenter:
469
537
  sources = list()
470
538
  units_rest = list()
471
539
 
472
- for p in self.vars.values():
540
+ for p in self.parent.vars.values():
473
541
  names.append(p.name)
474
542
  class_names.append(p.class_name)
475
543
  info.append(p.info if p.info else '')
@@ -493,11 +561,11 @@ class RDocumenter:
493
561
 
494
562
  # symbols based on output format
495
563
  if export == 'rest':
496
- symbols = [item.tex_name for item in self.vars.values()]
564
+ symbols = [item.tex_name for item in self.parent.vars.values()]
497
565
  symbols = math_wrap(symbols, export=export)
498
566
  title = 'Vars\n----------------------------------'
499
567
  else:
500
- symbols = [item.name for item in self.vars.values()]
568
+ symbols = [item.name for item in self.parent.vars.values()]
501
569
  title = 'Vars'
502
570
 
503
571
  plain_dict = OrderedDict([('Name', names),
@@ -536,7 +604,7 @@ class RDocumenter:
536
604
  str
537
605
  Tabulated output in a string
538
606
  """
539
- if len(self.rparams) == 0:
607
+ if len(self.parent.rparams) == 0:
540
608
  return ''
541
609
 
542
610
  # prepare temporary lists
@@ -545,7 +613,7 @@ class RDocumenter:
545
613
  sources = list()
546
614
  units_rest = list()
547
615
 
548
- for p in self.rparams.values():
616
+ for p in self.parent.rparams.values():
549
617
  names.append(p.name)
550
618
  class_names.append(p.class_name)
551
619
  info.append(p.info if p.info else '')
@@ -562,11 +630,11 @@ class RDocumenter:
562
630
 
563
631
  # symbols based on output format
564
632
  if export == 'rest':
565
- symbols = [item.tex_name for item in self.rparams.values()]
633
+ symbols = [item.tex_name for item in self.parent.rparams.values()]
566
634
  symbols = math_wrap(symbols, export=export)
567
635
  title = 'Parameters\n----------------------------------'
568
636
  else:
569
- symbols = [item.name for item in self.rparams.values()]
637
+ symbols = [item.name for item in self.parent.rparams.values()]
570
638
  title = 'Parameters'
571
639
 
572
640
  plain_dict = OrderedDict([('Name', names),
ams/interface.py CHANGED
@@ -8,7 +8,7 @@ import logging
8
8
  from collections import OrderedDict, Counter
9
9
 
10
10
  from andes.utils.misc import elapsed
11
- from andes.system import System as andes_System
11
+ from andes.system import System as adSystem
12
12
 
13
13
  from ams.utils import create_entry
14
14
  from ams.io import input_formats
@@ -107,7 +107,7 @@ def to_andes_pflow(system, no_output=False, default_config=True, **kwargs):
107
107
  Additional arguments to be passed to ``andes.system.System()``.
108
108
  """
109
109
 
110
- adsys = andes_System(no_outpu=no_output, default_config=default_config, **kwargs)
110
+ adsys = adSystem(no_outpu=no_output, default_config=default_config, **kwargs)
111
111
  # FIXME: is there a systematic way to do this? Other config might be needed
112
112
  adsys.config.freq = system.config.freq
113
113
  adsys.config.mva = system.config.mva
ams/routines/grbopt.py CHANGED
@@ -10,6 +10,8 @@ import scipy.io
10
10
  from andes.shared import np, pd
11
11
  from andes.utils.misc import elapsed
12
12
 
13
+ from ams.core import Config
14
+
13
15
  from ams.io.pypower import system2ppc
14
16
 
15
17
  from ams.opt import Var, Objective
@@ -39,9 +41,13 @@ class OPF(DCPF1):
39
41
  self.info = 'Optimal Power Flow'
40
42
  self.type = 'ACED'
41
43
 
44
+ # Overwrite the config to be empty, as it is not used in this routine
45
+ self.config = Config(self.class_name)
46
+
42
47
  self.obj = Objective(name='obj',
43
48
  info='total cost, placeholder',
44
49
  e_str='sum(c2 * pg**2 + c1 * pg + c0)',
50
+ unit='$',
45
51
  sense='min',)
46
52
 
47
53
  self.pi = Var(info='Lagrange multiplier on real power mismatch',
@@ -97,23 +103,22 @@ class OPF(DCPF1):
97
103
  """
98
104
  Run the OPF routine using gurobi-optimods.
99
105
 
100
- This method invokes `self.solve(**kwargs)`, which internally utilizes
101
- `gurobi-optimods` to solve the OPF problem.
106
+ This method invokes `gurobi-optimods.opf.solve_opf` to solve the OPF problem.
102
107
 
103
- Keyword arguments
104
- -------------------
105
- - ``opftype`` : str
108
+ Parameters
109
+ ----------
110
+ - opftype : str
106
111
  Type of OPF to solve (default: 'AC').
107
- - ``branch_switching`` : bool
112
+ - branch_switching : bool
108
113
  Enable branch switching (default: False).
109
- - ``min_active_branches`` : float
114
+ - min_active_branches : float
110
115
  Defines the minimum number of branches that must be turned on when
111
116
  branch switching is active, i.e. the minimum number of turned on
112
117
  branches is equal to ``numbranches * min_active_branches``. Has no
113
118
  effect if ``branch_switching`` is set to False.
114
- - ``use_mip_start`` : bool
119
+ - use_mip_start : bool
115
120
  Use MIP start (default: False).
116
- - ``time_limit`` : float
121
+ - time_limit : float
117
122
  Time limit for the solver (default: 0.0, no limit).
118
123
  """
119
124
  if not self.initialized:
ams/routines/pypower.py CHANGED
@@ -147,8 +147,8 @@ class DCPF1(RoutineBase):
147
147
  model='Line',)
148
148
  # --- objective ---
149
149
  self.obj = Objective(name='obj',
150
- info='total cost',
151
- e_str='0',
150
+ info='total cost, placeholder',
151
+ e_str='0', unit='$',
152
152
  sense='min',)
153
153
 
154
154
  # --- total cost ---
@@ -346,16 +346,13 @@ class PFlow1(DCPF1):
346
346
  It leverages PYPOWER's internal power flow solver and maps results back to the
347
347
  AMS system.
348
348
 
349
- Known Issues
350
- ------------
351
- - Fast-Decoupled (XB version) and Fast-Decoupled (BX version) algorithms are
352
- not fully supported yet.
353
-
354
349
  Notes
355
350
  -----
356
351
  - This class does not implement the AMS-style power flow formulation.
357
352
  - For detailed mathematical formulations and algorithmic details, refer to the
358
353
  MATPOWER User's Manual, section on Power Flow.
354
+ - Fast-Decoupled (XB version) and Fast-Decoupled (BX version) algorithms are
355
+ not fully supported yet.
359
356
  """
360
357
 
361
358
  def __init__(self, system, config):
@@ -380,7 +377,7 @@ class PFlow1(DCPF1):
380
377
  pf_max_it="maximum number of iterations for Newton's method",
381
378
  pf_max_it_fd="maximum number of iterations for fast decoupled method",
382
379
  pf_max_it_gs="maximum number of iterations for Gauss-Seidel method",
383
- enforce_q_lims="enforce gen reactive power limits, at expense of |V|",
380
+ enforce_q_lims="enforce gen reactive power limits, at expense of V magnitude",
384
381
  )
385
382
  self.config.add_extra("_alt",
386
383
  pf_alg=(1, 2, 3, 4),
@@ -424,15 +421,12 @@ class DCOPF1(DCPF1):
424
421
  function) is always included in the objective, regardless of the generator's
425
422
  commitment status. See `pypower/opf_costfcn.py` for implementation details.
426
423
 
427
- Known Issues
428
- ------------
429
- - Algorithms 400, 500, 600, and 700 are not fully supported yet.
430
-
431
424
  Notes
432
425
  -----
433
426
  - This class does not implement the AMS-style DC optimal power flow formulation.
434
427
  - For detailed mathematical formulations and algorithmic details, refer to the
435
428
  MATPOWER User's Manual, section on Optimal Power Flow.
429
+ - Algorithms 400, 500, 600, and 700 are not fully supported yet.
436
430
  """
437
431
 
438
432
  def __init__(self, system, config):
@@ -522,10 +516,7 @@ class DCOPF1(DCPF1):
522
516
  scpdipm_red_it=r'o_{scpdipm\_red\_it}',
523
517
  )
524
518
 
525
- self.obj = Objective(name='obj',
526
- info='total cost, placeholder',
527
- e_str='sum(c2 * pg**2 + c1 * pg + c0)',
528
- sense='min',)
519
+ self.obj.e_str = 'sum(c2 * pg**2 + c1 * pg + c0)'
529
520
 
530
521
  self.pi = Var(info='Lagrange multiplier on real power mismatch',
531
522
  name='pi', unit='$/p.u.',
ams/system.py CHANGED
@@ -9,7 +9,7 @@ from typing import Dict, Optional
9
9
 
10
10
  import numpy as np
11
11
 
12
- from andes.system import System as andes_System
12
+ from andes.system import System as adSystem
13
13
  from andes.system import (_config_numpy, load_config_rc)
14
14
  from andes.variables import FileMan
15
15
 
@@ -49,7 +49,7 @@ def disable_methods(methods):
49
49
  setattr(System, method, disable_method(getattr(System, method)))
50
50
 
51
51
 
52
- class System(andes_System):
52
+ class System(adSystem):
53
53
  """
54
54
  A subclass of ``andes.system.System``, this class encapsulates data, models,
55
55
  and routines for scheduling modeling and analysis in power systems.
ams/utils/paths.py CHANGED
@@ -184,7 +184,7 @@ def get_pycode_path(pycode_path=None, mkdir=False):
184
184
  """
185
185
 
186
186
  if pycode_path is None:
187
- pycode_path = os.path.join(get_dot_andes_path(), 'pycode')
187
+ pycode_path = os.path.join(get_dot_ams_path(), 'pycode')
188
188
 
189
189
  if mkdir is True:
190
190
  os.makedirs(pycode_path, exist_ok=True)
@@ -203,7 +203,7 @@ def get_pkl_path():
203
203
 
204
204
  """
205
205
  pkl_name = 'calls.pkl'
206
- ams_path = get_dot_andes_path()
206
+ ams_path = get_dot_ams_path()
207
207
 
208
208
  if not os.path.exists(ams_path):
209
209
  os.makedirs(ams_path)
@@ -213,7 +213,7 @@ def get_pkl_path():
213
213
  return pkl_path
214
214
 
215
215
 
216
- def get_dot_andes_path():
216
+ def get_dot_ams_path():
217
217
  """
218
218
  Return the path to ``$HOME/.ams``
219
219
  """
@@ -28,4 +28,5 @@ folder of the repository
28
28
  ../_examples/demo/demo_ESD1.ipynb
29
29
  ../_examples/demo/demo_AGC.ipynb
30
30
  ../_examples/demo/demo_debug.ipynb
31
- ../_examples/demo/demo_mat.ipynb
31
+ ../_examples/demo/demo_mat.ipynb
32
+ ../_examples/demo/demo_wrapper_routines.ipynb
@@ -7,7 +7,7 @@ import ams
7
7
 
8
8
  if not (os.path.isfile('routineref.rst') and os.path.isfile('configref.rst')):
9
9
 
10
- ss = ams.load(ams.get_case('ieee14/ieee14_uced.xlsx'))
10
+ ss = ams.load(ams.get_case('5bus/pjm5bus_demo.json'))
11
11
 
12
12
  # write the top-level index file
13
13
 
@@ -9,8 +9,14 @@ 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.10 (2024-xx-xx)
13
- --------------------
12
+ v1.0.11 (2025-05-23)
13
+ ----------------------
14
+
15
+ - Refactor Documenter
16
+ - Fix bug in documentation building
17
+
18
+ v1.0.10 (2025-05-23)
19
+ ----------------------
14
20
 
15
21
  - Add bus type correction in ``system.System.setup()``
16
22
  - Revise ``ams.io.psse.read`` to complete model Zone when necessary
@@ -30,7 +36,7 @@ v1.0.10 (2024-xx-xx)
30
36
  - Remove legacy revised PYPOWER module
31
37
  - Remove function ``ams.shared.ppc2df``
32
38
 
33
- v1.0.9 (2024-04-23)
39
+ v1.0.9 (2025-04-23)
34
40
  --------------------
35
41
 
36
42
  Improve MATPOWER file converter:
@@ -38,7 +44,7 @@ Improve MATPOWER file converter:
38
44
  - Add a M file case writer
39
45
  - Include Area and Zone in both MATPOWER read and write
40
46
 
41
- v1.0.8 (2024-04-20)
47
+ v1.0.8 (2025-04-20)
42
48
  --------------------
43
49
 
44
50
  - Run workflow "Publish" only on push tag event
@@ -48,7 +54,7 @@ v1.0.8 (2024-04-20)
48
54
  - Include ``gentype`` and ``genfuel`` when parsing MATPOWER cases
49
55
  - Fix logging level in ``ACOPF.run``
50
56
 
51
- v1.0.7 (2024-04-14)
57
+ v1.0.7 (2025-04-14)
52
58
  --------------------
53
59
 
54
60
  - Address several wording issues in the documentation
@@ -62,44 +68,44 @@ v1.0.7 (2024-04-14)
62
68
  parameters conversion
63
69
  - Update case files
64
70
 
65
- v1.0.6 (2024-04-10)
71
+ v1.0.6 (2025-04-10)
66
72
  --------------------
67
73
 
68
74
  - Enhance handling of Type 1 gencost: Automatically fallback to Type 2 gencost
69
75
  - Add parameter correction for zero line angle difference
70
76
 
71
- v1.0.5 (2024-04-09)
77
+ v1.0.5 (2025-04-09)
72
78
  --------------------
73
79
 
74
80
  - Include sensitivity matrices calculation demo in documentation
75
81
  - Add ``DCOPF2``, a PTDF-based DCOPF routine
76
82
  - Fix bug when update routine parameters before it is initialized
77
83
 
78
- v1.0.4 (2024-04-05)
84
+ v1.0.4 (2025-04-05)
79
85
  --------------------
80
86
 
81
87
  - Fix format in release notes
82
88
  - Add badges of GitHub relesase and commits in README
83
89
  - Add a demo to show sensitivity matrices calculation
84
90
 
85
- v1.0.3 (2024-03-17)
91
+ v1.0.3 (2025-03-17)
86
92
  --------------------
87
93
 
88
94
  - Bug fix in function ``ams.interface.parse_addfile``, released in v1.0.3a1
89
95
 
90
- v1.0.2 (2024-02-01)
96
+ v1.0.2 (2025-02-01)
91
97
  --------------------
92
98
 
93
99
  - Enhance the GitHub Actions workflow file
94
100
  - Deprecate andes logger configuration in ``config_logger``
95
101
  - Deprecate solver specification in ``demo_ESD1``
96
102
 
97
- v1.0.1 (2024-01-26)
103
+ v1.0.1 (2025-01-26)
98
104
  --------------------
99
105
 
100
106
  Hotfix: removed dependencies on `SCIP` and `pyscipopt` to resolve installation issues
101
107
 
102
- v1.0.0 (2024-01-24)
108
+ v1.0.0 (2025-01-24)
103
109
  --------------------
104
110
 
105
111
  - **Breaking Change**: rename model ``Region`` to ``Zone`` for clarity. Prior case
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ltbams
3
- Version: 1.0.10
3
+ Version: 1.0.11
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
@@ -57,21 +57,18 @@ Python Software for Power System Scheduling Modeling and Co-Simulation with Dyna
57
57
 
58
58
  <img src="docs/source/images/sponsors/CURENT_Logo_NameOnTrans.png" alt="CURENT ERC Logo" width="300" height="auto">
59
59
 
60
- | | Stable | Develop |
61
- |---|---|---|
62
- | Documentation | [![Documentation Status](https://readthedocs.org/projects/ams/badge/?version=stable)](https://ams.readthedocs.io/en/stable/?badge=stable) | [![Develop Documentation](https://readthedocs.org/projects/ams/badge/?version=develop)](https://ams.readthedocs.io/en/develop/?badge=develop) |
63
-
64
60
  | Badges | | |
65
61
  |---|---|---|
66
62
  | Repo | ![Project Status: Active](https://www.repostatus.org/badges/latest/active.svg) | ![Repo Size](https://img.shields.io/github/repo-size/CURENT/ams) |
67
- | Version | ![PyPI Version](https://img.shields.io/pypi/v/ltbams.svg) | ![Conda Version](https://anaconda.org/conda-forge/ltbams/badges/version.svg) |
63
+ | Version | [![PyPI Version](https://img.shields.io/pypi/v/ltbams.svg)](https://pypi.org/project/ltbams/) | [![Anaconda-Server Badge](https://anaconda.org/conda-forge/ltbams/badges/version.svg)](https://anaconda.org/conda-forge/ltbams) |
68
64
  | Tag | [![GitHub Tag](https://img.shields.io/github/v/tag/CURENT/ams)](https://github.com/CURENT/ams/tags) | ![GitHub commits since latest release (branch)](https://img.shields.io/github/commits-since/curent/ams/latest/develop) |
69
- | Download | ![PyPI - Downloads](https://img.shields.io/pypi/dm/ltbams) | ![Anaconda-Server Badge](https://anaconda.org/conda-forge/ltbams/badges/downloads.svg) |
65
+ | Documentation | [![Read the Docs](https://img.shields.io/readthedocs/ams?label=stable)](https://ltb.readthedocs.io/projects/ams/en/stable/?badge=stable) | [![Read the Docs](https://img.shields.io/readthedocs/ams?label=develop)](https://ltb.readthedocs.io/projects/ams/en/develop/?badge=develop) |
66
+ | Download | [![PyPI - Downloads](https://img.shields.io/pypi/dm/ltbams)](https://pypi.org/project/ltbams/) | [![Anaconda-Server Badge](https://anaconda.org/conda-forge/ltbams/badges/downloads.svg)](https://anaconda.org/conda-forge/ltbams) |
70
67
  | Code Quality | ![Codacy Badge](https://app.codacy.com/project/badge/Grade/69456da1b8634f2f984bd769e35f0050) | ![Codacy Badge](https://app.codacy.com/project/badge/Coverage/69456da1b8634f2f984bd769e35f0050) |
71
68
  | Code Cov | ![codecov](https://codecov.io/gh/CURENT/ams/graph/badge.svg?token=RZI5GLLBQH) | |
72
69
  | Last Commit | ![GitHub last commit (master)](https://img.shields.io/github/last-commit/CURENT/ams/master?label=last%20commit%20to%20master) | ![GitHub last commit (develop)](https://img.shields.io/github/last-commit/CURENT/ams/develop?label=last%20commit%20to%20develop) |
73
- | CI | ![Compatibility Tests](https://github.com/CURENT/ams/actions/workflows/compatibility.yml/badge.svg) | ![Azure Pipline](https://dev.azure.com/curentltb/ams/_apis/build/status%2FCURENT.ams?branchName=master) |
74
- | CD | ![Publish to TestPyPI and PyPI](https://github.com/CURENT/ams/actions/workflows/publish-pypi.yml/badge.svg?branch=master) | |
70
+ | CI | [![Compatibility](https://github.com/CURENT/ams/actions/workflows/compatibility.yml/badge.svg)](https://github.com/CURENT/ams/actions/workflows/compatibility.yml) | [![Build Status](https://dev.azure.com/curentltb/ams/_apis/build/status%2FCURENT.ams?branchName=scuc)](https://dev.azure.com/curentltb/ams/_build/latest?definitionId=2&branchName=scuc) |
71
+ | CD | [![Publish](https://github.com/CURENT/ams/actions/workflows/publish-pypi.yml/badge.svg)](https://github.com/CURENT/ams/actions/workflows/publish-pypi.yml) | |
75
72
  | Structure | [![Structure](https://img.shields.io/badge/code_base-visualize-blue)](https://mango-dune-07a8b7110.1.azurestaticapps.net/?repo=CURENT%2Fams) | [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/CURENT/ams) |
76
73
  | Dependency | [![libraries](https://img.shields.io/librariesio/release/pypi/ltbams)](https://libraries.io/pypi/ltbams) | |
77
74
  | Try on Binder | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/curent/ams/master) | |
@@ -237,7 +234,7 @@ See [GitHub contributors][GitHub contributors] for the contributor list.
237
234
  AMS is licensed under the [GPL v3 License](./LICENSE).
238
235
 
239
236
  # Related Projects
240
- - [Popular Open Source Libraries for Power System Analysis](https://github.com/jinningwang/best-of-ps)
237
+ - [Popular Open Source Libraries for Power System Analysis](https://github.com/ps-wiki/best-of-ps)
241
238
  - [G-PST Tools Portal](https://g-pst.github.io/tools/): An open tools portal with a classification approach
242
239
  - [Open Source Software (OSS) for Electricity Market Research, Teaching, and Training](https://www2.econ.iastate.edu/tesfatsi/ElectricOSS.htm)
243
240
 
@@ -1,12 +1,12 @@
1
1
  ams/__init__.py,sha256=q-9-f0YCg6aaTW19VCkY6VosfvRA2ObI9mF1f_3016Y,313
2
2
  ams/__main__.py,sha256=EB4GfGiKgvnQ_psNr0QwPoziYvjmGvQ2yVsBwQtfrLw,170
3
- ams/_version.py,sha256=kccksMimNEDK-8pkw0RnSVrUE7NGH1_HlY85CE4sJgQ,498
3
+ ams/_version.py,sha256=9w0v2vIzAou5TWcsacfNdhiCAr9S83BM7FAKRy_t8h0,498
4
4
  ams/cli.py,sha256=EyNFXn565gFCppTxpyTZviBdPgUuKtgAPZ4WE6xewRk,6164
5
- ams/interface.py,sha256=-I5dRdHQPxyHBDCp02eYuqyW1aleHwn_nGgTxFYAG1I,45248
5
+ ams/interface.py,sha256=-UN7-TiSt7mOS0W7526LuOk4KCIGDZSguRaVmh_KMRM,45240
6
6
  ams/main.py,sha256=lIqC16TO0pye75Wv8l_6EemNtm15iyMdvu8YQFkdd_4,23599
7
7
  ams/report.py,sha256=ewcffopOzT5o45eJNmcV8pxeQqPIjKbarGN33-yHGA8,10961
8
8
  ams/shared.py,sha256=4sY2U0sghs_S2V6C7Z0OyQ6WZRfpCXk2_Cf_Mg24Vr4,3900
9
- ams/system.py,sha256=kASxxtA6rQ2mCBdwGXd_M3FRTH8xSXE99h8UCPrMnfU,29773
9
+ ams/system.py,sha256=eAsaXO2O_7_PAIuPFup3edztuAhKMhODrR9l92CYx38,29765
10
10
  ams/cases/5bus/pjm5bus_demo.json,sha256=IpxO2vzB9-9Kg9xjOXREKeXEz9wjFE7cuQbcUu8VORA,23152
11
11
  ams/cases/5bus/pjm5bus_demo.xlsx,sha256=OWIUprkg8_aQ_bTCaEFMl7Bhfa1R20zxAHXRQtXBix0,32607
12
12
  ams/cases/5bus/pjm5bus_ev.xlsx,sha256=vR8dJv5jIxib1pgcMonhzvraoqZVJWhBSJdVXDL0qsI,19498
@@ -37,7 +37,7 @@ ams/cases/wecc/wecc.m,sha256=8Wqal6H5r1wNxLLQBCXo2V3v3JZY5IJDEkyrEGCrCWE,30498
37
37
  ams/cases/wecc/wecc_uced.xlsx,sha256=R3tZgxEqz_ctKcjA1wwFecxn-QZXutvf7NzgnCg_078,94767
38
38
  ams/core/__init__.py,sha256=lIvrAvYf2yrHWqYi0rVuJgJt8KNA8nTmN2iuZ125z9Q,123
39
39
  ams/core/common.py,sha256=934J7xq5JvC14yKp2Z4hWKUFJFhxzAnxB_8_99CChY0,704
40
- ams/core/documenter.py,sha256=FNkpiP65iO809B4Bgmp5C1QeJTQHi-sS9vTP7Wd9D8Q,23131
40
+ ams/core/documenter.py,sha256=3-jUYrtN8zDZXd8tQZlmZouJluJPH9_xIDbK9ZEEnRU,25762
41
41
  ams/core/matprocessor.py,sha256=3eEij-ul8Rx25ZwNbv66YEOKyUXB-fYO-ZQs5BpqmIU,26610
42
42
  ams/core/model.py,sha256=LNZtzyf2A7Tz3pn9IDs35JYaHSkQRqhqZicTpZGSqsc,10926
43
43
  ams/core/param.py,sha256=LPH48xUHyqWqODD6IsiamUtkJDDSgGCEMAo6vroFoHE,11130
@@ -88,29 +88,29 @@ ams/routines/dcopf2.py,sha256=sDCP8zqYHDh7s7p9SX6G8QhMfIxCg3VPYJn6r3pRKyo,3620
88
88
  ams/routines/dcpf.py,sha256=lGZ9LmCL1DsFB-sNxI7NGrq0qd_iBRMDPJmU5022t20,8242
89
89
  ams/routines/dopf.py,sha256=8D36-FkPORYGaMnwGTqwz8HxAXk5ywo3mk8NlGq327g,6289
90
90
  ams/routines/ed.py,sha256=9Hf_ZqD6poIxCIBfsTMC0DGoPNEja1ZtVxqhb4ijhgE,11875
91
- ams/routines/grbopt.py,sha256=DeNpm6JU-I_i_Q_vicaz_u_MnrE6zSLeyxcfJOluOoc,5367
91
+ ams/routines/grbopt.py,sha256=RjrMq6XPHeBEbf-Pt9sLk2D1vnXZYYwaic4BP8lbACg,5480
92
92
  ams/routines/pflow.py,sha256=5_9n10r_PfsVXIRkaBgKxVITumImZ8mvpHnwxX_ECdw,9432
93
- ams/routines/pypower.py,sha256=1DjhNpCqhSQdZivYQsNvpBaKUEhmNsiWGgAHdMB7cOk,26740
93
+ ams/routines/pypower.py,sha256=U1UJbcNG7JawGmK9sKtjZlRrGwODVWDjJFucisMcvJs,26545
94
94
  ams/routines/routine.py,sha256=v4jzsziQPvbVh5m0AH629NBEtmKlLvitFW5m-YfFtfY,35833
95
95
  ams/routines/rted.py,sha256=GOHRxo0-HS5HhwQg8lv7-2VcGr_M_TdUvvomgJ31fDQ,22070
96
96
  ams/routines/type.py,sha256=lvTWSnCYIbRJXIm3HX6jA0Hv-WWYusTOUPfoW8DITlU,3877
97
97
  ams/routines/uc.py,sha256=VcuNy2TnBjsewKEGIqeo2EFTyuhpx5QsEvgpAtscDIQ,15648
98
98
  ams/utils/__init__.py,sha256=2hAQmWRgmnE-bCGT9cJoW9FkPDMGRiGkbBcUgj-bgjI,122
99
99
  ams/utils/misc.py,sha256=Y6tPKpUKJa7bL9alroJuG2UNW9vdQjnfAmKb2EbIls8,2027
100
- ams/utils/paths.py,sha256=D9VNUwtJtHy-8PFzMnxtQ9HpkOXT6vdVOjfOTuoKGKw,6699
100
+ ams/utils/paths.py,sha256=o9Ku2ETmYxsoD7VbMlS4qv_wGtXtT-SWIgDs0F7jpCQ,6693
101
101
  docs/Makefile,sha256=UKXBFAbKGPt1Xw9J84343v0Mh8ylAZ-tE0uCd74DrQU,725
102
102
  docs/make.bat,sha256=9UgKGb4SdP006622fJiFxeFT1BeycYAs6hDbV1xwPy8,804
103
103
  docs/source/api.rst,sha256=BRzdDFDzDwVL7Jr_Xj-O5Icgx0gt5hNNd1OjvPl7ap0,1490
104
104
  docs/source/conf.py,sha256=UyoWogZTUNSJU7pQS_JaR28nKddW94zr01LYoIciZZw,6688
105
105
  docs/source/genmodelref.py,sha256=IhmF7bDw8BXPvLD8V3WjQNrfc-H07r5iS-_4DHbbp-8,1420
106
- docs/source/genroutineref.py,sha256=0JyMc2kV5bWrWbSoO6d7o4QgDgG8mVy3JGGQWacJypw,1064
106
+ docs/source/genroutineref.py,sha256=glHhbWUXfZzMDrkque9CBZu8QtdxlxPojInERzAAOwA,1063
107
107
  docs/source/index.rst,sha256=N5phQS5RIyYs-NZo_5yYB8LjvHzOKLeXzRA-M8i-g3Q,2688
108
- docs/source/release-notes.rst,sha256=Fa-rDL0lhaZVi8nwfyn7gCQhQUKyn7NtMIIBkeGM-Vc,13724
108
+ docs/source/release-notes.rst,sha256=7BtbNLQ2EUvSvB9KGNELicPAFqNT8uBzQQLqlT9MpMc,13830
109
109
  docs/source/_templates/autosummary/base.rst,sha256=zl3U4baR4a6YjsHyT-x9zCOrHwKZOVUdWn1NPX2u3bc,106
110
110
  docs/source/_templates/autosummary/class.rst,sha256=Hv_igCsLsUpM62_zN0nqj6FSfKnS5xLyu8ZldMbfOAk,668
111
111
  docs/source/_templates/autosummary/module.rst,sha256=YdbpCudOrEU-JbuSlzGvcOI2hn_KrCM6FW5HcGqkaEE,1113
112
112
  docs/source/_templates/autosummary/module_toctree.rst,sha256=sg30OdqFDLyo8Y3hl9V-s2BXb1bzcjjqqWaWi-C3qFM,1126
113
- docs/source/examples/index.rst,sha256=6VT3wVeKk8BWf6pJQtZrmcumW_3jI8esdlzja8scUCA,742
113
+ docs/source/examples/index.rst,sha256=yXR54WHHcBY38-h9LkdTBcNq3HDeT6eSNyrMmafq12E,792
114
114
  docs/source/getting_started/copyright.rst,sha256=d3S7FjrbysVqQd3pEBadrrkcQOZ7sYYeDTCOS4goPC8,715
115
115
  docs/source/getting_started/index.rst,sha256=mcp1NdUwbPoNzpn7Owf5Qzfd6J_--ToU52PjmrbwjBY,1512
116
116
  docs/source/getting_started/install.rst,sha256=pCL5GDNxwkWnrPaO48i9c0bBPT_dYAWvD2CQ7Oi2P_0,7400
@@ -136,7 +136,7 @@ docs/source/modeling/model.rst,sha256=j7OSvoXnDht6rGpgwPiJklsCWrebfx4DxIN-G8r6iF
136
136
  docs/source/modeling/routine.rst,sha256=BkUE3y5L1lA7LP9Nyzc4zzY-tF3t4k7egBE188kybHY,4286
137
137
  docs/source/modeling/system.rst,sha256=NMOPNMOKG1_dRyNPPx-MiCKbbpadxWJxGyU6geRUsvQ,1374
138
138
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
139
- tests/test_1st_system.py,sha256=63ngZwXbUzs1964XmqzlkWUgBugi29vuEDMBBTXxLiE,1900
139
+ tests/test_1st_system.py,sha256=WoCgeyUCjBVwyYCqzwDkYy8F3dWArMQBESqIUQk6tOk,1907
140
140
  tests/test_addressing.py,sha256=MIT713KCqMg0h2o4rBDZsGUrpGadmMlXnrrdq-wB77E,1364
141
141
  tests/test_case.py,sha256=b_YZhwIN9sX3FCMD03hRNygV-mYthNj7cOhEv7-by-g,8857
142
142
  tests/test_cli.py,sha256=TtCGBy2e7Ll_2gJTFo9juZtzhaakho_MqkcqhG2w2dk,870
@@ -163,8 +163,8 @@ tests/test_rtn_pypower.py,sha256=KO5VOZxETxVH2mY1mgNvzj1gz1Gdak1sAWxYleDU4E8,104
163
163
  tests/test_rtn_rted.py,sha256=QHDUymorCqQAJKFlDgTy40JyLTGDvNVNU3tjbjDl3-0,9850
164
164
  tests/test_rtn_uc.py,sha256=UbMeaam3dZwgq2LAJokGOl3LT5B3TWKMjCp4dRcLs40,8497
165
165
  tests/test_service.py,sha256=6IP6CAH2xHxGHZM4-R8LjZxVJ2L10LcGaPDyRIqKLmc,2438
166
- ltbams-1.0.10.dist-info/METADATA,sha256=607sw75UjOTCI4FuqQROlZn7BobwBeBubXQ5r9H_Bgc,13511
167
- ltbams-1.0.10.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
168
- ltbams-1.0.10.dist-info/entry_points.txt,sha256=FA56FlhO_yVNeEf810SrorVQb7_Xsmo3_EW-W-ijUfA,37
169
- ltbams-1.0.10.dist-info/top_level.txt,sha256=pyKDqG2kj13F9-BYd_wkruRdBSqLXw8Nwc-cmljqrxg,15
170
- ltbams-1.0.10.dist-info/RECORD,,
166
+ ltbams-1.0.11.dist-info/METADATA,sha256=HJopLlES434MQhl_hg4DDQNs90TfSJLovZKG-NChtNs,13808
167
+ ltbams-1.0.11.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
168
+ ltbams-1.0.11.dist-info/entry_points.txt,sha256=FA56FlhO_yVNeEf810SrorVQb7_Xsmo3_EW-W-ijUfA,37
169
+ ltbams-1.0.11.dist-info/top_level.txt,sha256=pyKDqG2kj13F9-BYd_wkruRdBSqLXw8Nwc-cmljqrxg,15
170
+ ltbams-1.0.11.dist-info/RECORD,,
tests/test_1st_system.py CHANGED
@@ -30,7 +30,7 @@ class TestCodegen(unittest.TestCase):
30
30
  docum._var_doc(max_width=78, export=export)
31
31
  docum._service_doc(max_width=78, export=export)
32
32
  docum._param_doc(max_width=78, export=export)
33
- docum.config.doc(max_width=78, export=export)
33
+ docum.parent.config.doc(max_width=78, export=export)
34
34
 
35
35
 
36
36
  class TestParamCorrection(unittest.TestCase):