Skip to content

Commit

Permalink
Merge pull request #581 from jinningwang/alt
Browse files Browse the repository at this point in the history
Enhancement features development
  • Loading branch information
cuihantao authored Nov 28, 2024
2 parents 12135ed + c9bfaf1 commit 4e992a8
Show file tree
Hide file tree
Showing 9 changed files with 2,608 additions and 20 deletions.
36 changes: 31 additions & 5 deletions andes/core/model/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ def set(self, src, idx, attr, value):

return True

def alter(self, src, idx, value):
def alter(self, src, idx, value, attr='v'):
"""
Alter values of input parameters or constant service.
Expand All @@ -546,17 +546,43 @@ def alter(self, src, idx, value):
The device to alter
value : float
The desired value
attr : str
The attribute to alter, default is 'v'.
Notes
-----
New in version 1.9.3: Added the `attr` parameter and the feature to alter
specific attributes. This feature is useful when you need to manipulate parameter
values in the system base and ensure that these changes are reflected in the
dumped case file.
Examples
--------
>>> import andes
>>> ss = andes.load(andes.get_case('5bus/pjm5bus.xlsx'), setup=True)
>>> ss.GENCLS.alter(src='M', idx=2, value=1, attr='v')
>>> ss.GENCLS.get(src='M', idx=2, attr='v')
3.0
>>> ss.GENCLS.alter(src='M', idx=2, value=1, attr='vin')
>>> ss.GENCLS.get(src='M', idx=2, attr='v')
1.0
"""

instance = self.__dict__[src]

if hasattr(instance, 'vin') and (instance.vin is not None):
self.set(src, idx, 'vin', value)

uid = self.idx2uid(idx)
self.set(src, idx, 'v', value * instance.pu_coeff[uid])
else:
if attr == 'vin':
self.set(src, idx, 'vin', value / instance.pu_coeff[uid])
self.set(src, idx, 'v', value=value)
else:
self.set(src, idx, 'vin', value)
self.set(src, idx, 'v', value * instance.pu_coeff[uid])
elif not hasattr(instance, 'vin') and attr == 'vin':
logger.warning(f"{self.class_name}.{src} has no `vin` attribute, changing `v`.")
self.set(src, idx, 'v', value)
else:
self.set(src, idx, attr=attr, value=value)

def get_inputs(self, refresh=False):
"""
Expand Down
7 changes: 5 additions & 2 deletions andes/core/model/modeldata.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,12 +202,15 @@ def as_df(self, vin=False):
Export all parameters as a `pandas.DataFrame` object.
This function utilizes `as_dict` for preparing data.
Parameters
----------
vin : bool
If True, export all parameters from original input (``vin``).
Returns
-------
DataFrame
A dataframe containing all model data. An `uid` column is added.
vin : bool
If True, export all parameters from original input (``vin``).
"""
if vin is False:
out = pd.DataFrame(self.as_dict()).set_index('uid')
Expand Down
97 changes: 95 additions & 2 deletions andes/models/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import numpy as np

from andes.core.service import BackRef
from andes.shared import pd
from andes.utils.func import list_flatten, validate_keys_values

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -243,6 +244,38 @@ def set(self, src: str, idx, attr, value):

return True

def alter(self, src, idx, value, attr='v'):
"""
Alter values of input parameters or constant service for a group of models.
.. note::
New in version 1.9.3.
Parameters
----------
src : str
The parameter name to alter
idx : str, float, int
The unique identifier for the device to alter
value : float
The desired value
attr : str, optional
The attribute to alter. Default is 'v'.
"""
self._check_src(src)
self._check_idx(idx)

idx, _ = self._1d_vectorize(idx)
models = self.idx2model(idx)

if isinstance(value, (str, int, float, np.integer, np.floating)):
value = [value] * len(idx)

for mdl, ii, val in zip(models, idx, value):
mdl.alter(src, ii, val, attr=attr)

return True

def find_idx(self, keys, values, allow_none=False, default=None, allow_all=False):
"""
Find indices of devices that satisfy the given `key=value` condition.
Expand Down Expand Up @@ -442,6 +475,9 @@ def get_all_idxes(self):
"""
Return all the devices idx in this group.
.. note::
New in version 1.9.3.
Returns
-------
list
Expand All @@ -463,6 +499,63 @@ def get_all_idxes(self):
"""
return list(self._idx2model.keys())

def as_dict(self, vin=False):
"""
Export group common parameters as a dictionary.
.. note::
New in version 1.9.3.
This method returns a dictionary where the keys are the `ModelData` parameter names
and the values are array-like structures containing the data in the order they were added.
Unlike `ModelData.as_dict()`, this dictionary does not include the `uid` field.
Parameters
----------
vin : bool, optional
If True, includes the `vin` attribute in the dictionary. Default is False.
Returns
-------
dict
A dictionary of common parameters.
"""
out_all = []
out_params = self.common_params.copy()
out_params.insert(2, 'idx')

for mdl in self.models.values():
if mdl.n <= 0:
continue
mdl_data = mdl.as_df(vin=True) if vin else mdl.as_dict()
mdl_dict = {k: mdl_data.get(k) for k in out_params if k in mdl_data}
out_all.append(mdl_dict)

if not out_all:
return {}

out = {key: np.concatenate([item[key] for item in out_all]) for key in out_all[0].keys()}
return out

def as_df(self, vin=False):
"""
Export group common parameters as a `pandas.DataFrame` object.
.. note::
New in version 1.9.3.
Parameters
----------
vin : bool
If True, export all parameters from original input (``vin``).
Returns
-------
DataFrame
A dataframe containing all model data. An `uid` column is added.
"""
return pd.DataFrame(self.as_dict(vin=vin))

def doc(self, export='plain'):
"""
Return the documentation of the group in a string.
Expand Down Expand Up @@ -579,7 +672,7 @@ class StaticGen(GroupBase):

