Skip to content

Commit

Permalink
Merge pull request #259 from cuihantao/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
cuihantao committed Jan 31, 2022
2 parents aa4567c + 40c7bc2 commit 9281c39
Show file tree
Hide file tree
Showing 26 changed files with 2,181 additions and 1,205 deletions.
1,405 changes: 1,405 additions & 0 deletions andes/cases/ieee14/ieee14_exac1.json

Large diffs are not rendered by default.

Binary file added andes/cases/ieee14/ieee14_pll1.xlsx
Binary file not shown.
6 changes: 3 additions & 3 deletions andes/cli.py
Expand Up @@ -5,11 +5,11 @@
import argparse
import importlib
import logging
import os
import platform
import sys
from time import strftime

from andes.shared import NCPUS_PHYSICAL
from ._version import get_versions

from andes.main import config_logger, find_log_path
Expand Down Expand Up @@ -59,7 +59,7 @@ def create_parser():
run.add_argument('-P', '--pert', help='Perturbation file path', default='')
run.add_argument('-o', '--output-path', help='Output path prefix', type=str, default='')
run.add_argument('-n', '--no-output', help='Force no output of any kind', action='store_true')
run.add_argument('--ncpu', help='Number of parallel processes', type=int, default=os.cpu_count())
run.add_argument('--ncpu', help='Number of parallel processes', type=int, default=NCPUS_PHYSICAL)
run.add_argument('--dime-address', help='DiME streaming server protocol, address and port,'
'e.g., tcp://127.0.0.1:5000 or ipc:///tmp/dime2', type=str)
run.add_argument('--tf', help='End time of time-domain simulation', type=float)
Expand Down Expand Up @@ -159,7 +159,7 @@ def create_parser():
prep.add_argument('--pycode-path', help='Save path for generated pycode')
prep.add_argument('-m', '--models', nargs='*', help='model names to be individually prepared',
)
prep.add_argument('--ncpu', help='Number of parallel processes', type=int, default=os.cpu_count())
prep.add_argument('--ncpu', help='Number of parallel processes', type=int, default=NCPUS_PHYSICAL)
prep.add_argument('--nomp', help='Disable multiprocessing', action='store_true',)
prep.add_argument('--incubate', help='Save generated pycode under the ANDES code directory to avoid codegen',
action='store_true')
Expand Down
34 changes: 14 additions & 20 deletions andes/core/block.py
Expand Up @@ -11,11 +11,9 @@
from collections import OrderedDict
from typing import Iterable, List, Optional, Tuple, Union

import numpy as np

from andes.core.common import JacTriplet, ModelFlags, dummify
from andes.core.discrete import (AntiWindup, AntiWindupRate, DeadBand,
HardLimiter, LessThan, RateLimiter, Selector,)
HardLimiter, LessThan, RateLimiter,)
from andes.core.service import EventFlag
from andes.core.var import Algeb, State

Expand Down Expand Up @@ -1593,12 +1591,9 @@ def __init__(self, u1, u2, name=None, tex_name=None, info=None):
self.u2 = dummify(u2)
self.enforce_tex_name((u1, u2))

self.sl = Selector(self.u1, self.u2, fun=np.maximum.reduce,
info='HVGate Selector',
)

self.y = Algeb(info='HVGate output', tex_name='y', discrete=self.sl)
self.vars = {'y': self.y, 'sl': self.sl}
self.lt = LessThan(self.u1, self.u2)
self.y = Algeb(info='HVGate output', tex_name='y', discrete=self.lt)
self.vars = {'y': self.y, 'lt': self.lt}

def define(self):
"""
Expand All @@ -1619,8 +1614,8 @@ def define(self):
Not sure if this is a bug or intended.
"""
self.y.v_str = f'{self.name}_sl_s0*{self.u1.name} + {self.name}_sl_s1*{self.u2.name}'
self.y.e_str = f'{self.name}_sl_s0*{self.u1.name} + {self.name}_sl_s1*{self.u2.name} - ' \
self.y.v_str = f'{self.name}_lt_z0*{self.u1.name} + {self.name}_lt_z1*{self.u2.name}'
self.y.e_str = f'{self.name}_lt_z0*{self.u1.name} + {self.name}_lt_z1*{self.u2.name} - ' \
f'{self.name}_y'


