Skip to content

Commit

Permalink
Merge pull request #100 from CURENT/misc
Browse files Browse the repository at this point in the history
Misc
  • Loading branch information
jinningwang authored Nov 23, 2024
2 parents 61a3116 + d8c7b38 commit b238c73
Show file tree
Hide file tree
Showing 46 changed files with 2,482 additions and 1,872 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ Python Software for Power System Scheduling Modeling and Co-Simulation with Dyna

# Why AMS

With the built-in interface with dynamic simulation engine, ANDES, AMS enables Dynamics Interfaced Stability Constrained Production Cost and Market Operation Modeling.
With the built-in interface with ANDES, AMS enables **Dynamics Incorporated Stability-Constrained Scheduling**.

AMS is a **Modeling Framework** that provides a descriptive way to formulate scheduling problems.
The optimization problems are then handled by **CVXPY** and solved with third-party solvers.

AMS produces credible scheduling results and competitive performance.
The following results show the comparison of DCOPF between AMS and other tools.
Expand Down
3 changes: 2 additions & 1 deletion ams/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from . import _version
__version__ = _version.get_versions()['version']

from ams import opt # NOQA
from ams import benchmarks # NOQA

from ams.main import config_logger, load, run # NOQA
Expand All @@ -10,4 +11,4 @@

__author__ = 'Jining Wang'

__all__ = ['System', 'get_case', 'System']
__all__ = ['System', 'get_case']
80 changes: 74 additions & 6 deletions ams/core/documenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,10 @@ def get(self, max_width=78, export='plain'):
# add tables
self.parent.syms.generate_symbols()
out += self._obj_doc(max_width=max_width, export=export)
out += self._constr_doc(max_width=max_width, export=export)
out += self._expr_doc(max_width=max_width, export=export)
out += self._constr_doc(max_width=max_width, export=export)
out += self._var_doc(max_width=max_width, export=export)
out += self._exprc_doc(max_width=max_width, export=export)
out += self._service_doc(max_width=max_width, export=export)
out += self._param_doc(max_width=max_width, export=export)
out += self.config.doc(max_width=max_width, export=export)
Expand Down Expand Up @@ -316,17 +317,26 @@ def _constr_doc(self, max_width=78, export='plain'):
rest_dict=rest_dict)

def _expr_doc(self, max_width=78, export='plain'):
# expression documentation
# Expression documentation
if len(self.parent.exprs) == 0:
return ''

# prepare temporary lists
names, var_names, info = list(), list(), list()
names, info = list(), list()
units, sources, units_rest = list(), list(), list()

for p in self.parent.exprs.values():
names.append(p.name)
var_names.append(p.var)
info.append(p.info if p.info else '')
units.append(p.unit if p.unit else '')
units_rest.append(f'*{p.unit}*' if p.unit else '')

slist = []
if p.owner is not None and p.src is not None:
slist.append(f'{p.owner.class_name}.{p.src}')
elif p.owner is not None and p.src is None:
slist.append(f'{p.owner.class_name}')
sources.append(','.join(slist))

# expressions based on output format
expressions = []
Expand All @@ -342,13 +352,67 @@ def _expr_doc(self, max_width=78, export='plain'):
expressions = math_wrap(expressions, export=export)

plain_dict = OrderedDict([('Name', names),
('Variable', var_names),
('Description', info),
('Unit', units),
])
rest_dict = OrderedDict([('Name', names),
('Description', info),
('Expression', expressions),
('Unit', units_rest),
('Source', sources),
])

# convert to rows and export as table
return make_doc_table(title=title,
max_width=max_width,
export=export,
plain_dict=plain_dict,
rest_dict=rest_dict)

def _exprc_doc(self, max_width=78, export='plain'):
# ExpressionCalc documentation
if len(self.parent.exprcs) == 0:
return ''

# prepare temporary lists
names, info = list(), list()
units, sources, units_rest = list(), list(), list()

for p in self.parent.exprcs.values():
names.append(p.name)
info.append(p.info if p.info else '')
units.append(p.unit if p.unit else '')
units_rest.append(f'*{p.unit}*' if p.unit else '')

