Source code for pyramses.simulator

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Python module for RAMSES dynamic simulator. It provides an interface through Python to
perform dynamic simulations and extract data from RAMSES."""

import ctypes
import _ctypes
import os
import sys
import warnings
import datetime
import numpy as np
from scipy.sparse import coo_matrix

from .cases import cfg
from .globals import RAMSESError, CustomWarning, __libdir__, wrapToList

[docs]class sim(object): """Simulation class.""" warnings.showwarning = CustomWarning ramsesCount = 0 # Provides a sum of all instances of Ramses running os.environ[ "KMP_DUPLICATE_LIB_OK"] = "TRUE" # This allows to run even if 2 versions of MKL are present on the computer # print(__libdir__) # print(os.path.join(__libdir__,"ramses.dll")) def __init__(self, custLibDir = None): """Initialize the DLL libraries.""" if custLibDir is None: ramLibDir = __libdir__ else: try: if os.path.exists(custLibDir) and os.path.isdir(custLibDir): ramLibDir = custLibDir warnings.warn("Overwriting the internal DLL with the one at %s. The DLL in that location will be locked. To unlock it, you need to del() this instance of pyramses.sim() or restart the kernel." % ramLibDir) else: raise RAMSESError('RAMSES: The path %s does not exist or it is not a directory.' % (custLibDir)) except OSError as e: raise RAMSESError('RAMSES: The path %s gave an error: ' % (custLibDir), e) try: # print(sys.platform) if sys.platform in ('win32', 'cygwin'): self._ramseslib = ctypes.CDLL(os.path.join(ramLibDir, "ramses.dll")) else: # if (not find_library('iomp5')): # self._omplib = ctypes.CDLL(os.path.join(__libdir__, "libiomp5.so"), mode=ctypes.RTLD_GLOBAL) # self._mkllib = ctypes.CDLL(os.path.join(__libdir__, "libmkl.so"), mode=ctypes.RTLD_GLOBAL) self._ramseslib = ctypes.CDLL(os.path.join(ramLibDir, "ramses.so")) except OSError as e: raise ImportError('RAMSES: ', e) sim.ramsesCount += 1 self._ramsesNum = sim.ramsesCount # This is the current instance of Ramses self._setcalls() def __del__(self): warnings.warn("Simulator with number %i was deleted." % self._ramsesNum) if sys.platform in ('win32', 'cygwin'): _ctypes.FreeLibrary(self._ramseslib._handle) else: _ctypes.dlclose(self._ramseslib._handle) sim.ramsesCount -= 1 def _c_func_wrapper(self, cdecl_text): """Read the ramses.h file and sets the necessary call types for Python.""" def move_pointer_and_strip(type_def, name): if '*' in name: type_def += ' ' + name[:name.rindex('*') + 1] name = name.rsplit('*', 1)[1] return type_def.strip(), name.strip() def type_lookup(type_def): '''Supported C variable types and their ctypes equivalents.''' types = { 'void': None, 'char *': ctypes.c_char_p, 'int': ctypes.c_int, 'int *': ctypes.POINTER(ctypes.c_int), 'void *': ctypes.c_void_p, 'size_t': ctypes.c_size_t, 'size_t *': ctypes.POINTER(ctypes.c_size_t), 'double': ctypes.c_double, 'double *': ctypes.POINTER(ctypes.c_double) } type_def_without_const = type_def.replace('const ', '') if type_def_without_const in types: return types[type_def_without_const] elif (type_def_without_const.endswith('*') and type_def_without_const[:-1] in types): return ctypes.POINTER(types[type_def_without_const[:-1]]) else: raise KeyError(type_def) a, b = [i.strip() for i in cdecl_text.split('(', 1)] params, _ = b.rsplit(')', 1) rtn_type, name = move_pointer_and_strip(*a.rsplit(' ', 1)) param_spec = [] for param in params.split(','): if param != 'void': param_spec.append(move_pointer_and_strip(*param.rsplit(' ', 1))) try: func = getattr(self._ramseslib, name) # get the function from the dll setattr(func, 'restype', type_lookup(rtn_type)) # set the return type setattr(func, 'argtypes', [type_lookup(type_def) for type_def, _ in param_spec]) # set the argument types except AttributeError as e: #raise AttributeError( # 'RAMSES: Function %s is listed in ramses.h but cannot be found in the library.' % (name), e) warnings.warn('RAMSES: Function %s is listed in ramses.h but cannot be found in the library.' % (name)) print(e) def _setcalls(self): """Define the argument types and returning types for the routines in RAMSES""" try: with open(os.path.join(__libdir__, "ramses.h"), 'r') as f: _C_HEADER = f.read() for cdecl_text in _C_HEADER.splitlines(): if cdecl_text.strip(): if not cdecl_text.startswith("//"): self._c_func_wrapper(cdecl_text) except IOError as e: raise IOError("RAMSES: Cannot open ramses.h files", e)
[docs] def getLastErr(self): """Return the last error message issued by RAMSES. :rtype: str :Example: >>> import pyramses >>> ram = pyramses.sim() >>> case = pyramses.cfg("cmd.txt") >>> ram.execSim(case, 0) # start simulation paused >>> ram.getLastErr() 'This is an error msg' """ errMsg = ctypes.create_string_buffer(1024) try: retval = self._ramseslib.get_last_err_log(errMsg) except KeyError: retval = 1 if (retval != 0): raise RAMSESError('RAMSES: Function getLastErr failed.') return errMsg.value.decode()
[docs] def getJac(self): """Gets the Jacobian matrix written in files :Example: >>> import pyramses >>> ram = pyramses.sim() >>> case = pyramses.cfg("cmd.txt") >>> ram.execSim(case, 0) # start simulation paused >>> ram.getJac() """ try: retval = self._ramseslib.get_Jac() except KeyError: retval = 1 if (retval != 0) and (retval != 112): raise RAMSESError('RAMSES: Function get_Jac failed.') Nmat = 0 try: f = open('py_eqs.dat','r') lines = f.readlines() f.close() rowl = [] coll = [] datal = [] for x in lines: xsplit = x.split() if int(xsplit[0]) > Nmat: Nmat = int(xsplit[0]) if int(xsplit[5]) > 0: rowl.append(int(xsplit[0])-1) coll.append(int(xsplit[5])-1) datal.append(1) row = np.array( rowl, dtype=int ) col = np.array( coll, dtype=int ) data = np.array( datal, dtype=float ) E = coo_matrix((data,(row,col)), shape=(Nmat,Nmat)).tocsc() except: raise RAMSESError('RAMSES: Function get_Jac failed while reading E.') try: f = open('py_val.dat','r') lines = f.readlines() f.close() row = np.array( [ int(x.split()[0])-1 for x in lines ], dtype=int ) col = np.array( [ int(x.split()[1])-1 for x in lines ], dtype=int ) data = np.array( [ x.split()[2] for x in lines ], dtype=float ) A = coo_matrix((data,(row,col)), shape=(Nmat,Nmat)).tocsc() except: raise RAMSESError('RAMSES: Function get_Jac failed while reading A.') return A, E
[docs] def getCompName(self, comp_type, num): """Return the name of the num:superscript:`th` component of type comp_type. :param str comp_type: the component type (BUS, SYNC, INJ, DCTL, BRANCH, TWOP, SHUNT, LOAD) :param int num: The number of the component to be fetched :returns: The component name :rtype: srt :Example: >>> import pyramses >>> ram = pyramses.sim() >>> case = pyramses.cfg("cmd.txt") >>> ram.execSim(case, 0) # start simulation paused >>> ram.getCompName("BUS",1) 'B1' """ get_name_func = { 'BUS': self._ramseslib.get_bus_name, 'SYNC': self._ramseslib.get_sync_name, 'INJ': self._ramseslib.get_inj_name, 'DCTL': self._ramseslib.get_dctl_name, 'BRANCH': self._ramseslib.get_branch_name, 'TWOP': self._ramseslib.get_twop_name, 'SHUNT': self._ramseslib.get_shunt_name, 'LOAD': self._ramseslib.get_load_name } name = ctypes.create_string_buffer(21) try: retval = get_name_func[comp_type](num, name) except KeyError: retval = 1 if (retval != 0): raise RAMSESError( 'RAMSES: Function getCompName(%s,%i) failed. Does this component exist?' % (comp_type, num)) return name.value.decode()
[docs] def getAllCompNames(self, comp_type): """Get list of all components of type comp_type :param str comp_type: the component type (BUS, SYNC, INJ, DCTL, BRANCH, TWOP, SHUNT, LOAD) :returns: list of component names :rtype: list of str :Example: >>> import pyramses >>> ram = pyramses.sim() >>> case = pyramses.cfg("cmd.txt") >>> ram.execSim(case, 0) # start simulation paused >>> ram.getAllCompNames("BUS") ['B1', 'B2', 'B3'] """ get_nb_func = { 'BUS': self._ramseslib.get_nbbus, 'SYNC': self._ramseslib.get_nbsync, 'INJ': self._ramseslib.get_nbinj, 'DCTL': self._ramseslib.get_nbdctl, 'BRANCH': self._ramseslib.get_nbbra, 'TWOP': self._ramseslib.get_nbtwop, 'SHUNT': self._ramseslib.get_nbshunt, 'LOAD': self._ramseslib.get_nbload } try: Nb = get_nb_func[comp_type]() except KeyError: raise RAMSESError( 'RAMSES: Function getAllCompName(%s) failed. Does this component type exists?' % (comp_type)) names = [] if Nb > 0: for comp in range(1, Nb + 1): names.append(self.getCompName(comp_type, comp)) return names
[docs] def execSim(self, cmd, pause=None): """Run a simulation. :param cmd: provides the case description :type cmd: type(:class:`.cfg`) :param t_pause: pause time (optional). If not given, the simulation will run until the end as described in the dst file. :type t_pause: float :Example: >>> import pyramses >>> ram = pyramses.sim() >>> case = pyramses.cfg("cmd.txt") >>> ram.execSim(case) # start simulation .. note:: If you have an existing command file, you can pass it to the simulator as pyramses.cfg("cmd.txt") """ if not isinstance(cmd, cfg): raise TypeError('RAMSES: Function execSim because the command file is not of type pyramses.cfg()') if pause is not None: self.pauseSim(pause) cmdfilename = cmd.writeCmdFile() if not cmd._out: outfilename = os.path.join(os.getcwd(),'output '+datetime.datetime.now().strftime("%d.%m.%Y-%H.%M.%S")+'.trace') else: outfilename = cmd._out[0] retval = self._ramseslib.ramses(cmdfilename.encode('utf-8'), outfilename.encode('utf-8')) if (retval != 0) and (retval != 112): raise RAMSESError('RAMSES: Function execSim() failed with the flag %i. Last message was: %s' % (retval, self.getLastErr())) return 0
[docs] def contSim(self, pause=None): """Continue the simulation until the given time. The pause argument is optional and it gives the time until the simulation will stop.""" if pause is not None: self.pauseSim(pause) retval = self._ramseslib.continue_simul() if (retval != 0) and (retval != 112): raise RAMSESError('RAMSES: Function contSim() failed with the flag %i. Last message was: %s' % (retval, self.getLastErr())) return 0
[docs] def getBusVolt(self, busNames): """Return the voltage magnitude of a list of buses :param busNames: the names of buses :type busNames: list of str :returns: list of bus voltage magnitudes :rtype: list of floats :Example: >>> import pyramses >>> ram = pyramses.sim() >>> case = pyramses.cfg("cmd.txt") >>> ram.execSim(case, 10.0) # simulate until 10 seconds and pause >>> buses = ['g1','g2','g3'] >>> ram.getBusVolt(buses) [1.0736851673414456, 1.0615442362180327, 1.064702686997689] """ volts = [] bus_volt = ctypes.c_double() for bus in busNames: retval = self._ramseslib.get_volt_mag(bus.encode('utf-8'), bus_volt) if (retval != 0): raise RAMSESError( 'RAMSES: Function getBusVolt(%s) failed with the flag %i. Does the bus exist? Last message was: %s' % (bus, retval, self.getLastErr())) volts.append(bus_volt.value) return volts
[docs] def getBranchPow(self, branchName): """Return the active and reactive powers of a list of branches :param branchName: the names of branches :type branchName: list of str :returns: list of branch powers. These are active and reactive power at the origin and extremity respectively (p_orig, q_orig, p_extr, q_extr) :rtype: list of floats :Example: >>> import pyramses >>> ram = pyramses.sim() >>> case = pyramses.cfg("cmd.txt") >>> ram.execSim(case, 10.0) # simulate until 10 seconds and pause >>> branchName = ['1011-1013','1012-1014','1021-1022'] >>> ram.getBranchPow(branchName) """ pows = [] p_orig = ctypes.c_double() q_orig = ctypes.c_double() p_extr = ctypes.c_double() q_extr = ctypes.c_double() for branch in branchName: retval = self._ramseslib.get_line_pow(branch.encode('utf-8'), p_orig, q_orig, p_extr, q_extr) if (retval != 0): raise RAMSESError( 'RAMSES: Function get_line_pow(%s) failed with the flag %i. Does the branch exist? Last message was: %s' % (branch, retval, self.getLastErr())) thisBranch = [p_orig.value, q_orig.value, p_extr.value, q_extr.value] pows.append(thisBranch) return pows
[docs] def getBranchCur(self, branchName): """Return the currents of a list of branches :param branchName: the names of branches :type branchName: list of str :returns: list of branch currents. These are x-y components at the origin and extremity respectively (ix_orig, iy_orig, ix_extr, iy_extr) :rtype: list of floats :Example: >>> import pyramses >>> ram = pyramses.sim() >>> case = pyramses.cfg("cmd.txt") >>> ram.execSim(case, 10.0) # simulate until 10 seconds and pause >>> branchName = ['1011-1013','1012-1014','1021-1022'] >>> ram.getBranchCur(branchName) """ curs = [] ix_orig = ctypes.c_double() iy_orig = ctypes.c_double() ix_extr = ctypes.c_double() iy_extr = ctypes.c_double() for branch in branchName: retval = self._ramseslib.get_line_cur(branch.encode('utf-8'), ix_orig, iy_orig, ix_extr, iy_extr) if (retval != 0): raise RAMSESError( 'RAMSES: Function get_line_cur(%s) failed with the flag %i. Does the branch exist? Last message was: %s' % (branch, retval, self.getLastErr())) thisBranch = [ix_orig.value, iy_orig.value, ix_extr.value, iy_extr.value] curs.append(thisBranch) return curs
[docs] def getBusPha(self, busNames): """Return the voltage phase of a list of buses :param busNames: the names of buses :type busNames: list of str :returns: list of bus voltage phase :rtype: list of floats :Example: >>> import pyramses >>> ram = pyramses.sim() >>> case = pyramses.cfg("cmd.txt") >>> ram.execSim(case, 10.0) # simulate until 10 seconds and pause >>> buses = ['g1','g2','g3'] >>> ram.getBusPha(buses) [0.0000000000000000, 10.0615442362180327, 11.064702686997689] """ pha = [] bus_pha = ctypes.c_double() for bus in busNames: retval = self._ramseslib.get_volt_pha(bus.encode('utf-8'), bus_pha) if (retval != 0): raise RAMSESError( 'RAMSES: Function getBusPha(%s) failed with the flag %i. Does the bus exist? Last message was: %s' % (bus, retval, self.getLastErr())) pha.append(bus_pha.value) return pha
[docs] def endSim(self): """End the simulation""" self._ramseslib.set_end_simul() return self.contSim(self.getInfTime())
[docs] def getEndSim(self): """Check if the simulation has ended :returns: 0 -> simulation is still working, 1 -> simulation has ended :rtype: integer """ return self._ramseslib.get_end_simul()
[docs] def getSimTime(self): """Get the current simulation time :returns: current simulation time in RAMSES. :rtype: float """ return self._ramseslib.get_sim_time()
[docs] def getInfTime(self): """Get the maximum representable double from the simulator () :returns: maximum representable double :rtype: float """ return self._ramseslib.get_huge_double()
[docs] def initObserv(self,traj_filenm): """Initialize observable selection (structure and trajectory file) :param traj_filenm: the file to save the trajectory at :type traj_filenm: str :Example: >>> import pyramses >>> ram = pyramses.sim() >>> case = pyramses.cfg("cmd.txt") # command file without any observables >>> ram.execSim(case, 0.0) # start >>> traj_filenm = 'obs.trj' >>> ram.initObserv(traj_filenm) """ return self._ramseslib.initObserv(traj_filenm.encode('utf-8'))
[docs] def addObserv(self,string): """Add an element to be observed :param string: the element with proper format :type string: str :Example: >>> import pyramses >>> ram = pyramses.sim() >>> case = pyramses.cfg("cmd.txt") # command file without any observables >>> ram.execSim(case, 0.0) # start >>> traj_filenm = 'obs.trj' >>> ram.initObserv(traj_filenm) >>> string = 'BUS *' # monitor all buses >>> ram.addObserv(string) """ return self._ramseslib.addObserv(string.encode('utf-8'))
[docs] def finalObserv(self): """Finalize observable selection, allocate buffer, and write header of trajectory file :Example: >>> import pyramses >>> ram = pyramses.sim() >>> case = pyramses.cfg("cmd.txt") # command file without any observables >>> ram.execSim(case, 0.0) # start >>> traj_filenm = 'obs.trj' >>> ram.initObserv(traj_filenm) >>> string = 'BUS *' # monitor all buses >>> ram.addObserv(string) >>> ram.finalObserv() """ return self._ramseslib.finalObserv()
[docs] def getPrm(self, comp_type, comp_name, prm_name): """Get the value of a named parameter :param comp_type: the types of components (EXC, TOR, INJ, DCTL, TWOP) :type comp_type: list of str :param comp_name: the names of components :type comp_name: list of str :param prm_name: the names of parameters :type prm_name: list of str :returns: list of parameter values :rtype: list of floats :Example: >>> import pyramses >>> ram = pyramses.sim() >>> case = pyramses.cfg("cmd.txt") >>> ram.execSim(case, 10.0) # simulate until 10 seconds and pause >>> comp_type = ['EXC','EXC','EXC'] >>> comp_name = ['g1','g2','g3'] >>> prm_name = ['V0','V0','V0'] >>> ram.getPrm(comp_type,comp_name, prm_name) [1.0736851673414456, 1.0615442362180327, 1.064702686997689] """ comp_type = wrapToList(comp_type) comp_name = wrapToList(comp_name) prm_name = wrapToList(prm_name) if not (len(comp_type) == len(comp_name) == len(prm_name)): raise ValueError('RAMSES: Function getPrm failed because the lists are not equal!') prm_values = [] for a, b, c in zip(comp_type, comp_name, prm_name): prm_value = ctypes.c_double() retval = self._ramseslib.get_named_prm(a.encode('utf-8'), b.encode('utf-8'), c.encode('utf-8'), prm_value) if retval != 0: raise RAMSESError( 'RAMSES: Function getPrm(%s,%s,%s) failed with the flag %i. Does the parameter or equipment exist? Last message was: %s' % (a, b, c, retval, self.getLastErr())) prm_values.append(prm_value.value) if len(prm_values) == 1: return prm_values[0] else: return prm_values
[docs] def defineSS(self, ssID, filter1, filter2, filter3): """Define a subsytem using three filters. The resulting list is an intersection of the filters. :param ssID: Number of the SS :type ssID: int :param filter1: Voltage levels to be included :type filter1: list of str or str :param filter2: Zones (which zone/zones will be included) :type filter2: list of str or str :param filter3: Bus names to be included :type filter3: list of str or str :Example: >>> import pyramses >>> ram = pyramses.sim() >>> case = pyramses.cfg("cmd.txt") >>> ram.execSim(case, 0.0) >>> ram.defineSS(1, ['735'], [], []) # SS 1 with all buses at 735 kV, no zones, no list of buses .. note:: An empty filter means it is deactivated and discarded. """ filter1 = wrapToList(filter1) filter2 = wrapToList(filter2) filter3 = wrapToList(filter3) strF1 = ' '.join(filter1) strF2 = ' '.join(filter2) strF3 = ' '.join(filter3) retval = self._ramseslib.define_SS(ctypes.c_int(ssID), strF1.encode('utf-8'), ctypes.c_int(len(filter1)), strF2.encode('utf-8'), ctypes.c_int(len(filter2)), strF3.encode('utf-8'), ctypes.c_int(len(filter3))) if retval != 0: raise RAMSESError('RAMSES: Function define_SS(%i,...) failed with the flag %i. Last message was: %s' % (ssID, retval, self.getLastErr()))
[docs] def getSS(self, ssID): """Retrieve the buses of a subsytem. :param ssID: Number of the SS :type ssID: int :returns: list of buses :rtype: list of str :Example: >>> import pyramses >>> ram = pyramses.sim() >>> case = pyramses.cfg("cmd.txt") >>> ram.execSim(case, 0.0) >>> ram.defineSS(1, ['735'], [], []) # SS 1 with all buses at 735 kV >>> ram.getSS(1) # get list of buses in SS 1 """ mxreclen = self._ramseslib.get_nbbus() string_buffer = ctypes.create_string_buffer(19 * mxreclen) retval = self._ramseslib.get_SS(ctypes.c_int(ssID), ctypes.c_int(mxreclen), string_buffer) if retval != 0: raise RAMSESError('RAMSES: Function getSS(%i) failed with the flag %i. Last message was: %s' % (ssID, retval, self.getLastErr())) return string_buffer.value.split()
[docs] def getTrfoSS(self, ssID, location, in_service, rettype): """Retrieve transformer information of subsystem after applying some filters :param ssID: Number of the SS :type ssID: int :param location: 1 – both buses inside SS, 2 - tie transformers, 3 – 1 & 2 :type location: int :param in_service: 1 – transformers in service, 2 - all transformers :type in_service: int :param rettype: Type of response (NAME, From, To, Status, Tap, Currentf, Currentt, Pf, Qf, Pt, Qt). :type rettype: str :returns: list of transformer names :rtype: list of str :Example: >>> import pyramses >>> ram = pyramses.sim() >>> case = pyramses.cfg("cmd.txt") >>> ram.execSim(case, 0.0) >>> ram.defineSS(1, ['735'], [], []) # SS 1 with all buses at 735 kV >>> ram.getTrfoSS(1,3,2,'Status') .. note:: Tap is not implemented yet. .. todo:: Implement Taps after discussing with Lester. """ if rettype not in ['NAME', 'From', 'To', 'Status', 'Tap', 'Currentf', 'Currentt', 'Pf', 'Qf', 'Pt', 'Qt']: raise RAMSESError('RAMSES: Function getTrfoSS(%i,%i,%i,%s): rettype is not valid!' % ( ssID, location, in_service, rettype)) elif location not in [1, 2, 3]: raise RAMSESError('RAMSES: Function getTrfoSS(%i,%i,%i,%s): location is not valid!' % ( ssID, location, in_service, rettype)) elif in_service not in [1, 2]: raise RAMSESError('RAMSES: Function getTrfoSS(%i,%i,%i,%s): in_service is not valid!' % ( ssID, location, in_service, rettype)) mxreclen = self._ramseslib.get_nbbra() string_buffer = ctypes.create_string_buffer(21 * mxreclen) dp_vec = (ctypes.c_double * mxreclen)() dp_int = (ctypes.c_int * mxreclen)() elem = ctypes.c_int() retval = self._ramseslib.get_transformer_in_SS(ctypes.c_int(ssID), ctypes.c_int(location), ctypes.c_int(in_service), rettype.encode('utf-8'), ctypes.c_int(mxreclen), string_buffer, dp_vec, dp_int, elem) if retval != 0: raise RAMSESError('RAMSES: Function getTrfoSS(%i,%i,%i,%s) failed with the flag %i.' % ( ssID, location, in_service, rettype, retval)) if elem == 0: return [] elif rettype in ['Tap', 'Status']: return [dp_int[i] for i in range(0, elem.value)] elif rettype in ['Currentf', 'Currentt', 'Pf', 'Qf', 'Pt', 'Qt']: return [dp_vec[i] for i in range(0, elem.value)] else: return string_buffer.value.split()
[docs] def getPrmNames(self, comp_type, comp_name): """Get the named parameters of a model :param comp_type: the types of components (EXC, TOR, INJ, DCTL, TWOP) :type comp_type: list of str or str :param comp_name: the names of component instances :type comp_name: list of str or str :returns: list of parameter names :rtype: list of lists of strings :Example: >>> import pyramses >>> ram = pyramses.sim() >>> case = pyramses.cfg("cmd.txt") >>> ram.execSim(case, 0.0) # initialize and wait >>> comp_type = ['EXC','EXC','EXC'] >>> comp_name = ['g1','g2','g3'] # name of synchronous machines >>> ram.getPrmNames(comp_type,comp_name) """ comp_type = wrapToList(comp_type) comp_name = wrapToList(comp_name) if not (len(comp_type) == len(comp_name)): raise ValueError('RAMSES: Function getPrmNames failed because the lists are not equal!') prm_names = [] mxprm = self._ramseslib.get_mxprm() # get maximum number of parameters in any model for a, b in zip(comp_type, comp_name): string_buffer = ctypes.create_string_buffer(11 * mxprm) retval = self._ramseslib.get_comp_prm_names(a.encode('utf-8'), b.encode('utf-8'), ctypes.c_int(mxprm), string_buffer) if retval != 0: raise RAMSESError( 'RAMSES: Function getPrm(%s,%s) failed with the flag %i. Does the parameter or equipment exist?' % (a, b, retval)) decodedstring = string_buffer.value.decode() prm_names.append(decodedstring.split()) if len(prm_names) == 1: return prm_names[0] else: return prm_names
[docs] def getObs(self, comp_type, comp_name, obs_name): """Get the value of a named observable. :param comp_type: the types of components ('EXC','TOR','INJ','TWOP','DCTL','SYN') :type comp_type: list of str :param comp_name: the names of components :type comp_name: list of str :param obs_name: the names of observables :type obs_name: list of str :returns: list of observable values :rtype: list of floats .. note:: For the synchronous generator ('SYN') the accepted obs_name values are - 'P': Active power (MW) - 'Q': Reactive power (MVAr) -'Omega': Machine speed (pu) - 'S': Apparent power (MVA) - 'SNOM': Nominal apparent power (MVA) - 'PNOM': Nominal active power (MW) :Example: >>> import pyramses >>> ram = pyramses.sim() >>> case = pyramses.cfg("cmd.txt") >>> ram.execSim(case, 10.0) # simulate until 10 seconds and pause >>> comp_type = ['INJ','EXC','TOR'] >>> comp_name = ['L_11','g2','g3'] >>> obs_name = ['P','vf','Pm'] >>> ram.getObs(comp_type,comp_name, obs_name) [199.73704732259995, 1.3372945282585218, 0.816671075203357] """ comp_type = wrapToList(comp_type) comp_name = wrapToList(comp_name) obs_name = wrapToList(obs_name) if not (len(comp_type) == len(comp_name) == len(obs_name)): raise ValueError('RAMSES: Function getObs failed because the lists are not equal!') obs_values = [] for a, b, c in zip(comp_type, comp_name, obs_name): obs_value = ctypes.c_double() retval = self._ramseslib.get_named_obs(a.encode('utf-8'), b.encode('utf-8'), c.encode('utf-8'), obs_value) if retval != 0: raise RAMSESError( 'RAMSES: Function getObs(%s,%s,%s) failed with the flag %i. Does the observable or equipment exist?' % (a, b, c, retval)) obs_values.append(obs_value.value) return obs_values
[docs] def pauseSim(self, t_pause): """Pause the simulation at the t_pause time :param t_pause: pause time :type t_pause: float """ return self._ramseslib.set_pause_time(t_pause)
[docs] def addDisturb(self, t_dist, disturb): """Add a new disturbance at a specific time. Follows the same structure as the disturbances in the dst files. :param t_dist: time of the disturbance :type t_dist: float :param disturb: description of disturbance :type disturb: str :Example: >>> import pyramses >>> ram = pyramses.sim() >>> case = pyramses.cfg("cmd.txt") >>> ram.execSim(case, 80.0) # simulate until 80 seconds and pause >>> ram.addDisturb(100.000, 'CHGPRM DCTL 1-1041 Vsetpt -0.05 0') # Decrease the setpoint of the DCTL by 0.015 pu, at t=100 s >>> ram.addDisturb(100.000, 'CHGPRM DCTL 2-1042 Vsetpt -0.05 0') >>> ram.addDisturb(100.000, 'CHGPRM DCTL 3-1043 Vsetpt -0.05 0') >>> ram.addDisturb(100.000, 'CHGPRM DCTL 4-1044 Vsetpt -0.05 0') >>> ram.addDisturb(100.000, 'CHGPRM DCTL 5-1045 Vsetpt -0.05 0') >>> ram.contSim(ram.getInfTime()) # continue the simulation """ return self._ramseslib.add_disturb(t_dist, disturb.encode('utf-8'))
[docs] def load_MDL(MDLName): """Load external DLL file with user defined models. Should be in current directory or absolute path. :param MDLName: path to file :type MDLName: str :Example: >>> import pyramses >>> ram = pyramses.sim() >>> ram = pyramses.load_MDL("MDLs.dll") >>> case = pyramses.cfg("cmd.txt") >>> ram.execSim(case) # simulate """ return self._ramseslib.c_load_MDL(MDLName.encode('utf-8'))
[docs] def unload_MDL(MDLName): """Unload external DLL file with user defined models. Should be in current directory or absolute path. :param MDLName: path to file :type MDLName: str :Example: >>> import pyramses >>> ram = pyramses.sim() >>> ram = pyramses.load_MDL("MDLs.dll") >>> case = pyramses.cfg("cmd.txt") >>> ram.execSim(case) # simulate >>> ram = pyramses.unload_MDL("MDLs.dll") """ return self._ramseslib.c_unload_MDL(MDLName.encode('utf-8'))
[docs] def get_MDL_no(): """Unload external DLL file with user defined models. Should be in current directory or absolute path. :returns: list of observable values :rtype: list of floats :Example: >>> import pyramses >>> ram = pyramses.sim() >>> ram = pyramses.load_MDL("MDLs.dll") >>> case = pyramses.cfg("cmd.txt") >>> ram.execSim(case) # simulate >>> ram = pyramses.get_MDL_no() """ return self._ramseslib.c_get_MDL_no()
#int get_MDL_names(int mxreclen, char *DLL_Names);