Expand All @@ -1642,13 +1637,10 @@ def __init__(self, u1, u2, name=None, tex_name=None, info=None):
self.u2 = dummify(u2)
self.enforce_tex_name((u1, u2))

self.sl = Selector(self.u1, self.u2, fun=np.minimum.reduce,
info='LVGate Selector',
)
self.lt = LessThan(self.u1, self.u2)
self.y = Algeb(info='LVGate output', tex_name='y', discrete=self.lt)

self.y = Algeb(info='LVGate output', tex_name='y', discrete=self.sl)

self.vars = {'y': self.y, 'sl': self.sl}
self.vars = {'y': self.y, 'lt': self.lt}

def define(self):
"""
Expand All @@ -1664,8 +1656,8 @@ def define(self):
Same problem as `HVGate` as `minimum` does not sympify correctly.
"""
self.y.v_str = f'{self.name}_sl_s0*{self.u1.name} + {self.name}_sl_s1*{self.u2.name}'
self.y.e_str = f'{self.name}_sl_s0*{self.u1.name} + {self.name}_sl_s1*{self.u2.name} - ' \
self.y.v_str = f'{self.name}_lt_z1*{self.u1.name} + {self.name}_lt_z0*{self.u2.name}'
self.y.e_str = f'{self.name}_lt_z1*{self.u1.name} + {self.name}_lt_z0*{self.u2.name} - ' \
f'{self.name}_y'


Expand Down Expand Up @@ -1807,6 +1799,8 @@ class Piecewise(Block):
The first range (-inf, x0) applies `fun_0`, and
the last range (x_{n-1}, +inf) applies the last function `fun_n`.
The function returns zero if no condition is met.
Parameters
----------
points : list, tuple
Expand Down Expand Up @@ -1837,7 +1831,7 @@ def define(self):
args.append(f'({self.funs[i]}, {self.u.name} <= {self.points[i]})')
args.append(f'({self.funs[i + 1]}, {self.u.name} > {self.points[-1]})')

args_comma = ', '.join(args)
args_comma = ', '.join(args) + ', (0, True)'
pw_fun = f'Piecewise({args_comma}, evaluate=False)'

