Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement features development #581

Merged
merged 24 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
if not hasattr(instance, 'vin'):
raise AttributeError(f"{self.class_name}.{src} has no `vin` attribute.")
jinningwang marked this conversation as resolved.
Show resolved Hide resolved

if hasattr(instance, 'vin') and (instance.vin is not None):
uid = self.idx2uid(idx)
self.set(src, idx, 'v', value * instance.pu_coeff[uid])
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])
else:
self.set(src, idx, 'v', value)
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
19 changes: 14 additions & 5 deletions docs/source/release-notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,21 @@ v1.9.3 (2024-04-XX)
- 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.
- 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``

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