def __init__(self):
super().__init__()
self.common_params.extend(('Sn', 'Vn', 'p0', 'q0', 'ra', 'xs', 'subidx'))
self.common_params.extend(('bus', 'Sn', 'Vn', 'p0', 'q0', 'ra', 'xs', 'subidx'))
self.common_vars.extend(('q', 'a', 'v'))

self.SynGen = BackRef()
Expand Down Expand Up @@ -642,7 +735,7 @@ class SynGen(GroupBase):

def __init__(self):
super().__init__()
self.common_params.extend(('Sn', 'Vn', 'fn', 'bus', 'M', 'D', 'subidx'))
self.common_params.extend(('bus', 'gen', 'Sn', 'Vn', 'fn', 'M', 'D', 'subidx'))
self.common_vars.extend(('omega', 'delta', ))
self.idx_island = []
self.uid_island = []
Expand Down
36 changes: 25 additions & 11 deletions docs/source/release-notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ v1.9 Notes

v1.9.3 (2024-04-XX)
-------------------
Development of connectivity manager `ConnMan`:
Development of connectivity manager ``ConnMan``:

- Add case `ieee14_conn.xlsx` for demonstration.
- Add `ConnMan` class to manage connectivity.
- Add `ConnMan` to `System` to as an attribute `conn`.
- Add a demo notebook for `ConnMan`.
- Add case ``ieee14_conn.xlsx`` for demonstration.
- Add ``ConnMan`` class to manage connectivity.
- Add ``ConnMan`` to `System` to as an attribute ``conn``.
- Add a demo notebook ``ConnMan.ipynb``. See folder ``andes/examples/demonstration``.

Other changes:

Expand All @@ -25,13 +25,27 @@ Other changes:
- In symbolic processor, most variables are assumed to be real, except some
services that are specified as complex. This will allow generating simplified
expressions.
- Adjust `BusFreq.Tw.default` to 0.1.
- Adjust ``BusFreq.Tw.default`` to 0.1.
- Add parameter from_csv=None in TDS.run() to allow loading data from CSV files at TDS begining.
- Fix `TDS.init()` and `TDS._csv_step()` to fit loading from CSV when `Output` exists.
- Add parameter `allow_all=False` to `ModelData.find_idx()` `GroupBase.find_idx()` to allow searching all matches.
- Add method `GroupBase.get_all_idxes()` to get all indices of a group.
- Enhanced three-winding transformer parsing in PSS/E raw files by assigning the equivalent star bus `area`, `owner`, and `zone` using the high-voltage bus values.
- Specify `multiprocess <=0.70.16` in requirements as 0.70.17 does not support Linux.
- Fix ``TDS.init()`` and ``TDS._csv_step()`` to fit loading from CSV when ``Output`` exists.
- Add function signature ``allow_all=False`` to ``ModelData.find_idx()`` ``GroupBase.find_idx()``
to allow searching all matches.
- Enhanced three-winding transformer parsing in PSS/E raw files by assigning the equivalent star bus ``area``,
``owner``, and ``zone`` using the high-voltage bus values.
- Add function signature ``attr='v'`` to method ``Model.alter`` for altering parameter values without manual
per unit conversion
- Add following methods to ``GroupBase`` for easier usage: ``get_all_idxes``, ``alter``, ``as_dict``, and ``as_df``
- Add two demo ``add_RenGen.ipynb`` and ``replace_SynGen.ipynb`` to show how to do renewable penetration via code.
See folder ``andes/examples/demonstration``
- Add a demo ``manipulate_params.ipynb`` to compare the differnce between ``set`` and ``alter``
- Extend ``SynGen`` common parameters with ``bus``, ``gen``, ``Sn``, ``Vn``, and ``fn``
- Extend ``StaticGen`` common parameters with ``bus``
- Fix ``TDS.init()`` and ``TDS._csv_step()`` to fit loading from CSV when ``Output`` exists.
- Add parameter ``allow_all=False`` to ``ModelData.find_idx()`` ``GroupBase.find_idx()`` to allow searching all matches.
- Add method ``GroupBase.get_all_idxes()`` to get all indices of a group.
- Enhanced three-winding transformer parsing in PSS/E raw files by assigning the equivalent star bus ``area``,
``owner``, and ``zone`` using the high-voltage bus values.
- Specify `multiprocess<=0.70.16` in requirements as 0.70.17 does not support Linux.

v1.9.2 (2024-03-25)
-------------------
Expand Down
Loading

0 comments on commit 4e992a8

Please sign in to comment.