self.y.v_str = pw_fun
Expand Down
41 changes: 34 additions & 7 deletions andes/core/discrete.py
Expand Up @@ -38,6 +38,9 @@ def __init__(self, name=None, tex_name=None, info=None, no_warn=False,
if not hasattr(self, 'export_flags_tex'):
self.export_flags_tex = []

self.input_list = [] # references to input variables
self.param_list = [] # references to parameters

self.x_set = list()
self.y_set = list() # NOT being used

Expand Down Expand Up @@ -265,6 +268,9 @@ def __init__(self, u, bound, equal=False, enable=True, name=None, tex_name=None,
self.export_flags = ['z0', 'z1']
self.export_flags_tex = ['z_0', 'z_1']

self.input_list.extend([self.u])
self.param_list.extend([self.bound])

self.has_check_var = True

def check_var(self, *args, **kwargs):
Expand Down Expand Up @@ -376,6 +382,9 @@ def __init__(self, u, lower, upper, enable=True,
self.export_flags.append('zi')
self.export_flags_tex.append('z_i')

self.input_list.extend([self.u])
self.param_list.extend([self.lower, self.upper])

if not self.no_lower:
self.export_flags.append('zl')
self.export_flags_tex.append('z_l')
Expand Down Expand Up @@ -737,9 +746,9 @@ def check_eq(self,
# logger.debug(f'AntiWindup for states {self.state.a[idx]}')

# Very important note:
# `System.fg_to_dae` is called after `System.l_update_eq`, which calls this function.
# Equation values set in `self.state.e` is collected by `System._e_to_dae`, while
# variable values are collected by the separate loop in `System.fg_to_dae`.
# The set equation values and variable values are collected by `System.fg_to_dae`:
# - Equation values is collected by `System._e_to_dae`,
# - Variable values are collected at the end of `System.fg_to_dae`.
# Also, equation values are processed in `TDS` for resetting the `q`.


Expand All @@ -760,7 +769,7 @@ class RateLimiter(Discrete):
"""

def __init__(self, u, lower, upper, enable=True,
no_lower=False, no_upper=False, lower_cond=None, upper_cond=None,
no_lower=False, no_upper=False, lower_cond=1, upper_cond=1,
name=None, tex_name=None, info=None):
Discrete.__init__(self, name=name, tex_name=tex_name, info=info)
self.u = u
Expand Down Expand Up @@ -801,6 +810,9 @@ def __init__(self, u, lower, upper, enable=True,
self.export_flags_tex.append('z_{ur}')
self.warn_flags.append(('zur', 'upper'))

self.param_list.extend([self.rate_lower, self.rate_upper,
self.rate_lower_cond, self.rate_upper_cond])

def check_eq(self, **kwargs):
if not self.enable:
return
Expand Down Expand Up @@ -864,6 +876,13 @@ class Selector(Discrete):
A potential bug when more than two inputs are provided, and values in different inputs are equal.
Only two inputs are allowed.
.. deprecated:: 1.5.9
Use of this class for comparison-based output is discouraged.
Instead, use `LessThan` and `Limiter` to construct piesewise equations.
See the new implementation of ``HVGate`` and ``LVGate``.
Examples
--------
Example 1: select the largest value between `v0` and `v1` and put it into vmax.
Expand All @@ -890,9 +909,6 @@ class Selector(Discrete):
--------
numpy.ufunc.reduce : NumPy reduce function
andes.core.block.HVGate
andes.core.block.LVGate
"""

def __init__(self, *args, fun, tex_name=None, info=None):
Expand All @@ -911,6 +927,8 @@ def __init__(self, *args, fun, tex_name=None, info=None):
self.export_flags = [f's{i}' for i in range(len(self.input_vars))]
self.export_flags_tex = [f's_{i}' for i in range(len(self.input_vars))]

self.input_list = args

self.has_check_var = True

def check_var(self, *args, **kwargs):
Expand Down Expand Up @@ -986,6 +1004,7 @@ def __init__(self, u, options: Union[list, Tuple], info: str = None,

self.export_flags = [f's{i}' for i in range(len(options))]
self.export_flags_tex = [f's_{i}' for i in range(len(options))]
self.input_list.extend([self.u])

self.has_check_var = True

Expand Down Expand Up @@ -1076,6 +1095,8 @@ def __init__(self, u, center, lower, upper,

self.center = dummify(center) # CURRENTLY NOT IN USE

self.param_list.extend([self.center])

def check_var(self, *args, **kwargs):
"""
Notes
Expand Down Expand Up @@ -1211,6 +1232,8 @@ def __init__(self, u, mode='step', delay=0,
self.delay = delay
self.export_flags = ['v']
self.export_flags_tex = ['v']
self.input_list.extend([u])

self.has_check_var = True

self.t = np.array([0])
Expand Down Expand Up @@ -1335,6 +1358,8 @@ def __init__(self, u, interval=1.0, offset=0.0, name=None, tex_name=None, info=N

self.export_flags = ['v']
self.export_flags_tex = ['v']
self.input_list.extend([self.u])

self.has_check_var = True

self.v = np.array([0])
Expand Down Expand Up @@ -1439,6 +1464,8 @@ def __init__(self, *, v, lower, upper, bsw, gsw, dt, u, enable=True,
self.err_tol = err_tol

self.has_check_var = True
self.input_list.extend([self.v])
self.param_list.extend([self.lower, self.upper, self.u])

self.t_last = None
self.t_enable = None
Expand Down
6 changes: 4 additions & 2 deletions andes/core/model.py
Expand Up @@ -244,8 +244,10 @@ def add(self, **kwargs):
idx = kwargs['idx']
self.uid[idx] = self.n
self.n += 1
if "name" in self.params and kwargs.get("name") is None:
kwargs["name"] = idx
if "name" in self.params:
name = kwargs.get("name")
if (name is None) or (not isinstance(name, str) and np.isnan(name)):
kwargs["name"] = idx

if "idx" not in self.params:
kwargs.pop("idx")
Expand Down
3 changes: 3 additions & 0 deletions andes/core/symprocessor.py
Expand Up @@ -64,6 +64,9 @@ def broadcastcond(cond):
printer._print(sympy.S.NaN))


# the line below caches Piecewise instances
sympy.OldPiecewise = sympy.Piecewise

sympy.Piecewise = FixPiecewise


Expand Down
10 changes: 5 additions & 5 deletions andes/main.py
Expand Up @@ -26,7 +26,7 @@

import andes
from andes.routines import routine_cli
from andes.shared import Pool, Process, coloredlogs, unittest
from andes.shared import Pool, Process, coloredlogs, unittest, NCPUS_PHYSICAL
from andes.system import System
from andes.utils.misc import elapsed, is_interactive
from andes.utils.paths import get_config_path, get_log_dir, tests_root
Expand Down Expand Up @@ -490,7 +490,7 @@ def find_log_path(lg):
return out


def _run_multiprocess_proc(cases, ncpu=os.cpu_count(), **kwargs):
def _run_multiprocess_proc(cases, ncpu=NCPUS_PHYSICAL, **kwargs):
"""
Run multiprocessing with `Process`.
Expand All @@ -515,7 +515,7 @@ def _run_multiprocess_proc(cases, ncpu=os.cpu_count(), **kwargs):
return True


def _run_multiprocess_pool(cases, ncpu=os.cpu_count(), verbose=logging.INFO, **kwargs):
def _run_multiprocess_pool(cases, ncpu=NCPUS_PHYSICAL, verbose=logging.INFO, **kwargs):
"""
Run multiprocessing jobs using Pool.
Expand All @@ -539,7 +539,7 @@ def _run_multiprocess_pool(cases, ncpu=os.cpu_count(), verbose=logging.INFO, **k
return ret


def run(filename, input_path='', verbose=20, mp_verbose=30, ncpu=os.cpu_count(), pool=False,
def run(filename, input_path='', verbose=20, mp_verbose=30, ncpu=NCPUS_PHYSICAL, pool=False,
cli=False, codegen=False, shell=False, **kwargs):
"""
Entry point to run ANDES routines.
Expand Down Expand Up @@ -724,7 +724,7 @@ def prepare(quick=False, incremental=False, models=None,

cli = kwargs.get("cli", False)
full = kwargs.get("full", False)
ncpu = kwargs.get("ncpu", os.cpu_count())
ncpu = kwargs.get("ncpu", NCPUS_PHYSICAL)

if cli is True:
if not full:
Expand Down
7 changes: 5 additions & 2 deletions andes/models/__init__.py
Expand Up @@ -31,13 +31,16 @@
'ESAC1A', 'ESST1A']),
('pss', ['IEEEST', 'ST2CUT']),
('motor', ['Motor3', 'Motor5']),
('measurement', ['BusFreq', 'BusROCOF', 'PMU']),
('measurement', ['BusFreq', 'BusROCOF', 'PMU', 'PLL1']),
('dc', ['Node', 'Ground', 'R', 'L', 'C', 'RCp', 'RCs', 'RLs', 'RLCs', 'RLCp']),
('acdc', ['VSCShunt']),
('renewable', ['REGCA1', 'REECA1', 'REECA1E', 'REECA1G',
'REPCA1', 'WTDTA1', 'WTDS', 'WTARA1', 'WTPTA1', 'WTTQA1', 'WTARV1',
'REGCVSG', 'REGCVSG2']),
'REGCV1', 'REGCV2']),
('distributed', ['PVD1', 'ESD1', 'EV1', 'EV2', 'DGPRCT1', 'DGPRCTExt']),
('coi', ['COI']),
# ('experimental', ['PI2', 'TestDB1', 'TestPI', 'TestLagAWFreeze', 'FixedGen']),
])


model_aliases = {"REGCVSG": "REGCV1", "REGCVSG2": "REGCV2"}
3 changes: 2 additions & 1 deletion andes/models/measurement/__init__.py
Expand Up @@ -4,4 +4,5 @@

from andes.models.measurement.busfreq import BusFreq # noqa
from andes.models.measurement.busrocof import BusROCOF # noqa
from andes.models.measurement.pmu import PMU # noqa
from andes.models.measurement.pmu import PMU # noqa
from andes.models.measurement.pll import PLL1 # noqa

0 comments on commit 9281c39

Please sign in to comment.