slist = []
if p.owner is not None and p.src is not None:
slist.append(f'{p.owner.class_name}.{p.src}')
elif p.owner is not None and p.src is None:
slist.append(f'{p.owner.class_name}')
sources.append(','.join(slist))

# expressions based on output format
expressions = []
if export == 'rest':
for p in self.parent.exprcs.values():
expr = _tex_pre(self, p, self.parent.syms.tex_map)
logger.debug(f'{p.name} math: {expr}')
expressions.append(expr)

title = 'ExpressionCalcs\n----------------------------------'
else:
title = 'ExpressionCalcs'
expressions = math_wrap(expressions, export=export)

plain_dict = OrderedDict([('Name', names),
('Description', info),
('Unit', units),
])
rest_dict = OrderedDict([('Name', names),
('Variable', var_names),
('Description', info),
('Expression', expressions),
('Unit', units_rest),
('Source', sources),
])

# convert to rows and export as table
Expand Down Expand Up @@ -423,6 +487,8 @@ def _var_doc(self, max_width=78, export='plain'):
slist = []
if p.owner is not None and p.src is not None:
slist.append(f'{p.owner.class_name}.{p.src}')
elif p.owner is not None and p.src is None:
slist.append(f'{p.owner.class_name}')
sources.append(','.join(slist))

# symbols based on output format
Expand Down Expand Up @@ -490,6 +556,8 @@ def _param_doc(self, max_width=78, export='plain'):
slist = []
if p.owner is not None and p.src is not None:
slist.append(f'{p.owner.class_name}.{p.src}')
elif p.owner is not None and p.src is None:
slist.append(f'{p.owner.class_name}')
sources.append(','.join(slist))

# symbols based on output format
Expand Down
6 changes: 4 additions & 2 deletions ams/core/matprocessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from andes.shared import tqdm, tqdm_nb
from andes.utils.misc import elapsed, is_notebook

from ams.opt.omodel import Param
from ams.opt import Param
from ams.shared import pd, sps

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -140,7 +140,9 @@ def class_name(self):

class MatProcessor:
"""
Class for matrix processing in AMS system.
Class for matrices processing in AMS system.
The connectivity matrices `Cft`, `Cg`, `Cl`, and `Csh` ***have taken*** the
devices connectivity into account.
The MParams' row names and col names are assigned in `System.setup()`.
"""
Expand Down
2 changes: 1 addition & 1 deletion ams/core/param.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import numpy as np
from scipy.sparse import issparse

from ams.opt.omodel import Param
from ams.opt import Param

logger = logging.getLogger(__name__)

Expand Down
66 changes: 43 additions & 23 deletions ams/core/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from andes.core.service import BaseService

from ams.opt.omodel import Param
from ams.opt import Param


