class System(object): """ New power system class """ def __init__(self, case: Optional[str] = None, name: Optional[str] = None, config_path: Optional[str] = None, options: Optional[Dict] = None, **kwargs): self.name = name self.options = {} if options is None else options if kwargs: self.options.update(kwargs) self.calls = OrderedDict() self.models = OrderedDict() self.groups = OrderedDict() self.programs = OrderedDict() self.switch_times = np.array([]) # get and load default config file self.config = Config(self.__class__.__name__) self._config_path = get_config_path( ) if not config_path else config_path self._config_from_file = self.load_config(self._config_path) self.config.load(self._config_from_file) # custom configuration for system goes after this line self.config.add( OrderedDict(( ('freq', 60), ('mva', 100), ('store_z', 0), ))) self.files = FileMan() self.files.set(case=case, **self.options) self.dae = DAE(system=self) # dynamic imports: routine import need to query model flags self._group_import() self._model_import() self._routine_import() self._models_with_flag = { 'pflow': self.get_models_with_flag('pflow'), 'tds': self.get_models_with_flag('tds'), 'pflow_and_tds': self.get_models_with_flag(('tds', 'pflow')), } # ------------------------------ # FIXME: reduce clutter with defaultdict `adders` and `setters`, each with `x`, `y`, `f`, and `g` self.f_adders, self.f_setters = list(), list() self.g_adders, self.g_setters = list(), list() self.x_adders, self.x_setters = list(), list() self.y_adders, self.y_setters = list(), list() self.antiwindups = list()
def edit_conf(edit_config: Optional[Union[str, bool]] = ''): """ Edit the Andes config file which occurs first in the search path. Parameters ---------- edit_config : bool If ``True``, try to open up an editor and edit the config file. Otherwise returns. Returns ------- bool ``True`` is a config file is found and an editor is opened. ``False`` if ``edit_config`` is False. """ ret = False # no `edit-config` supplied if edit_config == '': return ret conf_path = get_config_path() if conf_path is None: logger.info('Config file does not exist. Automatically saving.') system = System() conf_path = system.save_config() logger.info('Editing config file "%s"', conf_path) editor = '' if edit_config is not None: # use `edit_config` as default editor editor = edit_config else: # use the following default editors if platform.system() == 'Linux': editor = os.environ.get('EDITOR', 'vim') elif platform.system() == 'Darwin': editor = os.environ.get('EDITOR', 'vim') elif platform.system() == 'Windows': editor = 'notepad.exe' editor_cmd = editor.split() editor_cmd.append(conf_path) call(editor_cmd) ret = True return ret
def edit_conf(edit_config: Optional[Union[str, bool]] = ''): """ Edit the Andes config file which occurs first in the search path. Parameters ---------- edit_config : bool If ``True``, try to open up an editor and edit the config file. Otherwise returns. Returns ------- bool ``True`` is a config file is found and an editor is opened. ``False`` if ``edit_config`` is False. """ ret = False # no `edit-config` supplied if edit_config == '': return ret conf_path = get_config_path() if conf_path is not None: logger.info('Editing config file {}'.format(conf_path)) if edit_config is None: # use the following default editors if platform.system() == 'Linux': editor = os.environ.get('EDITOR', 'gedit') elif platform.system() == 'Darwin': editor = os.environ.get('EDITOR', 'vim') elif platform.system() == 'Windows': editor = 'notepad.exe' else: # use `edit_config` as default editor editor = edit_config call([editor, conf_path]) ret = True else: logger.info('Config file does not exist. Save config with \'andes ' '--save-config\'') ret = True return ret
class System(object): """ System contains models and routines for modeling and simulation. System contains a several special `OrderedDict` member attributes for housekeeping. These attributes include `models`, `groups`, `routines` and `calls` for loaded models, groups, analysis routines, and generated numerical function calls, respectively. Notes ----- System stores model and routine instances as attributes. Model and routine attribute names are the same as their class names. For example, `Bus` is stored at ``system.Bus``, the power flow calculation routine is at ``system.PFlow``, and the numerical DAE instance is at ``system.dae``. See attributes for the list of attributes. Attributes ---------- dae : andes.variables.dae.DAE Numerical DAE storage files : andes.variables.fileman.FileMan File path storage config : andes.core.Config System config storage models : OrderedDict model name and instance pairs groups : OrderedDict group name and instance pairs routines : OrderedDict routine name and instance pairs """ def __init__(self, case: Optional[str] = None, name: Optional[str] = None, config_path: Optional[str] = None, options: Optional[Dict] = None, **kwargs): self.name = name self.options = {} if options is not None: self.options.update(options) if kwargs: self.options.update(kwargs) self.calls = OrderedDict( ) # a dictionary with model names (keys) and their ``calls`` instance self.models = OrderedDict() # model names and instances self.groups = OrderedDict() # group names and instances self.routines = OrderedDict() # routine names and instances self.switch_times = np.array( []) # an array of ordered event switching times self.switch_dict = OrderedDict( ) # time: OrderedDict of associated models self.n_switches = 0 # number of elements in `self.switch_times` self.exit_code = 0 # command-line exit code, 0 - normal, others - error. # get and load default config file self._config_path = get_config_path() if config_path: self._config_path = config_path self._config_object = self.load_config(self._config_path) self.config = Config(self.__class__.__name__) self.config.load(self._config_object) # custom configuration for system goes after this line self.config.add( OrderedDict( (('freq', 60), ('mva', 100), ('store_z', 0), ('ipadd', 1), ('warn_limits', 1), ('warn_abnormal', 1), ('dime_enabled', 0), ('dime_name', 'andes'), ('dime_protocol', 'ipc'), ('dime_address', '/tmp/dime2')))) self.config.add_extra( "_help", freq='base frequency [Hz]', mva='system base MVA', store_z='store limiter status in TDS output', ipadd='Use spmatrix.ipadd if available', warn_limits='warn variables initialized at limits', warn_abnormal='warn initialization out of normal values', ) self.config.add_extra( "_alt", freq="float", mva="float", store_z=(0, 1), ipadd=(0, 1), warn_limits=(0, 1), warn_abnormal=(0, 1), ) self.config.check() self.exist = ExistingModels() self.files = FileMan(case=case, **self.options) # file path manager self.dae = DAE(system=self) # numerical DAE storage # dynamic imports of groups, models and routines self.import_groups() self.import_models() self.import_routines() # routine imports come after models self._getters = dict(f=list(), g=list(), x=list(), y=list()) self._adders = dict(f=list(), g=list(), x=list(), y=list()) self._setters = dict(f=list(), g=list(), x=list(), y=list()) self.antiwindups = list() # internal flags self.is_setup = False # if system has been setup
class System(object): """ The ANDES power system class. This class stores model and routine instances as attributes. Model and routine attribute names are the same as their class names. For example, the ``Bus`` instance of ``system`` is accessible at ``system.Bus``. """ def __init__(self, case: Optional[str] = None, name: Optional[str] = None, config_path: Optional[str] = None, options: Optional[Dict] = None, **kwargs ): self.name = name self.options = {} if options is not None: self.options.update(options) if kwargs: self.options.update(kwargs) self.calls = OrderedDict() # a dictionary with model names (keys) and their ``calls`` instance self.models = OrderedDict() # model names and instances self.groups = OrderedDict() # group names and instances self.routines = OrderedDict() # routine names and instances self.switch_times = np.array([]) # an array of ordered event switching times # get and load default config file self._config_path = get_config_path() if config_path: self._config_path = config_path self._config_object = self.load_config(self._config_path) self.config = Config(self.__class__.__name__) self.config.load(self._config_object) # custom configuration for system goes after this line self.config.add(OrderedDict((('freq', 60), ('mva', 100), ('store_z', 0), ('ipadd', 1), ))) self.config.add_extra("_help", freq='base frequency [Hz]', mva='system base MVA', store_z='store limiter status in TDS output', ipadd='Use spmatrix.ipadd if available', ) self.config.add_extra("_alt", freq="float", mva="float", store_z=(0, 1), ipadd=(0, 1), ) self.config.check() self.files = FileMan(case=case, **self.options) # file path manager self.dae = DAE(system=self) # numerical DAE storage # dynamic imports of groups, models and routines self._group_import() self._model_import() self._routine_import() # routine imports come after models self._models_flag = {'pflow': self.find_models('pflow'), 'tds': self.find_models('tds'), 'pflow_tds': self.find_models(('tds', 'pflow')), } self._adders = dict(f=list(), g=list(), x=list(), y=list()) self._setters = dict(f=list(), g=list(), x=list(), y=list()) self.antiwindups = list()