logger = logging.getLogger(__name__)
Expand All @@ -33,8 +33,6 @@ class RBaseService(BaseService, Param):
Description.
vtype : Type, optional
Variable type.
model : str, optional
Model name.
no_parse: bool, optional
True to skip parsing the service.
sparse: bool, optional
Expand Down Expand Up @@ -106,8 +104,8 @@ class ValueService(RBaseService):
Description.
vtype : Type, optional
Variable type.
model : str, optional
Model name.
no_parse: bool, optional
True to skip parsing the service.
sparse: bool, optional
True to return output as scipy csr_matrix.
"""
Expand Down Expand Up @@ -155,8 +153,8 @@ class ROperationService(RBaseService):
Description.
vtype : Type, optional
Variable type.
model : str, optional
Model name.
no_parse: bool, optional
True to skip parsing the service.
sparse: bool, optional
True to return output as scipy csr_matrix.
"""
Expand Down Expand Up @@ -194,6 +192,8 @@ class LoadScale(ROperationService):
Unit.
info : str, optional
Description.
no_parse: bool, optional
True to skip parsing the service.
sparse: bool, optional
True to return output as scipy csr_matrix.
"""
Expand Down Expand Up @@ -236,7 +236,7 @@ class NumOp(ROperationService):
Note that the scalar output is converted to a 1D array.
The optional kwargs are passed to the input function.
The `rargs` are passed to the input function.
Parameters
----------
Expand Down Expand Up @@ -397,8 +397,6 @@ class NumOpDual(NumOp):
Description.
vtype : Type, optional
Variable type.
model : str, optional
Model name.
rfun : Callable, optional
Function to apply to the output of ``fun``.
rargs : dict, optional
Expand All @@ -407,6 +405,8 @@ class NumOpDual(NumOp):
Expand the dimensions of the output array along a specified axis.
array_out : bool, optional
Whether to force the output to be an array.
no_parse: bool, optional
True to skip parsing the service.
sparse: bool, optional
True to return output as scipy csr_matrix.
"""
Expand Down Expand Up @@ -467,6 +467,10 @@ class MinDur(NumOpDual):
Unit.
info : str, optional
Description.
vtype : Type, optional
Variable type.
no_parse: bool, optional
True to skip parsing the service.
sparse: bool, optional
True to return output as scipy csr_matrix.
"""
Expand Down Expand Up @@ -537,8 +541,12 @@ class NumHstack(NumOp):
Description.
vtype : Type, optional
Variable type.
model : str, optional
Model name.
rfun : Callable, optional
Function to apply to the output of ``fun``.
rargs : dict, optional
Keyword arguments to pass to ``rfun``.
no_parse: bool, optional
True to skip parsing the service.
sparse: bool, optional
True to return output as scipy csr_matrix.
"""
Expand Down Expand Up @@ -624,8 +632,12 @@ class ZonalSum(NumOp):
Description.
vtype : Type
Variable type.
model : str
Model name.
rfun : Callable, optional
Function to apply to the output of ``fun``.
rargs : dict, optional
Keyword arguments to pass to ``rfun``.
no_parse: bool, optional
True to skip parsing the service.
sparse: bool, optional
True to return output as scipy csr_matrix.
"""
Expand Down Expand Up @@ -676,7 +688,7 @@ class VarSelect(NumOp):
A numerical matrix to select a subset of a 2D variable,
``u.v[:, idx]``.
For example, if nned to select Energy Storage output
For example, if need to select Energy Storage output
power from StaticGen `pg`, following definition can be used:
```python
class RTED:
Expand Down Expand Up @@ -709,6 +721,8 @@ class RTED:
Keyword arguments to pass to ``rfun``.
array_out : bool, optional
Whether to force the output to be an array.
no_parse: bool, optional
True to skip parsing the service.
sparse: bool, optional
True to return output as scipy csr_matrix.
"""
Expand Down Expand Up @@ -801,8 +815,12 @@ class VarReduction(NumOp):
A description of the operation.
vtype : Type, optional
The variable type.
model : str, optional
The model name associated with the operation.
rfun : Callable, optional
Function to apply to the output of ``fun``.
rargs : dict, optional
Keyword arguments to pass to ``rfun``.
no_parse: bool, optional
True to skip parsing the service.
sparse: bool, optional
True to return output as scipy csr_matrix.
"""
Expand All @@ -818,13 +836,11 @@ def __init__(self,
rfun: Callable = None,
rargs: dict = None,
no_parse: bool = False,
sparse: bool = False,
**kwargs):
sparse: bool = False,):
super().__init__(name=name, tex_name=tex_name, unit=unit,
info=info, vtype=vtype,
u=u, fun=None, rfun=rfun, rargs=rargs,
no_parse=no_parse, sparse=sparse,
**kwargs)
no_parse=no_parse, sparse=sparse,)
self.fun = fun

@property
Expand Down Expand Up @@ -859,8 +875,12 @@ class RampSub(NumOp):
Description.
vtype : Type
Variable type.
model : str
Model name.
rfun : Callable, optional
Function to apply to the output of ``fun``.
rargs : dict, optional
Keyword arguments to pass to ``rfun``.
no_parse: bool, optional
True to skip parsing the service.
sparse: bool, optional
True to return output as scipy csr_matrix.
"""
Expand Down
Loading

0 comments on commit b238c73

Please sign in to comment.