diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 76aa429b..31cc431c 100755 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -59,4 +59,4 @@ jobs: run: | rm src/pyfmi/__init__.py cp -rv src/pyfmi/tests/files tests - python3 -m nose --verbose tests/* + python3 -m nose --verbose tests/*.py diff --git a/setup.py b/setup.py index 99ece78b..cda00370 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,7 @@ import distutils import os import shutil -import numpy as N +import numpy as np import ctypes.util import sys @@ -244,9 +244,14 @@ def check_extensions(): compile_time_env=compile_time_env, compiler_directives={'language_level' : "3str"}) + # Test utilities + ext_list += cythonize([os.path.join("src", "pyfmi", "tests", "test_util.pyx")], + include_path = incl_path, + compiler_directives={'language_level' : "3str"}) + for i in range(len(ext_list)): - ext_list[i].include_dirs = [N.get_include(), "src", os.path.join("src", "pyfmi"), incdirs] + ext_list[i].include_dirs = [np.get_include(), "src", os.path.join("src", "pyfmi"), incdirs] ext_list[i].library_dirs = [libdirs] ext_list[i].language = "c" ext_list[i].libraries = ["fmilib_shared"] if sys.platform.startswith("win") else ["fmilib"] #If windows shared, else static diff --git a/src/common/__init__.py b/src/common/__init__.py index f7078232..7d2d2e27 100644 --- a/src/common/__init__.py +++ b/src/common/__init__.py @@ -21,25 +21,17 @@ __all__ = ['algorithm_drivers', 'core', 'diagnostics', 'io', 'plotting'] -import sys -python3_flag = True if sys.hexversion > 0x03000000 else False ## for backwards compatibility, to not break 'from pyfmi.common import diagnostics_prefix' ## TODO: Future: remove this from .diagnostics import DIAGNOSTICS_PREFIX as diagnostics_prefix -if python3_flag: - def encode(x): - if isinstance(x, str): - return x.encode() - else: - return x - def decode(x): - if isinstance(x, bytes): - return x.decode() - else: - return x -else: - def encode(x): +def encode(x): + if isinstance(x, str): + return x.encode() + else: return x - def decode(x): +def decode(x): + if isinstance(x, bytes): + return x.decode() + else: return x diff --git a/src/common/algorithm_drivers.py b/src/common/algorithm_drivers.py index fc69c50e..209abc86 100644 --- a/src/common/algorithm_drivers.py +++ b/src/common/algorithm_drivers.py @@ -18,11 +18,11 @@ Module containing optimization, simulation and initialization algorithms. """ -import numpy as N +import numpy as np default_int = int -int = N.int32 -N.int = N.int32 +int = np.int32 +np.int = np.int32 class AlgorithmBase(object): """ @@ -33,16 +33,20 @@ class AlgorithmBase(object): # __metaclass__=ABCMeta # @abstractmethod - def __init__(self, model, alg_args): pass + def __init__(self, model, alg_args): + pass # @abstractmethod - def solve(self): pass + def solve(self): + pass # @abstractmethod - def get_result(self): pass + def get_result(self): + pass @classmethod - def get_default_options(self): pass + def get_default_options(self): + pass class ResultBase(object): """ diff --git a/src/common/core.py b/src/common/core.py index b391d56e..0cfb3f52 100644 --- a/src/common/core.py +++ b/src/common/core.py @@ -20,12 +20,12 @@ import zipfile import tempfile -import platform as PL +import platform as plat import os import sys import shutil -import numpy as N +import numpy as np # location for temporary JModelica files def get_temp_location(): @@ -261,7 +261,7 @@ def get_platform_dir(): else: platform = 'linux' - if PL.architecture()[0].startswith('32'): + if plat.architecture()[0].startswith('32'): platform += '32' else: platform += '64' @@ -490,20 +490,20 @@ def __init__(self, abscissa, ordinate, tol=1e-8): """ self._abscissa = abscissa.astype('float') self._ordinate = ordinate - self._n = N.size(abscissa) - self._n_ordinate = N.size(self.ordinate,1) + self._n = np.size(abscissa) + self._n_ordinate = np.size(self.ordinate,1) self._x0 = abscissa[0] self._xf = abscissa[-1] - if not N.all(N.diff(self.abscissa) >= 0): + if not np.all(np.diff(self.abscissa) >= 0): raise Exception("The abscissae must be increasing.") - [double_point_indices] = N.nonzero(N.abs(N.diff(self.abscissa)) <= tol) + [double_point_indices] = np.nonzero(np.abs(np.diff(self.abscissa)) <= tol) while (len(double_point_indices) > 0): for i in double_point_indices: self.abscissa[i+1] = self.abscissa[i+1] + tol - [double_point_indices] = N.nonzero( - N.abs(N.diff(self.abscissa)) <= tol) + [double_point_indices] = np.nonzero( + np.abs(np.diff(self.abscissa)) <= tol) def eval(self,x): """ @@ -561,9 +561,9 @@ def eval(self,x): Two dimensional n x m matrix containing the ordinate values corresponding to the argument x. """ - y = N.zeros([N.size(x),self._n_ordinate]) + y = np.zeros([np.size(x),self._n_ordinate]) for i in range(self._n_ordinate): - y[:,i] = N.interp(x,self.abscissa,self.ordinate[:,i]) + y[:,i] = np.interp(x,self.abscissa,self.ordinate[:,i]) return y class TrajectoryLinearInterpolationExtrapolation(Trajectory): @@ -590,11 +590,11 @@ def eval(self, x): See http://stackoverflow.com/questions/2745329/how-to-make-scipy-interpolate-give-a-an-extrapolated-result-beyond-the-input-ran """ - y = N.zeros([N.size(x),N.size(self.ordinate,1)]) - for i in range(N.size(y,1)): - y[:,i] = N.interp(x,self.abscissa,self.ordinate[:,i]) - y[:,i] = N.where(x < self.abscissa[0], self.ordinate[0,i]+(x-self.abscissa[0])*(self.ordinate[0,i]-self.ordinate[1,i])/(self.abscissa[0]-self.abscissa[1]), y[:,i]) - y[:,i] = N.where(x > self.abscissa[-1], self.ordinate[-1,i]+(x-self.abscissa[-1])*(self.ordinate[-1,i]-self.ordinate[-2,i])/(self.abscissa[-1]-self.abscissa[-2]), y[:,i]) + y = np.zeros([np.size(x),np.size(self.ordinate,1)]) + for i in range(np.size(y,1)): + y[:,i] = np.interp(x,self.abscissa,self.ordinate[:,i]) + y[:,i] = np.where(x < self.abscissa[0], self.ordinate[0,i]+(x-self.abscissa[0])*(self.ordinate[0,i]-self.ordinate[1,i])/(self.abscissa[0]-self.abscissa[1]), y[:,i]) + y[:,i] = np.where(x > self.abscissa[-1], self.ordinate[-1,i]+(x-self.abscissa[-1])*(self.ordinate[-1,i]-self.ordinate[-2,i])/(self.abscissa[-1]-self.abscissa[-2]), y[:,i]) return y class TrajectoryConstantInterpolationExtrapolation(Trajectory): @@ -634,27 +634,27 @@ def eval(self, x): See http://stackoverflow.com/questions/2745329/how-to-make-scipy-interpolate-give-a-an-extrapolated-result-beyond-the-input-ran """ - y = N.zeros([N.size(x),N.size(self.ordinate,1)]) - x = N.array([x]).flatten() + y = np.zeros([np.size(x),np.size(self.ordinate,1)]) + x = np.array([x]).flatten() if self._mode == 1: - for i in range(N.size(y,1)): - for j in range(N.size(x)): + for i in range(np.size(y,1)): + for j in range(np.size(x)): try: y[j,i] = self.ordinate[self.abscissa<=x[j],i][-1] except IndexError: pass - y[:,i] = N.where(x < self.abscissa[0], self.ordinate[0,i], y[:,i]) - y[:,i] = N.where(x > self.abscissa[-1], self.ordinate[-1,i], y[:,i]) + y[:,i] = np.where(x < self.abscissa[0], self.ordinate[0,i], y[:,i]) + y[:,i] = np.where(x > self.abscissa[-1], self.ordinate[-1,i], y[:,i]) else: - for i in range(N.size(y,1)): - for j in range(N.size(x)): + for i in range(np.size(y,1)): + for j in range(np.size(x)): try: y[j,i] = self.ordinate[self.abscissa>=x[j],i][0] except IndexError: pass - y[:,i] = N.where(x < self.abscissa[0], self.ordinate[0,i], y[:,i]) - y[:,i] = N.where(x > self.abscissa[-1], self.ordinate[-1,i], y[:,i]) + y[:,i] = np.where(x < self.abscissa[0], self.ordinate[0,i], y[:,i]) + y[:,i] = np.where(x > self.abscissa[-1], self.ordinate[-1,i], y[:,i]) return y class TrajectoryUserFunction(Trajectory): @@ -686,9 +686,9 @@ def eval(self, x): corresponding to the argument x. """ try: - y = N.array(N.matrix(self.traj(float(x)))) + y = np.array(np.matrix(self.traj(float(x)))) except TypeError: - y = N.array(N.matrix(self.traj(x)).transpose()) + y = np.array(np.matrix(self.traj(x)).transpose()) #In order to guarantee that the #return values are on the correct #form. May need to be evaluated diff --git a/src/common/io.py b/src/common/io.py index 736f786f..2f3b4c8a 100644 --- a/src/common/io.py +++ b/src/common/io.py @@ -24,11 +24,8 @@ import os from functools import reduce -import numpy as N import numpy as np import scipy -import scipy.io -from scipy import interpolate scipy_minmaj = tuple(map(int, scipy.__version__.split('.')[:2])) if scipy_minmaj >= (1, 8): # due to a DeprecationWarning, we do below, this will likely need another change in a future update of scipy. @@ -38,7 +35,7 @@ import pyfmi.fmi as fmi import pyfmi.fmi_util as fmi_util -from pyfmi.common import python3_flag, encode, decode +from pyfmi.common import encode, decode from pyfmi.common.diagnostics import DIAGNOSTICS_PREFIX, DiagnosticsBase SYS_LITTLE_ENDIAN = sys.byteorder == 'little' @@ -160,7 +157,7 @@ def get_variable_index(self,name): name = name.replace(" ", "") try: - if python3_flag and isinstance(self, ResultDymolaBinary): + if isinstance(self, ResultDymolaBinary): return self.name_lookup[encode(name)] else: return self.name_lookup[name] @@ -171,7 +168,7 @@ def get_variable_index(self,name): if self._check_if_derivative_variable(name): try: #First do a simple search for the other naming convention - if python3_flag and isinstance(self, ResultDymolaBinary): + if isinstance(self, ResultDymolaBinary): return self.name_lookup[encode(self._convert_dx_name(name))] else: return self.name_lookup[self._convert_dx_name(name)] @@ -202,7 +199,7 @@ def _exhaustive_search_for_derivatives(self, name): state = self._find_underlying_state(name) index = self.get_variable_index(state) - alias_index = N.where(self.dataInfo[:,1]==self.dataInfo[index,1])[0] + alias_index = np.where(self.dataInfo[:,1]==self.dataInfo[index,1])[0] #Loop through all alias for ind in alias_index: @@ -210,19 +207,19 @@ def _exhaustive_search_for_derivatives(self, name): trial_name = list(self.name_lookup.keys())[ind] #Create the derivative name - if python3_flag and isinstance(self, ResultDymolaBinary): + if isinstance(self, ResultDymolaBinary): der_trial_name = self._create_derivative_from_state(decode(trial_name)) else: der_trial_name = self._create_derivative_from_state(trial_name) try: - if python3_flag and isinstance(self, ResultDymolaBinary): + if isinstance(self, ResultDymolaBinary): return self.name_lookup[encode(der_trial_name)] else: return self.name_lookup[der_trial_name] except KeyError: try: - if python3_flag and isinstance(self, ResultDymolaBinary): + if isinstance(self, ResultDymolaBinary): return self.name_lookup[encode(self._convert_dx_name(der_trial_name))] else: return self.name_lookup[self._convert_dx_name(der_trial_name)] @@ -328,7 +325,7 @@ def __init__(self, filename, delimiter=";"): data.append([float(d) for d in row]) - self.data = N.array(data) + self.data = np.array(data) def get_variable_data(self,name): """ @@ -606,9 +603,9 @@ def write_header(self, file_name='', parameters=None): f.write('int dataInfo(%d,%d)\n' % (num_vars+len(names_sens) + 1, 4)) f.write('0 1 0 -1 # time\n') - list_of_continuous_states = N.append(self.model._save_real_variables_val, + list_of_continuous_states = np.append(self.model._save_real_variables_val, self.model._save_int_variables_val) - list_of_continuous_states = N.append(list_of_continuous_states, + list_of_continuous_states = np.append(list_of_continuous_states, self.model._save_bool_variables_val).tolist() list_of_continuous_states = dict(zip(list_of_continuous_states, range(len(list_of_continuous_states)))) @@ -714,7 +711,7 @@ def write_point(self, data=None, parameter_data=[]): if data is None: #Retrieves the time-point [r,i,b] = self.model.save_time_point() - data = N.append(N.append(N.append(self.model.time,r),i),b) + data = np.append(np.append(np.append(self.model.time,r),i),b) #Write the point str_text = (" %.14E" % data[0]) @@ -752,7 +749,6 @@ def write_finalize(self): self._file_open = False - class ResultStorageMemory(ResultDymola): """ Class representing a simulation result that is kept in MEMORY. @@ -809,7 +805,7 @@ def get_variable_data(self,name): factor = -1 if var.alias == fmi.FMI_NEGATED_ALIAS else 1 if var.variability == fmi.FMI_CONSTANT or var.variability == fmi.FMI_PARAMETER: - return Trajectory([self.time[0],self.time[-1]],N.array([self.model.get(name),self.model.get(name)]).ravel()) + return Trajectory([self.time[0],self.time[-1]],np.array([self.model.get(name),self.model.get(name)]).ravel()) else: return Trajectory(self.time,factor*self.data[var.value_reference]) @@ -905,38 +901,24 @@ def __init__(self,fname): fid = fname fid.seek(0,0) # Needs to start from beginning of file - result = [] - # Read Aclass section nLines = self._find_phrase(fid, 'char Aclass') nLines = int(nLines[0]) - Aclass = [fid.readline().strip() for i in range(nLines)] - #Aclass = [] - #for i in range(0,nLines): - # Aclass.append(fid.readline().strip()) - self.Aclass = Aclass + self.Aclass = [fid.readline().strip() for i in range(nLines)] # Read name section nLines = self._find_phrase(fid, 'char name') nLines = int(nLines[0]) - name = [fid.readline().strip().replace(" ","") for i in range(nLines)] - #name = [] - #for i in range(0,nLines): - # name.append(fid.readline().strip().replace(" ","")) - self._name = name + self._name = [fid.readline().strip().replace(" ","") for i in range(nLines)] self.name_lookup = {key:ind for ind,key in enumerate(self._name)} # Read description section nLines = self._find_phrase(fid, 'char description') nLines = int(nLines[0]) - description = [fid.readline().strip() for i in range(nLines)] - #description = [] - #for i in range(0,nLines): - # description.append(fid.readline().strip()) - self.description = description + self.description = [fid.readline().strip() for i in range(nLines)] # Read dataInfo section nLines = self._find_phrase(fid, 'int dataInfo') @@ -945,26 +927,22 @@ def __init__(self,fname): nLines = int(nLines[0]) nCols = int(nCols[0]) - if python3_flag: - dataInfo = [list(map(int,fid.readline().split()[0:nCols])) for i in range(nLines)] - else: - dataInfo = [map(int,fid.readline().split()[0:nCols]) for i in range(nLines)] - self.dataInfo = N.array(dataInfo) + self.dataInfo = np.array([list(map(int,fid.readline().split()[0:nCols])) for i in range(nLines)]) # Find out how many data matrices there are - if len(name) == 1: #Only time + if len(self._name) == 1: #Only time nData = 2 else: nData = max(self.dataInfo[:,0]) self.data = [] for i in range(0,nData): - l = fid.readline() - tmp = l.partition(' ') - while tmp[0]!='float' and tmp[0]!='double' and l!='': - l = fid.readline() - tmp = l. partition(' ') - if l=='': + line = fid.readline() + tmp = line.partition(' ') + while tmp[0]!='float' and tmp[0]!='double' and line!='': + line = fid.readline() + tmp = line.partition(' ') + if line=='': raise JIOError('The result does not seem to be of a supported format.') tmp = tmp[2].partition('(') nLines = tmp[2].partition(',') @@ -974,34 +952,28 @@ def __init__(self,fname): data = [] for i in range(0,nLines): info = [] - while len(info) < nCols and l != '': - l = fid.readline() - info.extend(l.split()) + while len(info) < nCols and line != '': + line = fid.readline() + info.extend(line.split()) try: - if python3_flag: - data.append(list(map(float,info[0:nCols]))) - else: - data.append(map(float,info[0:nCols])) + data.append(list(map(float,info[0:nCols]))) except ValueError: #Handle 1.#INF's and such - if python3_flag: - data.append(list(map(robust_float,info[0:nCols]))) - else: - data.append(map(robust_float,info[0:nCols])) + data.append(list(map(robust_float,info[0:nCols]))) if len(info) == 0 and i < nLines-1: raise JIOError("Inconsistent number of lines in the result data.") del(info) - self.data.append(N.array(data)) + self.data.append(np.array(data)) if len(self.data) == 0: raise JIOError('Could not find any variable data in the result file.') def _find_phrase(self,fid, phrase): - l = fid.readline() - tmp = l.partition('(') - while tmp[0]!=phrase and l!='': - l = fid.readline() - tmp = l. partition('(') - if l=='': + line = fid.readline() + tmp = line.partition('(') + while tmp[0]!=phrase and line!='': + line = fid.readline() + tmp = line.partition('(') + if line=='': raise JIOError("The result does not seem to be of a supported format.") return tmp[2].partition(',') @@ -1136,7 +1108,7 @@ def shift_time(self,time_shift): The time shift offset. """ for i in range(len(self.data)): - for j in range(N.shape(self.data[i])[0]): + for j in range(np.shape(self.data[i])[0]): self.data[i][j,0] = self.data[i][j,0] + time_shift def append(self, res): @@ -1149,9 +1121,9 @@ def append(self, res): res -- A simulation result object of type DymolaResultTextual. """ - n_points = N.size(res.data[1],0) + n_points = np.size(res.data[1],0) time_shift = self.data[1][-1,0] - self.data[1] = N.vstack((self.data[1],res.data[1])) + self.data[1] = np.vstack((self.data[1],res.data[1])) self.data[1][n_points:,0] = self.data[1][n_points:,0] + time_shift #Overriding SCIPYs default reader for MATLAB v4 format @@ -1349,7 +1321,7 @@ def _get_name_dict(self): dict_names = list(name_dict.keys()) name_dict[DiagnosticsBase.calculated_diagnostics['nbr_steps']['name']] = None for name in dict_names: - if python3_flag and isinstance(name, bytes): + if isinstance(name, bytes): name = decode(name) if name == f'{DIAGNOSTICS_PREFIX}event_data.event_info.event_type': name_dict[DiagnosticsBase.calculated_diagnostics['nbr_time_events']['name']] = None @@ -1430,7 +1402,7 @@ def _get_interpolated_trajectory(self, data_index): time_vector = self._read_trajectory_data(0, False) data = self._read_trajectory_data(data_index, False) - f = interpolate.interp1d(time_vector, data, fill_value="extrapolate") + f = scipy.interpolate.interp1d(time_vector, data, fill_value="extrapolate") self._data_2[data_index] = f(diag_time_vector) @@ -1440,7 +1412,7 @@ def _get_interpolated_trajectory(self, data_index): def _get_description(self): if not self._description: description = scipy.io.loadmat(self._fname,chars_as_strings=False, variable_names=["description"])["description"] - self._description = ["".join(description[:,i]).rstrip() for i in range(description[0,:].size)] + self._description = ["".join(description[:,i]).rstrip() for i in range(np.size(description[0,:]))] return self._description @@ -1463,7 +1435,7 @@ def get_variable_data(self, name): A Trajectory object containing the time vector and the data vector of the variable. """ - if python3_flag and isinstance(name, bytes): + if isinstance(name, bytes): name = decode(name) if name == 'time' or name== 'Time': @@ -1476,7 +1448,7 @@ def get_variable_data(self, name): elif '{}.'.format(DiagnosticsBase.calculated_diagnostics['nbr_state_limits_step']['name']) in name: return Trajectory(self._get_diagnostics_trajectory(0), self._calculate_nbr_state_limits_step(name)) elif name == f'{DIAGNOSTICS_PREFIX}cpu_time': - return Trajectory(self._get_diagnostics_trajectory(0), N.cumsum(self.get_variable_data(f'{DIAGNOSTICS_PREFIX}cpu_time_per_step').x)) + return Trajectory(self._get_diagnostics_trajectory(0), np.cumsum(self.get_variable_data(f'{DIAGNOSTICS_PREFIX}cpu_time_per_step').x)) else: varInd = self.get_variable_index(name) @@ -1515,12 +1487,12 @@ def _calculate_events_and_steps(self, name): event_type_data = self.get_variable_data(f'{DIAGNOSTICS_PREFIX}event_data.event_info.event_type') except Exception: if name == steps_name: - self._data_3[steps_name] = N.array(range(len(self._get_diagnostics_trajectory(0)))) + self._data_3[steps_name] = np.array(range(len(self._get_diagnostics_trajectory(0)))) return self._data_3[name] - self._data_3[all_events_name] = N.zeros(len(event_type_data.x)) - self._data_3[time_events_name] = N.zeros(len(event_type_data.x)) - self._data_3[state_events_name] = N.zeros(len(event_type_data.x)) - self._data_3[steps_name] = N.zeros(len(event_type_data.x)) + self._data_3[all_events_name] = np.zeros(len(event_type_data.x)) + self._data_3[time_events_name] = np.zeros(len(event_type_data.x)) + self._data_3[state_events_name] = np.zeros(len(event_type_data.x)) + self._data_3[steps_name] = np.zeros(len(event_type_data.x)) nof_events = 0 nof_time_events = 0 nof_state_events = 0 @@ -1547,7 +1519,7 @@ def _calculate_nbr_state_limits_step(self, name): state_name = name.replace(step_limitation_name, '') state_error_data = self.get_variable_data(f'{DIAGNOSTICS_PREFIX}state_errors.'+state_name) event_type_data = self.get_variable_data(f'{DIAGNOSTICS_PREFIX}event_data.event_info.event_type') - self._data_3[name] = N.zeros(len(event_type_data.x)) + self._data_3[name] = np.zeros(len(event_type_data.x)) nof_times_state_limits_step = 0 for ind, state_error in enumerate(state_error_data.x): if event_type_data.x[ind] == -1 and state_error >= 1.0: @@ -1697,7 +1669,7 @@ def integration_point(self, solver = None): #Sets the parameters, if any if solver and self.options["sensitivities"]: - self.param_sol += [N.array(solver.interpolate_sensitivity(model.time, 0)).flatten()] + self.param_sol += [np.array(solver.interpolate_sensitivity(model.time, 0)).flatten()] def simulation_end(self): """ @@ -1712,16 +1684,16 @@ def get_result(self): result of an instance of ResultBase or of an instance of a subclass of ResultBase. """ - t = N.array(self.time_sol) - r = N.array(self.real_sol) - data = N.c_[t,r] + t = np.array(self.time_sol) + r = np.array(self.real_sol) + data = np.c_[t,r] if len(self.int_sol) > 0 and len(self.int_sol[0]) > 0: - i = N.array(self.int_sol) - data = N.c_[data,i] + i = np.array(self.int_sol) + data = np.c_[data,i] if len(self.bool_sol) > 0 and len(self.bool_sol[0]) > 0: - b = N.array(self.bool_sol) - data = N.c_[data,b] + b = np.array(self.bool_sol) + data = np.c_[data,b] return ResultStorageMemory(self.model, data, [self.real_var_ref,self.int_var_ref,self.bool_var_ref], self.vars) @@ -1849,18 +1821,18 @@ def simulation_start(self): for i,val in enumerate(const_val_bool): const_str += "%.14E"%(const_alias_bool[i]*val)+delimiter - #for val in N.append(const_val_real,N.append(const_val_int,const_val_boolean)): + #for val in np.append(const_val_real,np.append(const_val_int,const_val_boolean)): # const_str += "%.14E"%val+delimiter self.const_str = const_str self._file = f self.cont_valref_real = cont_valref_real - self.cont_alias_real = N.array(cont_alias_real) + self.cont_alias_real = np.array(cont_alias_real) self.cont_valref_int = cont_valref_int - self.cont_alias_int = N.array(cont_alias_int) + self.cont_alias_int = np.array(cont_alias_int) self.cont_valref_bool = cont_valref_bool - self.cont_alias_bool = N.array(cont_alias_bool) + self.cont_alias_bool = np.array(cont_alias_bool) def integration_point(self, solver = None): """ @@ -1886,7 +1858,7 @@ def integration_point(self, solver = None): i = model.get_integer(self.cont_valref_int)*self.cont_alias_int b = model.get_boolean(self.cont_valref_bool)*self.cont_alias_bool - data = N.append(N.append(r,i),b) + data = np.append(np.append(r,i),b) cont_str = "" for val in data: @@ -2078,10 +2050,7 @@ def simulation_start(self): if isinstance(self.model, fmi.FMUModelME2): vars = self.model.get_model_variables(type=fmi.FMI2_REAL,include_alias=False,variability=fmi.FMI2_CONTINUOUS,filter=self.options["filter"]) - if python3_flag: - state_vars = [v.value_reference for i,v in self.model.get_states_list().items()] - else: - state_vars = [v.value_reference for i,v in self.model.get_states_list().iteritems()] + state_vars = [v.value_reference for i,v in self.model.get_states_list().items()] else: vars = self.model.get_model_variables(type=fmi.FMI_REAL,include_alias=False,variability=fmi.FMI_CONTINUOUS,filter=self.options["filter"]) state_vars = self.model.get_state_value_references() @@ -2289,10 +2258,10 @@ def simulation_start(self): #f.write('%s,%d)\n' % (' '*14, self._nvariables)) self._file = f - self._data_order = N.array(valueref_of_continuous_states) - self.real_var_ref = N.array(self.real_var_ref) - self.int_var_ref = N.array(self.int_var_ref) - self.bool_var_ref = N.array(self.bool_var_ref) + self._data_order = np.array(valueref_of_continuous_states) + self.real_var_ref = np.array(self.real_var_ref) + self.int_var_ref = np.array(self.int_var_ref) + self.bool_var_ref = np.array(self.bool_var_ref) def integration_point(self, solver = None):#parameter_data=[]): """ @@ -2317,14 +2286,14 @@ def integration_point(self, solver = None):#parameter_data=[]): i = model.get_integer(self.int_var_ref) b = model.get_boolean(self.bool_var_ref) - data = N.append(N.append(r,i),b) + data = np.append(np.append(r,i),b) #Write the point str_text = (" %.14E" % self.model.time) + ''.join([" %.14E" % (data[data_order[j]]) for j in range(self._nvariables-1)]) #Sets the parameters, if any if solver and self.options["sensitivities"]: - parameter_data = N.array(solver.interpolate_sensitivity(model.time, 0)).flatten() + parameter_data = np.array(solver.interpolate_sensitivity(model.time, 0)).flatten() for j in range(len(parameter_data)): str_text = str_text + (" %.14E" % (parameter_data[j])) @@ -2427,11 +2396,11 @@ def robust_float(value): return float(value) except ValueError: if value.startswith("1.#INF"): - return float(N.inf) + return float(np.inf) elif value.startswith("-1.#INF"): - return float(-N.inf) + return float(-np.inf) elif value.startswith("1.#QNAN") or value.startswith("-1.#IND"): - return float(N.nan) + return float(np.nan) else: raise ValueError @@ -2639,7 +2608,7 @@ def simulation_start(self, diagnostics_params={}, diagnostics_vars={}): self.dump_data_internal = fmi_util.DumpData(self.model, self._file, self.real_var_ref, self.int_var_ref, self.bool_var_ref, self._with_diagnostics) if self._with_diagnostics: - diag_data = N.array([val[0] for val in diagnostics_vars.values()], dtype=float) + diag_data = np.array([val[0] for val in diagnostics_vars.values()], dtype=float) self.diagnostics_point(diag_data) def integration_point(self, solver = None): diff --git a/src/common/log/parser.py b/src/common/log/parser.py index b2a8627e..47ca85b9 100644 --- a/src/common/log/parser.py +++ b/src/common/log/parser.py @@ -20,11 +20,9 @@ from xml import sax import re -import os import numpy as np from distutils.util import strtobool -from pyfmi.common.log.tree import * -from pyfmi.fmi_util import python3_flag +from pyfmi.common.log.tree import Node, Comment from pyfmi.fmi import FMUException ## Leaf parser ## @@ -59,8 +57,7 @@ def parse_value(text): text = text[1:-1].replace('""','"') else: assert '"' not in text - # for python 2 we need to avoid printing all strings as u'...' - return text if python3_flag else text.encode('ascii', 'xmlcharrefreplace') + return text def parse_vector(text): @@ -206,7 +203,7 @@ def extract_xml_log(dest, log, modulename = 'Model'): dest -- Name of the file which holds the extracted log, or a stream to write to - that supports the function 'write'. Default behaviour is to write to a file. + that supports the function 'write'. Default behavior is to write to a file. Default: get_log_filename() + xml log -- String of filename to extract log from or a stream. The support for stream diff --git a/src/common/log/prettyprinter.py b/src/common/log/prettyprinter.py index ac463772..a42d2133 100644 --- a/src/common/log/prettyprinter.py +++ b/src/common/log/prettyprinter.py @@ -19,7 +19,7 @@ """ from numpy import ndarray -from pyfmi.common.log.tree import * +from pyfmi.common.log.tree import Node, Comment def prettyprint(write, node): """Prettyprint a log node to the write callback write.""" diff --git a/src/common/log/tree.py b/src/common/log/tree.py index 1dc85a5e..043b4e4a 100644 --- a/src/common/log/tree.py +++ b/src/common/log/tree.py @@ -19,7 +19,6 @@ Each node is represented as a Node, Comment, or leaf (other types) """ -from pyfmi.fmi_util import python3_flag class Comment(object): """Log comment node. @@ -89,7 +88,7 @@ def find(self, types): types may be a string or list of strings. """ - if isinstance(types, str if python3_flag else basestring): + if isinstance(types, str): types = [types] nodes = [] diff --git a/src/common/plotting/plot_gui.py b/src/common/plotting/plot_gui.py index 5064fd28..7c3cf89e 100644 --- a/src/common/plotting/plot_gui.py +++ b/src/common/plotting/plot_gui.py @@ -25,6 +25,7 @@ from matplotlib import rcParams import fnmatch import re +import os #GUI modules try: @@ -49,8 +50,6 @@ except ImportError: print("JModelica Python package was not found.") -#Import general modules -import os as O ID_GRID = 15001 ID_LICENSE = 15002 @@ -290,7 +289,7 @@ def OnMenuOpen(self, event): #If OK load the results if dlg.ShowModal() == wx.ID_OK: for n in dlg.GetFilenames(): - self._OpenFile(O.path.join(dlg.GetDirectory(),n)) + self._OpenFile(os.path.join(dlg.GetDirectory(),n)) dlg.Destroy() #Destroy the popup window diff --git a/src/pyfmi/__init__.py b/src/pyfmi/__init__.py index 05b87784..49d628c6 100644 --- a/src/pyfmi/__init__.py +++ b/src/pyfmi/__init__.py @@ -26,13 +26,13 @@ from pyfmi.fmi_coupled import CoupledFMUModelME2 from pyfmi.master import Master from pyfmi.fmi_extended import FMUModelME1Extended -import numpy as N +import numpy as np import os.path import sys import time -int = N.int32 -N.int = N.int32 +int = np.int32 +np.int = np.int32 def testattr(**kwargs): """Add attributes to a test function/method/class. diff --git a/src/pyfmi/debug.py b/src/pyfmi/debug.py index c742c5f2..3e1b8837 100644 --- a/src/pyfmi/debug.py +++ b/src/pyfmi/debug.py @@ -19,8 +19,8 @@ This file contains methods for helping with debugging a simulation. """ -import numpy as N -import scipy as S +import numpy as np +import pylab as pl class DebugInformation: @@ -49,7 +49,7 @@ def _load_data(self): if len(row_data) > 2: event_indicators = row_data[2].strip().replace("\n","") event_indicators = event_indicators.split(" ") - self.event_indicators.append(N.array([abs(float(i)) for i in event_indicators])) + self.event_indicators.append(np.array([abs(float(i)) for i in event_indicators])) row_data = file.readline() elif row_data.startswith("Solver"): self.solver = row_data.split(" ")[-1] @@ -61,80 +61,71 @@ def _load_data(self): break def plot_time_distribution(self, normalized=False): - import pylab as P if normalized: - total_time = N.sum(self.real_time) - P.plot(self.simulated_time,self.real_time/total_time) - P.ylabel("Real Time (normalized)") + total_time = np.sum(self.real_time) + pl.plot(self.simulated_time,self.real_time/total_time) + pl.ylabel("Real Time (normalized)") else: - P.plot(self.simulated_time,self.real_time) - P.ylabel("Real Time [s]") - P.xlabel("Time [s]") + pl.plot(self.simulated_time,self.real_time) + pl.ylabel("Real Time [s]") + pl.xlabel("Time [s]") self._plot_events() - P.legend(("Time","Events")) + pl.legend(("Time","Events")) - P.grid() - P.show() + pl.grid() + pl.show() def plot_cumulative_time_elapsed(self, log_scale=False): - import pylab as P - - cumulative_sum = N.cumsum(self.real_time) + cumulative_sum = np.cumsum(self.real_time) if log_scale: - P.semilogy(self.simulated_time, cumulative_sum) + pl.semilogy(self.simulated_time, cumulative_sum) else: - P.plot(self.simulated_time, cumulative_sum) - P.xlabel("Time [s]") - P.ylabel("Real Time [s]") + pl.plot(self.simulated_time, cumulative_sum) + pl.xlabel("Time [s]") + pl.ylabel("Real Time [s]") self._plot_events() - P.legend(("Time","Events")) + pl.legend(("Time","Events")) - P.grid() - P.show() + pl.grid() + pl.show() def plot_step_size(self): - import pylab as P - - P.semilogy(self.simulated_time,N.diff([0.0]+self.simulated_time),drawstyle="steps-pre") - P.ylabel("Step-size") - P.xlabel("Time [s]") - P.title("Step-size history") - P.grid() - P.show() + pl.semilogy(self.simulated_time,np.diff([0.0]+self.simulated_time),drawstyle="steps-pre") + pl.ylabel("Step-size") + pl.xlabel("Time [s]") + pl.title("Step-size history") + pl.grid() + pl.show() def _plot_events(self): - import pylab as P - for ev in self.events: - P.axvline(x=ev,color='r') + pl.axvline(x=ev,color='r') def plot_event_indicators(self, mask=None, region=None): - import pylab as P - - ev_ind = N.array(self.event_indicators) - time = N.array(self.simulated_time) - ev_ind_name = N.array(["event_ind_%d"%i for i in range(len(ev_ind[0,:]))]) + ev_ind = np.array(self.event_indicators) + time = np.array(self.simulated_time) + ev_ind_name = np.array(["event_ind_%d"%i for i in range(len(ev_ind[0,:]))]) if region: lw = time > region[0] up = time < region[1] - time = time[N.logical_and(lw,up)] - ev_ind = ev_ind[N.logical_and(lw,up), :] + time = time[np.logical_and(lw,up)] + ev_ind = ev_ind[np.logical_and(lw,up), :] if mask: - P.plot(time, ev_ind[:,mask]) - P.legend(ev_ind_name[mask]) + pl.plot(time, ev_ind[:,mask]) + pl.legend(ev_ind_name[mask]) else: - P.plot(time, ev_ind) - P.legend(ev_ind_name) - P.grid() - P.xlabel("Time [s]") - P.title("Event Indicators") - P.show() + pl.plot(time, ev_ind) + pl.legend(ev_ind_name) + pl.grid() + pl.xlabel("Time [s]") + pl.title("Event Indicators") + pl.show() class ImplicitEulerDebugInformation(DebugInformation): pass @@ -166,11 +157,11 @@ def _load_data(self): self.order.append(int(row_data[2].strip())) error_data = row_data[3].strip().replace("\n","") error_data = error_data.split(" ") - self.weighted_error.append(N.array([abs(float(i)) for i in error_data])) + self.weighted_error.append(np.array([abs(float(i)) for i in error_data])) if len(row_data) > 4: event_indicators = row_data[4].strip().replace("\n","") event_indicators = event_indicators.split(" ") - self.event_indicators.append(N.array([abs(float(i)) for i in event_indicators])) + self.event_indicators.append(np.array([abs(float(i)) for i in event_indicators])) row_data = file.readline() elif row_data.startswith("Solver"): self.solver = row_data.split(" ")[-1] @@ -183,48 +174,44 @@ def _load_data(self): def plot_order(self): - import pylab as P - - P.plot(self.simulated_time, self.order,drawstyle="steps-pre") - P.grid() - P.xlabel("Time [s]") - P.ylabel("Order") - P.title("Order evolution") + pl.plot(self.simulated_time, self.order,drawstyle="steps-pre") + pl.grid() + pl.xlabel("Time [s]") + pl.ylabel("Order") + pl.title("Order evolution") self._plot_events() - P.legend(("Order","Events")) + pl.legend(("Order","Events")) - P.show() + pl.show() def plot_error(self, threshold=None, region=None, legend=True): - import pylab as P - - err = N.array(self.weighted_error) - time = N.array(self.simulated_time) + err = np.array(self.weighted_error) + time = np.array(self.simulated_time) if region: lw = time > region[0] up = time < region[1] - time = time[N.logical_and(lw,up)] - err = err[N.logical_and(lw,up), :] + time = time[np.logical_and(lw,up)] + err = err[np.logical_and(lw,up), :] if threshold: time_points, nbr_vars = err.shape - mask = N.ones(nbr_vars,dtype=bool) + mask = np.ones(nbr_vars,dtype=bool) for i in range(nbr_vars): - if N.max(err[:,i]) < threshold: + if np.max(err[:,i]) < threshold: mask[i] = False - P.semilogy(time, err[:,mask]) + pl.semilogy(time, err[:,mask]) if legend: - P.legend(N.array(self.state_variables)[mask],loc="lower right") + pl.legend(np.array(self.state_variables)[mask],loc="lower right") else: - P.semilogy(time, err) + pl.semilogy(time, err) if legend: - P.legend(self.state_variables, loc="lower right") - P.xlabel("Time [s]") - P.ylabel("Error") - P.title("Error evolution") - P.grid() - P.show() + pl.legend(self.state_variables, loc="lower right") + pl.xlabel("Time [s]") + pl.ylabel("Error") + pl.title("Error evolution") + pl.grid() + pl.show() class Radau5ODEDebugInformation(CVodeDebugInformation): pass diff --git a/src/pyfmi/examples/fmi20_bouncing_ball_native.py b/src/pyfmi/examples/fmi20_bouncing_ball_native.py index b9d9240c..22fc59fc 100644 --- a/src/pyfmi/examples/fmi20_bouncing_ball_native.py +++ b/src/pyfmi/examples/fmi20_bouncing_ball_native.py @@ -14,16 +14,16 @@ # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . -import os as O -import pylab as P -import numpy as N +import os +import pylab as pl +import numpy as np from pyfmi import load_fmu -curr_dir = O.path.dirname(O.path.abspath(__file__)); -path_to_fmus = O.path.join(curr_dir, 'files', 'FMUs') -path_to_fmus_me2 = O.path.join(path_to_fmus,"ME2.0") +curr_dir = os.path.dirname(os.path.abspath(__file__)) +path_to_fmus = os.path.join(curr_dir, 'files', 'FMUs') +path_to_fmus_me2 = os.path.join(path_to_fmus,"ME2.0") def run_demo(with_plots=True): """ @@ -39,7 +39,7 @@ def run_demo(with_plots=True): """ #Load the FMU by specifying the fmu and the directory - bouncing_fmu = load_fmu(O.path.join(path_to_fmus_me2, 'bouncingBall.fmu')) + bouncing_fmu = load_fmu(os.path.join(path_to_fmus_me2, 'bouncingBall.fmu')) Tstart = 0.5 #The start time. Tend = 3.0 #The final simulation time. @@ -155,18 +155,18 @@ def run_demo(with_plots=True): #Plot the solution if with_plots: #Plot the height - P.figure(1) - P.plot(t_sol,N.array(sol)[:,0]) - P.title(bouncing_fmu.get_name()) - P.ylabel('Height (m)') - P.xlabel('Time (s)') + pl.figure(1) + pl.plot(t_sol,np.array(sol)[:,0]) + pl.title(bouncing_fmu.get_name()) + pl.ylabel('Height (m)') + pl.xlabel('Time (s)') #Plot the velocity - P.figure(2) - P.plot(t_sol,N.array(sol)[:,1]) - P.title(bouncing_fmu.get_name()) - P.ylabel('Velocity (m/s)') - P.xlabel('Time (s)') - P.show() + pl.figure(2) + pl.plot(t_sol,np.array(sol)[:,1]) + pl.title(bouncing_fmu.get_name()) + pl.ylabel('Velocity (m/s)') + pl.xlabel('Time (s)') + pl.show() if __name__ == "__main__": run_demo() diff --git a/src/pyfmi/examples/fmi_bouncing_ball.py b/src/pyfmi/examples/fmi_bouncing_ball.py index 0245dc80..d7b4b658 100644 --- a/src/pyfmi/examples/fmi_bouncing_ball.py +++ b/src/pyfmi/examples/fmi_bouncing_ball.py @@ -14,16 +14,16 @@ # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . -import os as O -import pylab as P -import numpy as N +import os +import pylab as pl +import numpy as np from pyfmi import load_fmu -curr_dir = O.path.dirname(O.path.abspath(__file__)); -path_to_fmus = O.path.join(curr_dir, 'files', 'FMUs','ME1.0') -path_to_fmus2 = O.path.join(curr_dir, 'files', 'FMUs','ME2.0') +curr_dir = os.path.dirname(os.path.abspath(__file__)); +path_to_fmus = os.path.join(curr_dir, 'files', 'FMUs','ME1.0') +path_to_fmus2 = os.path.join(curr_dir, 'files', 'FMUs','ME2.0') def run_demo(with_plots=True, version="2.0"): """ @@ -31,9 +31,9 @@ def run_demo(with_plots=True, version="2.0"): ME FMUs version 1.0 and 2.0. """ if version == '1.0': - fmu_name = O.path.join(path_to_fmus,'bouncingBall.fmu') + fmu_name = os.path.join(path_to_fmus,'bouncingBall.fmu') else: - fmu_name = O.path.join(path_to_fmus2,'bouncingBall.fmu') + fmu_name = os.path.join(path_to_fmus2,'bouncingBall.fmu') model = load_fmu(fmu_name) @@ -44,24 +44,24 @@ def run_demo(with_plots=True, version="2.0"): v_res = res['v'] t = res['time'] - assert N.abs(res.final('h') - (0.0424044)) < 1e-4 + assert np.abs(res.final('h') - (0.0424044)) < 1e-4 # Plot the solution if with_plots: # Plot the height - fig = P.figure() - P.clf() - P.subplot(2,1,1) - P.plot(t, h_res) - P.ylabel('Height (m)') - P.xlabel('Time (s)') + pl.figure() + pl.clf() + pl.subplot(2,1,1) + pl.plot(t, h_res) + pl.ylabel('Height (m)') + pl.xlabel('Time (s)') # Plot the velocity - P.subplot(2,1,2) - P.plot(t, v_res) - P.ylabel('Velocity (m/s)') - P.xlabel('Time (s)') - P.suptitle('FMI Bouncing Ball') - P.show() + pl.subplot(2,1,2) + pl.plot(t, v_res) + pl.ylabel('Velocity (m/s)') + pl.xlabel('Time (s)') + pl.suptitle('FMI Bouncing Ball') + pl.show() if __name__ == "__main__": diff --git a/src/pyfmi/examples/fmi_bouncing_ball_cs.py b/src/pyfmi/examples/fmi_bouncing_ball_cs.py index 236e3cf8..5008adbc 100644 --- a/src/pyfmi/examples/fmi_bouncing_ball_cs.py +++ b/src/pyfmi/examples/fmi_bouncing_ball_cs.py @@ -14,16 +14,16 @@ # # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . -import os as O -import pylab as P -import numpy as N +import os +import pylab as pl +import numpy as np from pyfmi import load_fmu -curr_dir = O.path.dirname(O.path.abspath(__file__)); -path_to_fmus = O.path.join(curr_dir, 'files', 'FMUs', 'CS1.0') -path_to_fmus2 = O.path.join(curr_dir, 'files', 'FMUs', 'CS2.0') +curr_dir = os.path.dirname(os.path.abspath(__file__)); +path_to_fmus = os.path.join(curr_dir, 'files', 'FMUs', 'CS1.0') +path_to_fmus2 = os.path.join(curr_dir, 'files', 'FMUs', 'CS2.0') def run_demo(with_plots=True, version='2.0'): """ @@ -32,9 +32,9 @@ def run_demo(with_plots=True, version='2.0'): """ if version == '1.0': - fmu_name = O.path.join(path_to_fmus,'bouncingBall.fmu') + fmu_name = os.path.join(path_to_fmus,'bouncingBall.fmu') else: - fmu_name = O.path.join(path_to_fmus2,'bouncingBall.fmu') + fmu_name = os.path.join(path_to_fmus2,'bouncingBall.fmu') model = load_fmu(fmu_name) res = model.simulate(final_time=2.) @@ -44,24 +44,24 @@ def run_demo(with_plots=True, version='2.0'): v_res = res['v'] t = res['time'] - assert N.abs(res.final('h') - (0.0424044)) < 1e-2 + assert np.abs(res.final('h') - (0.0424044)) < 1e-2 # Plot the solution if with_plots: # Plot the height - fig = P.figure() - P.clf() - P.subplot(2,1,1) - P.plot(t, h_res) - P.ylabel('Height (m)') - P.xlabel('Time (s)') + pl.figure() + pl.clf() + pl.subplot(2,1,1) + pl.plot(t, h_res) + pl.ylabel('Height (m)') + pl.xlabel('Time (s)') # Plot the velocity - P.subplot(2,1,2) - P.plot(t, v_res) - P.ylabel('Velocity (m/s)') - P.xlabel('Time (s)') - P.suptitle('FMI Bouncing Ball') - P.show() + pl.subplot(2,1,2) + pl.plot(t, v_res) + pl.ylabel('Velocity (m/s)') + pl.xlabel('Time (s)') + pl.suptitle('FMI Bouncing Ball') + pl.show() if __name__ == "__main__": diff --git a/src/pyfmi/examples/fmi_bouncing_ball_native.py b/src/pyfmi/examples/fmi_bouncing_ball_native.py index e00a81f4..b1dd78ef 100644 --- a/src/pyfmi/examples/fmi_bouncing_ball_native.py +++ b/src/pyfmi/examples/fmi_bouncing_ball_native.py @@ -16,12 +16,12 @@ # along with this program. If not, see . import os -import pylab as P -import numpy as N +import pylab as pl +import numpy as np from pyfmi import load_fmu -curr_dir = os.path.dirname(os.path.abspath(__file__)); +curr_dir = os.path.dirname(os.path.abspath(__file__)) path_to_fmus = os.path.join(curr_dir, 'files', 'FMUs') path_to_fmus_me1 = os.path.join(path_to_fmus,"ME1.0") path_to_fmus_cs1 = os.path.join(path_to_fmus,"CS1.0") @@ -144,18 +144,18 @@ def run_demo(with_plots=True): #Plot the solution if with_plots: #Plot the height - P.figure(1) - P.plot(t_sol,N.array(sol)[:,0]) - P.title(bouncing_fmu.get_name()) - P.ylabel('Height (m)') - P.xlabel('Time (s)') + pl.figure(1) + pl.plot(t_sol,np.array(sol)[:,0]) + pl.title(bouncing_fmu.get_name()) + pl.ylabel('Height (m)') + pl.xlabel('Time (s)') #Plot the velocity - P.figure(2) - P.plot(t_sol,N.array(sol)[:,1]) - P.title(bouncing_fmu.get_name()) - P.ylabel('Velocity (m/s)') - P.xlabel('Time (s)') - P.show() + pl.figure(2) + pl.plot(t_sol,np.array(sol)[:,1]) + pl.title(bouncing_fmu.get_name()) + pl.ylabel('Velocity (m/s)') + pl.xlabel('Time (s)') + pl.show() if __name__ == "__main__": run_demo() diff --git a/src/pyfmi/examples/fmu_with_input.py b/src/pyfmi/examples/fmu_with_input.py index 2f7684f3..985233f5 100644 --- a/src/pyfmi/examples/fmu_with_input.py +++ b/src/pyfmi/examples/fmu_with_input.py @@ -15,16 +15,16 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . -import os as O -import numpy as N -import pylab as p +import os +import numpy as np +import pylab as pl from pyfmi import load_fmu -curr_dir = O.path.dirname(O.path.abspath(__file__)); -path_to_fmus = O.path.join(curr_dir, 'files', 'FMUs') -path_to_fmus_me1 = O.path.join(path_to_fmus,"ME1.0") -path_to_fmus_cs1 = O.path.join(path_to_fmus,"CS1.0") +curr_dir = os.path.dirname(os.path.abspath(__file__)) +path_to_fmus = os.path.join(curr_dir, 'files', 'FMUs') +path_to_fmus_me1 = os.path.join(path_to_fmus,"ME1.0") +path_to_fmus_cs1 = os.path.join(path_to_fmus,"CS1.0") def run_demo(with_plots=True): """ @@ -32,12 +32,12 @@ def run_demo(with_plots=True): See also simulation_with_input.py """ - fmu_name = O.path.join(path_to_fmus_me1,'SecondOrder.fmu') + fmu_name = os.path.join(path_to_fmus_me1,'SecondOrder.fmu') # Generate input - t = N.linspace(0.,10.,100) - u = N.cos(t) - u_traj = N.transpose(N.vstack((t,u))) + t = np.linspace(0.,10.,100) + u = np.cos(t) + u_traj = np.transpose(np.vstack((t,u))) # Create input object input_object = ('u', u_traj) @@ -56,17 +56,17 @@ def run_demo(with_plots=True): u_sim = res['u'] time_sim = res['time'] - assert N.abs(res.final('x1')*1.e1 - (-8.3999640)) < 1e-3 - assert N.abs(res.final('x2')*1.e1 - (-5.0691179)) < 1e-3 - assert N.abs(res.final('u')*1.e1 - (-8.3907153)) < 1e-3 + assert np.abs(res.final('x1')*1.e1 - (-8.3999640)) < 1e-3 + assert np.abs(res.final('x2')*1.e1 - (-5.0691179)) < 1e-3 + assert np.abs(res.final('u')*1.e1 - (-8.3907153)) < 1e-3 if with_plots: - fig = p.figure() - p.subplot(2,1,1) - p.plot(time_sim, x1_sim, time_sim, x2_sim) - p.subplot(2,1,2) - p.plot(time_sim, u_sim,'x-',t, u[:],'x-') - p.show() + pl.figure() + pl.subplot(2,1,1) + pl.plot(time_sim, x1_sim, time_sim, x2_sim) + pl.subplot(2,1,2) + pl.plot(time_sim, u_sim,'x-',t, u[:],'x-') + pl.show() if __name__=="__main__": run_demo() diff --git a/src/pyfmi/examples/fmu_with_input_function.py b/src/pyfmi/examples/fmu_with_input_function.py index c97db89e..2e4c42f5 100644 --- a/src/pyfmi/examples/fmu_with_input_function.py +++ b/src/pyfmi/examples/fmu_with_input_function.py @@ -15,16 +15,16 @@ # You should have received a copy of the GNU Lesser General Public License # along with this program. If not, see . -import os as O -import numpy as N -import pylab as p +import os +import numpy as np +import pylab as pl from pyfmi import load_fmu -curr_dir = O.path.dirname(O.path.abspath(__file__)); -path_to_fmus = O.path.join(curr_dir, 'files', 'FMUs') -path_to_fmus_me1 = O.path.join(path_to_fmus,"ME1.0") -path_to_fmus_cs1 = O.path.join(path_to_fmus,"CS1.0") +curr_dir = os.path.dirname(os.path.abspath(__file__)) +path_to_fmus = os.path.join(curr_dir, 'files', 'FMUs') +path_to_fmus_me1 = os.path.join(path_to_fmus,"ME1.0") +path_to_fmus_cs1 = os.path.join(path_to_fmus,"CS1.0") def run_demo(with_plots=True): """ @@ -32,10 +32,10 @@ def run_demo(with_plots=True): See also simulation_with_input.py """ - fmu_name = O.path.join(path_to_fmus_me1,'SecondOrder.fmu') + fmu_name = os.path.join(path_to_fmus_me1,'SecondOrder.fmu') # Create input object - input_object = ('u', N.cos) + input_object = ('u', np.cos) # Load the dynamic library and XML data model = load_fmu(fmu_name) @@ -48,17 +48,17 @@ def run_demo(with_plots=True): u_sim = res['u'] time_sim = res['time'] - assert N.abs(res.final('x1') - (-1.646485144)) < 1e-3 - assert N.abs(res.final('x2')*1.e1 - (-7.30591626709)) < 1e-3 - assert N.abs(res.final('u')*1.e1 - (1.54251449888)) < 1e-3 + assert np.abs(res.final('x1') - (-1.646485144)) < 1e-3 + assert np.abs(res.final('x2')*1.e1 - (-7.30591626709)) < 1e-3 + assert np.abs(res.final('u')*1.e1 - (1.54251449888)) < 1e-3 if with_plots: - fig = p.figure() - p.subplot(2,1,1) - p.plot(time_sim, x1_sim, time_sim, x2_sim) - p.subplot(2,1,2) - p.plot(time_sim, u_sim) - p.show() + pl.figure() + pl.subplot(2,1,1) + pl.plot(time_sim, x1_sim, time_sim, x2_sim) + pl.subplot(2,1,2) + pl.plot(time_sim, u_sim) + pl.show() if __name__=="__main__": run_demo() diff --git a/src/pyfmi/fmi.pxd b/src/pyfmi/fmi.pxd index b4caf933..b110a24c 100644 --- a/src/pyfmi/fmi.pxd +++ b/src/pyfmi/fmi.pxd @@ -17,17 +17,8 @@ """ Module containing the FMI interface Python wrappers. """ -import os -import sys -import logging -import fnmatch -import re -from collections import OrderedDict - -import numpy as N -cimport numpy as N - -N.import_array() +import numpy as np +cimport numpy as np cimport pyfmi.fmil_import as FMIL @@ -161,10 +152,6 @@ cdef class FMUModelME1(FMUModelBase): cdef int _get_nominal_continuous_states_fmil(self, FMIL.fmi1_real_t* xnominal, size_t nx) cdef public object _preinit_nominal_continuous_states -cdef class _ForTestingFMUModelME1(FMUModelME1): - cdef int _get_nominal_continuous_states_fmil(self, FMIL.fmi1_real_t* xnominal, size_t nx) - cpdef set_allocated_fmu(self, int value) - cdef class FMUModelBase2(ModelBase): """ FMI Model loaded from a dll. @@ -232,22 +219,22 @@ cdef class FMUModelBase2(ModelBase): cpdef serialized_fmu_state_size(self, state) cdef _add_scalar_variables(self, FMIL.fmi2_import_variable_list_t* variable_list) cdef _add_scalar_variable(self, FMIL.fmi2_import_variable_t* variable) - cdef int _get_directional_derivative(self, N.ndarray v_ref, N.ndarray z_ref, N.ndarray dv, N.ndarray dz) except -1 + cdef int _get_directional_derivative(self, np.ndarray v_ref, np.ndarray z_ref, np.ndarray dv, np.ndarray dz) except -1 cpdef set_real(self, valueref, values) - cpdef N.ndarray get_real(self, valueref) - cdef int _set_real(self, FMIL.fmi2_value_reference_t* vrefs, FMIL.fmi2_real_t* values, size_t size) - cdef int _get_real_by_ptr(self, FMIL.fmi2_value_reference_t* vrefs, size_t size, FMIL.fmi2_real_t* values) - cdef int _get_real_by_list(self, FMIL.fmi2_value_reference_t[:] valueref, size_t size, FMIL.fmi2_real_t[:] values) - cdef int _get_integer(self, FMIL.fmi2_value_reference_t[:] valueref, size_t size, FMIL.fmi2_integer_t[:] values) - cdef int _get_boolean(self, FMIL.fmi2_value_reference_t[:] valueref, size_t size, FMIL.fmi2_real_t[:] values) + cpdef np.ndarray get_real(self, valueref) + cdef int _set_real(self, FMIL.fmi2_value_reference_t* vrefs, FMIL.fmi2_real_t* values, size_t _size) + cdef int _get_real_by_ptr(self, FMIL.fmi2_value_reference_t* vrefs, size_t _size, FMIL.fmi2_real_t* values) + cdef int _get_real_by_list(self, FMIL.fmi2_value_reference_t[:] valueref, size_t _size, FMIL.fmi2_real_t[:] values) + cdef int _get_integer(self, FMIL.fmi2_value_reference_t[:] valueref, size_t _size, FMIL.fmi2_integer_t[:] values) + cdef int _get_boolean(self, FMIL.fmi2_value_reference_t[:] valueref, size_t _size, FMIL.fmi2_real_t[:] values) cdef class FMUModelCS2(FMUModelBase2): cpdef _get_time(self) cpdef _set_time(self, FMIL.fmi2_real_t t) cpdef int do_step(self, FMIL.fmi2_real_t current_t, FMIL.fmi2_real_t step_size, new_step=*) - cdef int _set_input_derivatives(self, N.ndarray value_refs, N.ndarray values, N.ndarray orders) - cdef int _get_output_derivatives(self, N.ndarray value_refs, N.ndarray values, N.ndarray orders) + cdef int _set_input_derivatives(self, np.ndarray value_refs, np.ndarray values, np.ndarray orders) + cdef int _get_output_derivatives(self, np.ndarray value_refs, np.ndarray values, np.ndarray orders) cdef class FMUModelME2(FMUModelBase2): @@ -266,20 +253,11 @@ cdef class FMUModelME2(FMUModelBase2): cdef class WorkerClass2: cdef int _dim - cdef N.ndarray _tmp1_val, _tmp2_val, _tmp3_val, _tmp4_val - cdef N.ndarray _tmp1_ref, _tmp2_ref, _tmp3_ref, _tmp4_ref + cdef np.ndarray _tmp1_val, _tmp2_val, _tmp3_val, _tmp4_val + cdef np.ndarray _tmp1_ref, _tmp2_ref, _tmp3_ref, _tmp4_ref cdef FMIL.fmi2_real_t* get_real_vector(self, int index) cdef FMIL.fmi2_value_reference_t* get_value_reference_vector(self, int index) - cdef N.ndarray get_value_reference_numpy_vector(self, int index) - cdef N.ndarray get_real_numpy_vector(self, int index) + cdef np.ndarray get_value_reference_numpy_vector(self, int index) + cdef np.ndarray get_real_numpy_vector(self, int index) cpdef verify_dimensions(self, int dim) - -cdef class _ForTestingFMUModelME2(FMUModelME2): - cdef int _get_real_by_ptr(self, FMIL.fmi2_value_reference_t* vrefs, size_t size, FMIL.fmi2_real_t* values) - cdef int _set_real(self, FMIL.fmi2_value_reference_t* vrefs, FMIL.fmi2_real_t* values, size_t size) - cdef int _get_real_by_list(self, FMIL.fmi2_value_reference_t[:] valueref, size_t size, FMIL.fmi2_real_t[:] values) - cdef int _get_integer(self, FMIL.fmi2_value_reference_t[:] valueref, size_t size, FMIL.fmi2_integer_t[:] values) - cdef int _get_boolean(self, FMIL.fmi2_value_reference_t[:] valueref, size_t size, FMIL.fmi2_real_t[:] values) - cdef int _get_nominal_continuous_states_fmil(self, FMIL.fmi2_real_t* xnominal, size_t nx) - cpdef set_initialized_fmu(self, int value) diff --git a/src/pyfmi/fmi.pyx b/src/pyfmi/fmi.pyx index e60b8268..13263331 100644 --- a/src/pyfmi/fmi.pyx +++ b/src/pyfmi/fmi.pyx @@ -27,7 +27,6 @@ For profiling: # distutils: define_macros=CYTHON_TRACE_NOGIL=1 """ import os -import sys import logging import fnmatch import re @@ -35,21 +34,20 @@ from collections import OrderedDict cimport cython from io import UnsupportedOperation -import scipy.sparse as sp -import numpy as N -cimport numpy as N +import scipy.sparse as sps +import numpy as np +cimport numpy as np from numpy cimport PyArray_DATA cimport pyfmi.fmil_import as FMIL -from pyfmi.common.core import create_temp_dir, delete_temp_dir -from pyfmi.common.core import create_temp_file, delete_temp_file +from pyfmi.common.core import create_temp_dir -from pyfmi.fmi_util import cpr_seed, enable_caching, python3_flag +from pyfmi.fmi_util import cpr_seed, enable_caching from pyfmi.fmi_util cimport encode, decode -int = N.int32 -N.int = N.int32 +int = np.int32 +np.int = np.int32 """Basic flags related to FMI""" @@ -143,8 +141,8 @@ FMI2_INITIAL_UNKNOWN = 3 DEF FORWARD_DIFFERENCE = 1 DEF CENTRAL_DIFFERENCE = 2 -FORWARD_DIFFERENCE_EPS = (N.finfo(float).eps)**0.5 -CENTRAL_DIFFERENCE_EPS = (N.finfo(float).eps)**(1/3.0) +FORWARD_DIFFERENCE_EPS = (np.finfo(float).eps)**0.5 +CENTRAL_DIFFERENCE_EPS = (np.finfo(float).eps)**(1/3.0) """Flags for evaluation of FMI Jacobians""" """Evaluate Jacobian w.r.t. states.""" @@ -1158,7 +1156,7 @@ cdef class IntegerType2(DeclaredType2): """ Class defining data structure based on the XML element Enumeration. """ - def __init__(self, name, description = "", quantity = "", min = -N.inf, max = N.inf): + def __init__(self, name, description = "", quantity = "", min = -np.inf, max = np.inf): DeclaredType2.__init__(self, name, description, quantity) self._min = min @@ -1190,7 +1188,7 @@ cdef class RealType2(DeclaredType2): """ Class defining data structure based on the XML element Enumeration. """ - def __init__(self, name, description = "", quantity = "", min = -N.inf, max = N.inf, nominal = 1.0, unbounded = False, + def __init__(self, name, description = "", quantity = "", min = -np.inf, max = np.inf, nominal = 1.0, unbounded = False, relative_quantity = False, display_unit = "", unit = ""): DeclaredType2.__init__(self, name, description, quantity) @@ -1544,9 +1542,9 @@ cdef class FMUModelBase(ModelBase): Calls the low-level FMI function: fmiGetReal """ cdef int status - cdef N.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] val_ref = N.array(valueref, copy=False, dtype=N.uint32).ravel() - cdef FMIL.size_t nref = N.size(val_ref) - cdef N.ndarray[FMIL.fmi1_real_t, ndim=1,mode='c'] val = N.array([0.0]*nref, dtype=float, ndmin=1) + cdef np.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] val_ref = np.array(valueref, copy=False, dtype=np.uint32).ravel() + cdef FMIL.size_t nref = np.size(val_ref) + cdef np.ndarray[FMIL.fmi1_real_t, ndim=1,mode='c'] val = np.array([0.0]*nref, dtype=float, ndmin=1) if nref == 0: ## get_real([]) return val @@ -1577,11 +1575,11 @@ cdef class FMUModelBase(ModelBase): Calls the low-level FMI function: fmiSetReal """ cdef int status - cdef N.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] val_ref = N.array(valueref, copy=False, dtype=N.uint32).ravel() - cdef N.ndarray[FMIL.fmi1_real_t, ndim=1,mode='c'] val = N.array(values, copy=False, dtype=float).ravel() - cdef FMIL.size_t nref = N.size(val_ref) + cdef np.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] val_ref = np.array(valueref, copy=False, dtype=np.uint32).ravel() + cdef np.ndarray[FMIL.fmi1_real_t, ndim=1,mode='c'] val = np.array(values, copy=False, dtype=float).ravel() + cdef FMIL.size_t nref = np.size(val_ref) - if nref != N.size(val): + if nref != np.size(val): raise FMUException( 'The length of valueref and values are inconsistent.') @@ -1611,9 +1609,9 @@ cdef class FMUModelBase(ModelBase): Calls the low-level FMI function: fmiGetInteger """ cdef int status - cdef N.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] val_ref = N.array(valueref, dtype=N.uint32,ndmin=1).ravel() - cdef FMIL.size_t nref = N.size(val_ref) - cdef N.ndarray[FMIL.fmi1_integer_t, ndim=1,mode='c'] val = N.array([0]*nref, dtype=int,ndmin=1) + cdef np.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] val_ref = np.array(valueref, dtype=np.uint32,ndmin=1).ravel() + cdef FMIL.size_t nref = np.size(val_ref) + cdef np.ndarray[FMIL.fmi1_integer_t, ndim=1,mode='c'] val = np.array([0]*nref, dtype=int,ndmin=1) if nref == 0: ## get_integer([]) return val @@ -1644,11 +1642,11 @@ cdef class FMUModelBase(ModelBase): Calls the low-level FMI function: fmiSetInteger """ cdef int status - cdef N.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] val_ref = N.array(valueref, dtype=N.uint32,ndmin=1).ravel() - cdef N.ndarray[FMIL.fmi1_integer_t, ndim=1,mode='c'] val = N.array(values, dtype=int,ndmin=1).ravel() - cdef FMIL.size_t nref = N.size(val_ref) + cdef np.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] val_ref = np.array(valueref, dtype=np.uint32,ndmin=1).ravel() + cdef np.ndarray[FMIL.fmi1_integer_t, ndim=1,mode='c'] val = np.array(values, dtype=int,ndmin=1).ravel() + cdef FMIL.size_t nref = np.size(val_ref) - if nref != N.size(val): + if nref != np.size(val): raise FMUException( 'The length of valueref and values are inconsistent.') @@ -1679,11 +1677,11 @@ cdef class FMUModelBase(ModelBase): Calls the low-level FMI function: fmiGetBoolean """ cdef int status - cdef N.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] val_ref = N.array(valueref, dtype=N.uint32,ndmin=1).ravel() - cdef FMIL.size_t nref = N.size(val_ref) + cdef np.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] val_ref = np.array(valueref, dtype=np.uint32,ndmin=1).ravel() + cdef FMIL.size_t nref = np.size(val_ref) if nref == 0: ## get_boolean([]) - return N.array([]) + return np.array([]) cdef void *val = FMIL.malloc(sizeof(FMIL.fmi1_boolean_t)*nref) @@ -1699,7 +1697,7 @@ cdef class FMUModelBase(ModelBase): if status != 0: raise FMUException('Failed to get the Boolean values.') - return N.array(return_values) + return np.array(return_values) def set_boolean(self, valueref, values): """ @@ -1720,19 +1718,19 @@ cdef class FMUModelBase(ModelBase): Calls the low-level FMI function: fmiSetBoolean """ cdef int status - cdef N.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] val_ref = N.array(valueref, dtype=N.uint32,ndmin=1).ravel() - cdef FMIL.size_t nref = N.size(val_ref) + cdef np.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] val_ref = np.array(valueref, dtype=np.uint32,ndmin=1).ravel() + cdef FMIL.size_t nref = np.size(val_ref) cdef void *val = FMIL.malloc(sizeof(FMIL.fmi1_boolean_t)*nref) - values = N.array(values,ndmin=1).ravel() + values = np.array(values,ndmin=1).ravel() for i in range(nref): if values[i]: (val)[i] = 1 else: (val)[i] = 0 - if nref != N.size(values): + if nref != np.size(values): raise FMUException( 'The length of valueref and values are inconsistent.') @@ -1764,8 +1762,8 @@ cdef class FMUModelBase(ModelBase): Calls the low-level FMI function: fmiGetString """ cdef int status - cdef N.ndarray[FMIL.fmi1_value_reference_t, ndim=1, mode='c'] input_valueref = N.array(valueref, dtype=N.uint32, ndmin=1).ravel() - cdef FMIL.size_t nref = N.size(input_valueref) + cdef np.ndarray[FMIL.fmi1_value_reference_t, ndim=1, mode='c'] input_valueref = np.array(valueref, dtype=np.uint32, ndmin=1).ravel() + cdef FMIL.size_t nref = np.size(input_valueref) if nref == 0: ## get_string([]) return [] @@ -1803,21 +1801,21 @@ cdef class FMUModelBase(ModelBase): Calls the low-level FMI function: fmiSetString """ cdef int status - cdef N.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] val_ref = N.array(valueref, dtype=N.uint32,ndmin=1).ravel() - cdef FMIL.fmi1_string_t* val = FMIL.malloc(sizeof(FMIL.fmi1_string_t)*N.size(val_ref)) + cdef np.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] val_ref = np.array(valueref, dtype=np.uint32,ndmin=1).ravel() + cdef FMIL.fmi1_string_t* val = FMIL.malloc(sizeof(FMIL.fmi1_string_t)*np.size(val_ref)) if not isinstance(values, list): raise FMUException( 'The values needs to be a list of values.') - if len(values) != N.size(val_ref): + if len(values) != np.size(val_ref): raise FMUException( 'The length of valueref and values are inconsistent.') values = [encode(item) for item in values] - for i in range(N.size(val_ref)): + for i in range(np.size(val_ref)): val[i] = values[i] - status = FMIL.fmi1_import_set_string(self._fmu, val_ref.data, N.size(val_ref), val) + status = FMIL.fmi1_import_set_string(self._fmu, val_ref.data, np.size(val_ref), val) FMIL.free(val) @@ -2888,9 +2886,9 @@ cdef class FMUModelCS1(FMUModelBase): cdef int status cdef unsigned int max_output_derivative cdef FMIL.size_t nref - cdef N.ndarray[FMIL.fmi1_real_t, ndim=1,mode='c'] values - cdef N.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] value_refs - cdef N.ndarray[FMIL.fmi1_integer_t, ndim=1,mode='c'] orders + cdef np.ndarray[FMIL.fmi1_real_t, ndim=1,mode='c'] values + cdef np.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] value_refs + cdef np.ndarray[FMIL.fmi1_integer_t, ndim=1,mode='c'] orders cdef FMIL.fmi1_import_capabilities_t *fmu_capabilities fmu_capabilities = FMIL.fmi1_import_get_capabilities(self._fmu) @@ -2901,20 +2899,20 @@ cdef class FMUModelCS1(FMUModelBase): if isinstance(variables,str): nref = 1 - value_refs = N.array([0], dtype=N.uint32,ndmin=1).ravel() - orders = N.array(order, dtype=N.int32) + value_refs = np.array([0], dtype=np.uint32,ndmin=1).ravel() + orders = np.array(order, dtype=np.int32) value_refs[0] = self.get_variable_valueref(variables) elif isinstance(variables,list) and isinstance(variables[-1],str): nref = len(variables) - value_refs = N.array([0]*nref, dtype=N.uint32,ndmin=1).ravel() - orders = N.array([0]*nref, dtype=N.int32) + value_refs = np.array([0]*nref, dtype=np.uint32,ndmin=1).ravel() + orders = np.array([0]*nref, dtype=np.int32) for i in range(nref): value_refs[i] = self.get_variable_valueref(variables[i]) orders[i] = order else: raise FMUException("The variables must either be a string or a list of strings") - values = N.array([0.0]*nref,dtype=float, ndmin=1) + values = np.array([0.0]*nref,dtype=float, ndmin=1) status = FMIL.fmi1_import_get_real_output_derivatives(self._fmu, value_refs.data, nref, orders.data, values.data) @@ -2976,30 +2974,30 @@ cdef class FMUModelCS1(FMUModelBase): cdef int status cdef int can_interpolate_inputs cdef FMIL.fmi1_import_capabilities_t *fmu_capabilities - cdef N.ndarray[FMIL.fmi1_integer_t, ndim=1,mode='c'] np_orders = N.array(orders, dtype=N.int32, ndmin=1).ravel() - cdef N.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] value_refs - cdef N.ndarray[FMIL.fmi1_real_t, ndim=1,mode='c'] val = N.array(values, dtype=float, ndmin=1).ravel() - cdef FMIL.size_t nref = N.size(val) - orders = N.array([0]*nref, dtype=N.int32) + cdef np.ndarray[FMIL.fmi1_integer_t, ndim=1,mode='c'] np_orders = np.array(orders, dtype=np.int32, ndmin=1).ravel() + cdef np.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] value_refs + cdef np.ndarray[FMIL.fmi1_real_t, ndim=1,mode='c'] val = np.array(values, dtype=float, ndmin=1).ravel() + cdef FMIL.size_t nref = np.size(val) + orders = np.array([0]*nref, dtype=np.int32) - if nref != N.size(np_orders): + if nref != np.size(np_orders): raise FMUException("The number of variables must be the same as the number of orders.") fmu_capabilities = FMIL.fmi1_import_get_capabilities(self._fmu) can_interpolate_inputs = FMIL.fmi1_import_get_canInterpolateInputs(fmu_capabilities) #NOTE IS THIS THE HIGHEST ORDER OF INTERPOLATION OR SIMPLY IF IT CAN OR NOT? - for i in range(N.size(np_orders)): + for i in range(np.size(np_orders)): if np_orders[i] < 1: raise FMUException("The order must be greater than zero.") if not can_interpolate_inputs: raise FMUException("The FMU does not support input derivatives.") if isinstance(variables,str): - value_refs = N.array([0], dtype=N.uint32,ndmin=1).ravel() + value_refs = np.array([0], dtype=np.uint32,ndmin=1).ravel() value_refs[0] = self.get_variable_valueref(variables) elif isinstance(variables,list) and isinstance(variables[-1],str): - value_refs = N.array([0]*nref, dtype=N.uint32,ndmin=1).ravel() + value_refs = np.array([0]*nref, dtype=np.uint32,ndmin=1).ravel() for i in range(nref): value_refs[i] = self.get_variable_valueref(variables[i]) else: @@ -3404,7 +3402,7 @@ cdef class FMUModelME1(FMUModelBase): def _get_continuous_states(self): cdef int status - cdef N.ndarray[double, ndim=1,mode='c'] ndx = N.zeros(self._nContinuousStates, dtype=N.double) + cdef np.ndarray[double, ndim=1,mode='c'] ndx = np.zeros(self._nContinuousStates, dtype=np.double) status = FMIL.fmi1_import_get_continuous_states(self._fmu, ndx.data ,self._nContinuousStates) if status != 0: @@ -3412,11 +3410,11 @@ cdef class FMUModelME1(FMUModelBase): return ndx - def _set_continuous_states(self, N.ndarray[FMIL.fmi1_real_t] values): + def _set_continuous_states(self, np.ndarray[FMIL.fmi1_real_t] values): cdef int status - cdef N.ndarray[FMIL.fmi1_real_t, ndim=1,mode='c'] ndx = values + cdef np.ndarray[FMIL.fmi1_real_t, ndim=1,mode='c'] ndx = values - if N.size(ndx) != self._nContinuousStates: + if np.size(ndx) != self._nContinuousStates: raise FMUException( 'Failed to set the new continuous states. ' \ 'The number of values are not consistent with the number of '\ @@ -3446,7 +3444,7 @@ cdef class FMUModelME1(FMUModelBase): The nominal values. """ cdef int status - cdef N.ndarray[FMIL.fmi1_real_t, ndim=1, mode='c'] xn = N.zeros(self._nContinuousStates, dtype=N.double) + cdef np.ndarray[FMIL.fmi1_real_t, ndim=1, mode='c'] xn = np.zeros(self._nContinuousStates, dtype=np.double) status = self._get_nominal_continuous_states_fmil( xn.data, self._nContinuousStates) if status != 0: @@ -3496,7 +3494,7 @@ cdef class FMUModelME1(FMUModelBase): Calls the low-level FMI function: fmiGetDerivatives """ cdef int status - cdef N.ndarray[FMIL.fmi1_real_t, ndim=1,mode='c'] values = N.empty(self._nContinuousStates,dtype=N.double) + cdef np.ndarray[FMIL.fmi1_real_t, ndim=1,mode='c'] values = np.empty(self._nContinuousStates,dtype=np.double) if self._nContinuousStates > 0: status = FMIL.fmi1_import_get_derivatives(self._fmu, values.data, self._nContinuousStates) @@ -3524,7 +3522,7 @@ cdef class FMUModelME1(FMUModelBase): Calls the low-level FMI function: fmiGetEventIndicators """ cdef int status - cdef N.ndarray[FMIL.fmi1_real_t, ndim=1,mode='c'] values = N.empty(self._nEventIndicators,dtype=N.double) + cdef np.ndarray[FMIL.fmi1_real_t, ndim=1,mode='c'] values = np.empty(self._nEventIndicators,dtype=np.double) status = FMIL.fmi1_import_get_event_indicators(self._fmu, values.data, self._nEventIndicators) @@ -3681,7 +3679,7 @@ cdef class FMUModelME1(FMUModelBase): Calls the low-level FMI function: fmiGetStateValueReferences """ cdef int status - cdef N.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] values = N.zeros(self._nContinuousStates,dtype=N.uint32) + cdef np.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] values = np.zeros(self._nContinuousStates,dtype=np.uint32) status = FMIL.fmi1_import_get_state_value_references( self._fmu, values.data, self._nContinuousStates) @@ -3945,27 +3943,6 @@ cdef class FMUModelME1(FMUModelBase): self._instantiated_fmu = 0 -cdef class _ForTestingFMUModelME1(FMUModelME1): - - cdef int _get_nominal_continuous_states_fmil(self, FMIL.fmi1_real_t* xnominal, size_t nx): - for i in range(nx): - if self._allocated_fmu == 1: # If initialized - # Set new values to test that atol gets auto-corrected. - xnominal[i] = 3.0 - else: - # Set some illegal values in order to test the fallback/auto-correction. - xnominal[i] = ((( i) % 3) - 1) * 2.0 # -2.0, 0.0, 2.0, - return FMIL.fmi1_status_ok - - cpdef set_allocated_fmu(self, int value): - self._allocated_fmu = value - - def __dealloc__(self): - # Avoid segfaults in dealloc. The FMU binaries should never be loaded for this - # test class, so we should never try to terminate or deallocate the FMU instance. - self._allocated_fmu = 0 - - cdef class FMUModelBase2(ModelBase): """ FMI Model loaded from a dll. @@ -4189,7 +4166,7 @@ cdef class FMUModelBase2(ModelBase): self._log = [] - cpdef N.ndarray get_real(self, valueref): + cpdef np.ndarray get_real(self, valueref): """ Returns the real-values from the valuereference(s). @@ -4210,9 +4187,9 @@ cdef class FMUModelBase2(ModelBase): Calls the low-level FMI function: fmi2GetReal """ cdef int status - cdef N.ndarray[FMIL.fmi2_value_reference_t, ndim=1,mode='c'] input_valueref = N.array(valueref, copy=False, dtype=N.uint32).ravel() - cdef FMIL.size_t nref = N.size(input_valueref) - cdef N.ndarray[FMIL.fmi2_real_t, ndim=1,mode='c'] output_value = N.zeros(nref) + cdef np.ndarray[FMIL.fmi2_value_reference_t, ndim=1,mode='c'] input_valueref = np.array(valueref, copy=False, dtype=np.uint32).ravel() + cdef FMIL.size_t nref = np.size(input_valueref) + cdef np.ndarray[FMIL.fmi2_real_t, ndim=1,mode='c'] output_value = np.zeros(nref) if nref == 0: ## get_real([]) return output_value @@ -4244,28 +4221,28 @@ cdef class FMUModelBase2(ModelBase): """ cdef int status - cdef N.ndarray[FMIL.fmi2_value_reference_t, ndim=1,mode='c'] input_valueref = N.array(valueref, copy=False, dtype=N.uint32).ravel() - cdef N.ndarray[FMIL.fmi2_real_t, ndim=1,mode='c'] set_value = N.array(values, copy=False, dtype=float).ravel() + cdef np.ndarray[FMIL.fmi2_value_reference_t, ndim=1,mode='c'] input_valueref = np.array(valueref, copy=False, dtype=np.uint32).ravel() + cdef np.ndarray[FMIL.fmi2_real_t, ndim=1,mode='c'] set_value = np.array(values, copy=False, dtype=float).ravel() - if N.size(input_valueref) != N.size(set_value): + if np.size(input_valueref) != np.size(set_value): raise FMUException('The length of valueref and values are inconsistent.') - status = FMIL.fmi2_import_set_real(self._fmu, input_valueref.data, N.size(input_valueref), set_value.data) + status = FMIL.fmi2_import_set_real(self._fmu, input_valueref.data, np.size(input_valueref), set_value.data) if status != 0: raise FMUException('Failed to set the Real values. See the log for possibly more information.') - cdef int _get_real_by_list(self, FMIL.fmi2_value_reference_t[:] valueref, size_t size, FMIL.fmi2_real_t[:] values): - return FMIL.fmi2_import_get_real(self._fmu, &valueref[0], size, &values[0]) + cdef int _get_real_by_list(self, FMIL.fmi2_value_reference_t[:] valueref, size_t _size, FMIL.fmi2_real_t[:] values): + return FMIL.fmi2_import_get_real(self._fmu, &valueref[0], _size, &values[0]) - cdef int _get_real_by_ptr(self, FMIL.fmi2_value_reference_t* vrefs, size_t size, FMIL.fmi2_real_t* values): - return FMIL.fmi2_import_get_real(self._fmu, vrefs, size, values) + cdef int _get_real_by_ptr(self, FMIL.fmi2_value_reference_t* vrefs, size_t _size, FMIL.fmi2_real_t* values): + return FMIL.fmi2_import_get_real(self._fmu, vrefs, _size, values) - cdef int _set_real(self, FMIL.fmi2_value_reference_t* vrefs, FMIL.fmi2_real_t* values, size_t size): - return FMIL.fmi2_import_set_real(self._fmu, vrefs, size, values) + cdef int _set_real(self, FMIL.fmi2_value_reference_t* vrefs, FMIL.fmi2_real_t* values, size_t _size): + return FMIL.fmi2_import_set_real(self._fmu, vrefs, _size, values) - cdef int _get_integer(self, FMIL.fmi2_value_reference_t[:] valueref, size_t size, FMIL.fmi2_integer_t[:] values): - return FMIL.fmi2_import_get_integer(self._fmu, &valueref[0], size, &values[0]) + cdef int _get_integer(self, FMIL.fmi2_value_reference_t[:] valueref, size_t _size, FMIL.fmi2_integer_t[:] values): + return FMIL.fmi2_import_get_integer(self._fmu, &valueref[0], _size, &values[0]) def get_integer(self, valueref): """ @@ -4288,9 +4265,9 @@ cdef class FMUModelBase2(ModelBase): Calls the low-level FMI function: fmi2GetInteger """ cdef int status - cdef N.ndarray[FMIL.fmi2_value_reference_t, ndim=1,mode='c'] input_valueref = N.array(valueref, dtype=N.uint32,ndmin=1).ravel() - cdef FMIL.size_t nref = N.size(input_valueref) - cdef N.ndarray[FMIL.fmi2_integer_t, ndim=1,mode='c'] output_value = N.zeros(nref, dtype=int) + cdef np.ndarray[FMIL.fmi2_value_reference_t, ndim=1,mode='c'] input_valueref = np.array(valueref, dtype=np.uint32,ndmin=1).ravel() + cdef FMIL.size_t nref = np.size(input_valueref) + cdef np.ndarray[FMIL.fmi2_integer_t, ndim=1,mode='c'] output_value = np.zeros(nref, dtype=int) if nref == 0: ## get_integer([]) return output_value @@ -4321,11 +4298,11 @@ cdef class FMUModelBase2(ModelBase): Calls the low-level FMI function: fmi2SetInteger """ cdef int status - cdef N.ndarray[FMIL.fmi2_value_reference_t, ndim=1,mode='c'] input_valueref = N.array(valueref, dtype=N.uint32,ndmin=1).ravel() - cdef N.ndarray[FMIL.fmi2_integer_t, ndim=1,mode='c'] set_value = N.array(values, dtype=int,ndmin=1).ravel() - cdef FMIL.size_t nref = N.size(input_valueref) + cdef np.ndarray[FMIL.fmi2_value_reference_t, ndim=1,mode='c'] input_valueref = np.array(valueref, dtype=np.uint32,ndmin=1).ravel() + cdef np.ndarray[FMIL.fmi2_integer_t, ndim=1,mode='c'] set_value = np.array(values, dtype=int,ndmin=1).ravel() + cdef FMIL.size_t nref = np.size(input_valueref) - if nref != N.size(set_value): + if nref != np.size(set_value): raise FMUException('The length of valueref and values are inconsistent.') status = FMIL.fmi2_import_set_integer(self._fmu, input_valueref.data, nref, set_value.data) @@ -4333,13 +4310,13 @@ cdef class FMUModelBase2(ModelBase): if status != 0: raise FMUException('Failed to set the Integer values. See the log for possibly more information.') - cdef int _get_boolean(self, FMIL.fmi2_value_reference_t[:] valueref, size_t size, FMIL.fmi2_real_t[:] values): + cdef int _get_boolean(self, FMIL.fmi2_value_reference_t[:] valueref, size_t _size, FMIL.fmi2_real_t[:] values): cdef int status - cdef void* output_value = FMIL.malloc(sizeof(FMIL.fmi2_boolean_t)*size) + cdef void* output_value = FMIL.malloc(sizeof(FMIL.fmi2_boolean_t)*_size) - status = FMIL.fmi2_import_get_boolean(self._fmu, &valueref[0], size, output_value) + status = FMIL.fmi2_import_get_boolean(self._fmu, &valueref[0], _size, output_value) - for i in range(size): + for i in range(_size): values[i] = (output_value)[i]==1 FMIL.free(output_value) @@ -4367,11 +4344,11 @@ cdef class FMUModelBase2(ModelBase): Calls the low-level FMI function: fmi2GetBoolean """ cdef int status - cdef N.ndarray[FMIL.fmi2_value_reference_t, ndim=1,mode='c'] input_valueref = N.array(valueref, dtype=N.uint32, ndmin=1).ravel() - cdef FMIL.size_t nref = N.size(input_valueref) + cdef np.ndarray[FMIL.fmi2_value_reference_t, ndim=1,mode='c'] input_valueref = np.array(valueref, dtype=np.uint32, ndmin=1).ravel() + cdef FMIL.size_t nref = np.size(input_valueref) if nref == 0: ## get_boolean([]) - return N.array([]) + return np.array([]) cdef void* output_value = FMIL.malloc(sizeof(FMIL.fmi2_boolean_t)*nref) @@ -4387,7 +4364,7 @@ cdef class FMUModelBase2(ModelBase): if status != 0: raise FMUException('Failed to get the Boolean values.') - return N.array(return_values) + return np.array(return_values) def set_boolean(self, valueref, values): """ @@ -4409,12 +4386,12 @@ cdef class FMUModelBase2(ModelBase): """ cdef int status - cdef N.ndarray[FMIL.fmi2_value_reference_t, ndim=1,mode='c'] input_valueref = N.array(valueref, dtype=N.uint32,ndmin=1).flatten() - cdef FMIL.size_t nref = N.size(input_valueref) + cdef np.ndarray[FMIL.fmi2_value_reference_t, ndim=1,mode='c'] input_valueref = np.array(valueref, dtype=np.uint32,ndmin=1).flatten() + cdef FMIL.size_t nref = np.size(input_valueref) cdef void* set_value = FMIL.malloc(sizeof(FMIL.fmi2_boolean_t)*nref) - values = N.array(values,ndmin=1).ravel() + values = np.array(values,ndmin=1).ravel() for i in range(nref): if values[i]: ( set_value)[i] = 1 @@ -4452,8 +4429,8 @@ cdef class FMUModelBase2(ModelBase): Calls the low-level FMI function: fmi2GetString """ cdef int status - cdef N.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode='c'] input_valueref = N.array(valueref, dtype=N.uint32, ndmin=1).ravel() - cdef FMIL.size_t nref = N.size(input_valueref) + cdef np.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode='c'] input_valueref = np.array(valueref, dtype=np.uint32, ndmin=1).ravel() + cdef FMIL.size_t nref = np.size(input_valueref) if nref == 0: ## get_string([]) return [] @@ -4492,21 +4469,21 @@ cdef class FMUModelBase2(ModelBase): Calls the low-level FMI function: fmi2SetString """ cdef int status - cdef N.ndarray[FMIL.fmi2_value_reference_t, ndim=1,mode='c'] val_ref = N.array(valueref, dtype=N.uint32,ndmin=1).ravel() - cdef FMIL.fmi2_string_t* val = FMIL.malloc(sizeof(FMIL.fmi2_string_t)*N.size(val_ref)) + cdef np.ndarray[FMIL.fmi2_value_reference_t, ndim=1,mode='c'] val_ref = np.array(valueref, dtype=np.uint32,ndmin=1).ravel() + cdef FMIL.fmi2_string_t* val = FMIL.malloc(sizeof(FMIL.fmi2_string_t)*np.size(val_ref)) if not isinstance(values, list): raise FMUException( 'The values needs to be a list of values.') - if len(values) != N.size(val_ref): + if len(values) != np.size(val_ref): raise FMUException( 'The length of valueref and values are inconsistent.') values = [encode(item) for item in values] - for i in range(N.size(val_ref)): + for i in range(np.size(val_ref)): val[i] = values[i] - status = FMIL.fmi2_import_set_string(self._fmu, val_ref.data, N.size(val_ref), val) + status = FMIL.fmi2_import_set_string(self._fmu, val_ref.data, np.size(val_ref), val) FMIL.free(val) @@ -6119,7 +6096,7 @@ cdef class FMUModelBase2(ModelBase): cdef FMUState2 internal_state = state cdef FMIL.size_t n_bytes - cdef N.ndarray[FMIL.fmi2_byte_t, ndim=1, mode='c'] serialized_fmu + cdef np.ndarray[FMIL.fmi2_byte_t, ndim=1, mode='c'] serialized_fmu cap1 = FMIL.fmi2_import_get_capability(self._fmu, FMIL.fmi2_me_canSerializeFMUstate) cap2 = FMIL.fmi2_import_get_capability(self._fmu, FMIL.fmi2_cs_canSerializeFMUstate) @@ -6127,7 +6104,7 @@ cdef class FMUModelBase2(ModelBase): raise FMUException('This FMU dos not support serialisation of FMU-state') n_bytes = self.serialized_fmu_state_size(state) - serialized_fmu = N.empty(n_bytes, dtype=N.byte) + serialized_fmu = np.empty(n_bytes, dtype=np.byte) status = FMIL.fmi2_import_serialize_fmu_state(self._fmu, internal_state.fmu_state, serialized_fmu.data, n_bytes) @@ -6159,7 +6136,7 @@ cdef class FMUModelBase2(ModelBase): """ cdef int status - cdef N.ndarray[FMIL.fmi2_byte_t, ndim=1, mode='c'] ser_fmu = serialized_fmu[0] + cdef np.ndarray[FMIL.fmi2_byte_t, ndim=1, mode='c'] ser_fmu = serialized_fmu[0] cdef FMUState2 state = FMUState2() cdef FMIL.size_t n_byte = len(ser_fmu) @@ -6327,18 +6304,11 @@ cdef class FMUModelBase2(ModelBase): cdef FMIL.fmi2_import_variable_t *variable cdef FMIL.fmi2_import_variable_list_t *variable_list - if python3_flag: - outputs = list(self.get_output_list().keys()) - states_dict = self.get_states_list() - states_list = list(states_dict.keys()) - inputs_dict = self.get_input_list() - inputs_list = list(inputs_dict.keys()) - else: - outputs = self.get_output_list().keys() - states_dict = self.get_states_list() - states_list = states_dict.keys() - inputs_dict = self.get_input_list() - inputs_list = inputs_dict.keys() + outputs = list(self.get_output_list().keys()) + states_dict = self.get_states_list() + states_list = list(states_dict.keys()) + inputs_dict = self.get_input_list() + inputs_list = list(inputs_dict.keys()) states = OrderedDict() states_kind = OrderedDict() @@ -6435,14 +6405,9 @@ cdef class FMUModelBase2(ModelBase): cdef FMIL.fmi2_import_variable_t *variable cdef FMIL.fmi2_import_variable_list_t *variable_list - if python3_flag: - derivatives = list(self.get_derivatives_list().keys()) - states_list = list(self.get_states_list().keys()) - inputs_list = list(self.get_input_list().keys()) - else: - derivatives = self.get_derivatives_list().keys() - states_list = self.get_states_list().keys() - inputs_list = self.get_input_list().keys() + derivatives = list(self.get_derivatives_list().keys()) + states_list = list(self.get_states_list().keys()) + inputs_list = list(self.get_input_list().keys()) states = OrderedDict() states_kind = OrderedDict() @@ -6520,8 +6485,8 @@ cdef class FMUModelBase2(ModelBase): cdef list data = [], row = [], col = [] cdef list local_group cdef int nbr_var_ref = len(var_ref), nbr_func_ref = len(func_ref) - cdef N.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] v = N.zeros(nbr_var_ref, dtype = N.double) - cdef N.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] data_local + cdef np.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] v = np.zeros(nbr_var_ref, dtype = np.double) + cdef np.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] data_local cdef int ind_local = 5 if add_diag else 4 if not self._has_entered_init_mode: @@ -6530,7 +6495,7 @@ cdef class FMUModelBase2(ModelBase): if group is not None: if output_matrix is not None: - if not isinstance(output_matrix, sp.csc_matrix): + if not isinstance(output_matrix, sps.csc_matrix): output_matrix = None else: data_local = output_matrix.data @@ -6561,16 +6526,16 @@ cdef class FMUModelBase2(ModelBase): A = output_matrix else: if len(data) == 0: - A = sp.csc_matrix((nbr_func_ref,nbr_var_ref)) + A = sps.csc_matrix((nbr_func_ref,nbr_var_ref)) else: - A = sp.csc_matrix((data, (row, col)), (nbr_func_ref,nbr_var_ref)) + A = sps.csc_matrix((data, (row, col)), (nbr_func_ref,nbr_var_ref)) return A else: if output_matrix is None or \ - (not isinstance(output_matrix, N.ndarray)) or \ - (isinstance(output_matrix, N.ndarray) and (output_matrix.shape[0] != nbr_func_ref or output_matrix.shape[1] != nbr_var_ref)): - A = N.zeros((nbr_func_ref,nbr_var_ref)) + (not isinstance(output_matrix, np.ndarray)) or \ + (isinstance(output_matrix, np.ndarray) and (output_matrix.shape[0] != nbr_func_ref or output_matrix.shape[1] != nbr_var_ref)): + A = np.zeros((nbr_func_ref,nbr_var_ref)) else: A = output_matrix @@ -6583,10 +6548,7 @@ cdef class FMUModelBase2(ModelBase): def _get_A(self, use_structure_info=True, add_diag=True, output_matrix=None): if self._group_A is None and use_structure_info: [derv_state_dep, derv_input_dep] = self.get_derivatives_dependencies() - if python3_flag: - self._group_A = cpr_seed(derv_state_dep, list(self.get_states_list().keys())) - else: - self._group_A = cpr_seed(derv_state_dep, self.get_states_list().keys()) + self._group_A = cpr_seed(derv_state_dep, list(self.get_states_list().keys())) if self._states_references is None: states = self.get_states_list() self._states_references = [s.value_reference for s in states.values()] @@ -6604,10 +6566,7 @@ cdef class FMUModelBase2(ModelBase): def _get_B(self, use_structure_info=True, add_diag=False, output_matrix=None): if self._group_B is None and use_structure_info: [derv_state_dep, derv_input_dep] = self.get_derivatives_dependencies() - if python3_flag: - self._group_B = cpr_seed(derv_input_dep, list(self.get_input_list().keys())) - else: - self._group_B = cpr_seed(derv_input_dep, self.get_input_list().keys()) + self._group_B = cpr_seed(derv_input_dep, list(self.get_input_list().keys())) if self._inputs_references is None: inputs = self.get_input_list() self._inputs_references = [s.value_reference for s in inputs.values()] @@ -6625,10 +6584,7 @@ cdef class FMUModelBase2(ModelBase): def _get_C(self, use_structure_info=True, add_diag=False, output_matrix=None): if self._group_C is None and use_structure_info: [out_state_dep, out_input_dep] = self.get_output_dependencies() - if python3_flag: - self._group_C = cpr_seed(out_state_dep, list(self.get_states_list().keys())) - else: - self._group_C = cpr_seed(out_state_dep, self.get_states_list().keys()) + self._group_C = cpr_seed(out_state_dep, list(self.get_states_list().keys())) if self._states_references is None: states = self.get_states_list() self._states_references = [s.value_reference for s in states.values()] @@ -6646,10 +6602,7 @@ cdef class FMUModelBase2(ModelBase): def _get_D(self, use_structure_info=True, add_diag=False, output_matrix=None): if self._group_D is None and use_structure_info: [out_state_dep, out_input_dep] = self.get_output_dependencies() - if python3_flag: - self._group_D = cpr_seed(out_input_dep, list(self.get_input_list().keys())) - else: - self._group_D = cpr_seed(out_input_dep, self.get_input_list().keys()) + self._group_D = cpr_seed(out_input_dep, list(self.get_input_list().keys())) if self._inputs_references is None: inputs = self.get_input_list() self._inputs_references = [s.value_reference for s in inputs.values()] @@ -6841,11 +6794,11 @@ cdef class FMUModelBase2(ModelBase): cdef FMIL.size_t nv, nz #input arrays - cdef N.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode='c'] v_ref = N.zeros(len(var_ref), dtype = N.uint32) - cdef N.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode='c'] z_ref = N.zeros(len(func_ref), dtype = N.uint32) - cdef N.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] dv = N.zeros(len(v), dtype = N.double) + cdef np.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode='c'] v_ref = np.zeros(len(var_ref), dtype = np.uint32) + cdef np.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode='c'] z_ref = np.zeros(len(func_ref), dtype = np.uint32) + cdef np.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] dv = np.zeros(len(v), dtype = np.double) #output array - cdef N.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] dz = N.zeros(len(func_ref), dtype = N.double) + cdef np.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] dz = np.zeros(len(func_ref), dtype = np.double) if not self._provides_directional_derivatives(): raise FMUException('This FMU does not provide directional derivatives') @@ -6870,20 +6823,20 @@ cdef class FMUModelBase2(ModelBase): return dz - cdef int _get_directional_derivative(self, N.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode="c"] v_ref, - N.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode="c"] z_ref, - N.ndarray[FMIL.fmi2_real_t, ndim=1, mode="c"] dv, - N.ndarray[FMIL.fmi2_real_t, ndim=1, mode="c"] dz) except -1: + cdef int _get_directional_derivative(self, np.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode="c"] v_ref, + np.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode="c"] z_ref, + np.ndarray[FMIL.fmi2_real_t, ndim=1, mode="c"] dv, + np.ndarray[FMIL.fmi2_real_t, ndim=1, mode="c"] dz) except -1: cdef int status - assert N.size(dv) >= N.size(v_ref) and N.size(dz) >= N.size(z_ref) + assert np.size(dv) >= np.size(v_ref) and np.size(dz) >= np.size(z_ref) if not self._provides_directional_derivatives(): raise FMUException('This FMU does not provide directional derivatives') status = FMIL.fmi2_import_get_directional_derivative(self._fmu, - v_ref.data, N.size(v_ref), - z_ref.data, N.size(z_ref), + v_ref.data, np.size(v_ref), + z_ref.data, np.size(z_ref), dv.data, dz.data) @@ -7194,11 +7147,11 @@ cdef class FMUModelCS2(FMUModelBase2): """ cdef int status cdef unsigned int can_interpolate_inputs - cdef N.ndarray[FMIL.fmi2_integer_t, ndim=1, mode='c'] orders - cdef N.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode='c'] value_refs - cdef N.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] val = N.array(values, dtype=float, ndmin=1).ravel() - cdef FMIL.size_t nref = N.size(val) - orders = N.array([0]*nref, dtype=N.int32) + cdef np.ndarray[FMIL.fmi2_integer_t, ndim=1, mode='c'] orders + cdef np.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode='c'] value_refs + cdef np.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] val = np.array(values, dtype=float, ndmin=1).ravel() + cdef FMIL.size_t nref = np.size(val) + orders = np.array([0]*nref, dtype=np.int32) can_interpolate_inputs = FMIL.fmi2_import_get_capability(self._fmu, FMIL.fmi2_cs_canInterpolateInputs) #NOTE IS THIS THE HIGHEST ORDER OF INTERPOLATION OR SIMPLY IF IT CAN OR NOT? @@ -7209,10 +7162,10 @@ cdef class FMUModelCS2(FMUModelBase2): raise FMUException("The FMU does not support input derivatives.") if isinstance(variables,str): - value_refs = N.array([0], dtype=N.uint32, ndmin=1).ravel() + value_refs = np.array([0], dtype=np.uint32, ndmin=1).ravel() value_refs[0] = self.get_variable_valueref(variables) - elif isinstance(variables,list) and N.prod([int(isinstance(v,str)) for v in variables]): #prod equals 0 or 1 - value_refs = N.array([0]*nref, dtype=N.uint32,ndmin=1).ravel() + elif isinstance(variables,list) and np.prod([int(isinstance(v,str)) for v in variables]): #prod equals 0 or 1 + value_refs = np.array([0]*nref, dtype=np.uint32,ndmin=1).ravel() for i in range(nref): value_refs[i] = self.get_variable_valueref(variables[i]) orders[i] = order @@ -7226,16 +7179,16 @@ cdef class FMUModelCS2(FMUModelBase2): if status != 0: raise FMUException('Failed to set the Real input derivatives.') - cdef int _set_input_derivatives(self, N.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode="c"] value_refs, - N.ndarray[FMIL.fmi2_real_t, ndim=1, mode="c"] values, - N.ndarray[FMIL.fmi2_integer_t, ndim=1, mode="c"] orders): + cdef int _set_input_derivatives(self, np.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode="c"] value_refs, + np.ndarray[FMIL.fmi2_real_t, ndim=1, mode="c"] values, + np.ndarray[FMIL.fmi2_integer_t, ndim=1, mode="c"] orders): cdef int status - assert N.size(values) >= N.size(value_refs) and N.size(orders) >= N.size(value_refs) + assert np.size(values) >= np.size(value_refs) and np.size(orders) >= np.size(value_refs) status = FMIL.fmi2_import_set_real_input_derivatives(self._fmu, value_refs.data, - N.size(value_refs), orders.data, + np.size(value_refs), orders.data, values.data) return status @@ -7261,9 +7214,9 @@ cdef class FMUModelCS2(FMUModelBase2): cdef int status cdef unsigned int max_output_derivative cdef FMIL.size_t nref - cdef N.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] values - cdef N.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode='c'] value_refs - cdef N.ndarray[FMIL.fmi2_integer_t, ndim=1, mode='c'] orders + cdef np.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] values + cdef np.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode='c'] value_refs + cdef np.ndarray[FMIL.fmi2_integer_t, ndim=1, mode='c'] orders max_output_derivative = FMIL.fmi2_import_get_capability(self._fmu, FMIL.fmi2_cs_maxOutputDerivativeOrder) @@ -7272,20 +7225,20 @@ cdef class FMUModelCS2(FMUModelBase2): if isinstance(variables,str): nref = 1 - value_refs = N.array([0], dtype=N.uint32, ndmin=1).ravel() - orders = N.array([order], dtype=N.int32) + value_refs = np.array([0], dtype=np.uint32, ndmin=1).ravel() + orders = np.array([order], dtype=np.int32) value_refs[0] = self.get_variable_valueref(variables) - elif isinstance(variables,list) and N.prod([int(isinstance(v,str)) for v in variables]): #prod equals 0 or 1 + elif isinstance(variables,list) and np.prod([int(isinstance(v,str)) for v in variables]): #prod equals 0 or 1 nref = len(variables) - value_refs = N.array([0]*nref, dtype=N.uint32, ndmin=1).ravel() - orders = N.array([0]*nref, dtype=N.int32) + value_refs = np.array([0]*nref, dtype=np.uint32, ndmin=1).ravel() + orders = np.array([0]*nref, dtype=np.int32) for i in range(nref): value_refs[i] = self.get_variable_valueref(variables[i]) orders[i] = order else: raise FMUException("The variables must either be a string or a list of strings") - values = N.array([0.0]*nref, dtype=float, ndmin=1) + values = np.array([0.0]*nref, dtype=float, ndmin=1) #status = FMIL.fmi2_import_get_real_output_derivatives(self._fmu, value_refs.data, nref, # orders.data, values.data) @@ -7296,15 +7249,15 @@ cdef class FMUModelCS2(FMUModelBase2): return values - cdef int _get_output_derivatives(self, N.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode="c"] value_refs, - N.ndarray[FMIL.fmi2_real_t, ndim=1, mode="c"] values, - N.ndarray[FMIL.fmi2_integer_t, ndim=1, mode="c"] orders): + cdef int _get_output_derivatives(self, np.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode="c"] value_refs, + np.ndarray[FMIL.fmi2_real_t, ndim=1, mode="c"] values, + np.ndarray[FMIL.fmi2_integer_t, ndim=1, mode="c"] orders): cdef int status - assert N.size(values) >= N.size(value_refs) and N.size(orders) >= N.size(value_refs) + assert np.size(values) >= np.size(value_refs) and np.size(orders) >= np.size(value_refs) status = FMIL.fmi2_import_get_real_output_derivatives(self._fmu, - value_refs.data, N.size(value_refs), + value_refs.data, np.size(value_refs), orders.data, values.data) return status @@ -7813,7 +7766,7 @@ cdef class FMUModelME2(FMUModelBase2): cdef int _get_event_indicators(self, FMIL.fmi2_real_t[:] values): #if not values.flags['C_CONTIGUOUS']: - # values = N.ascontiguousarray(values) + # values = np.ascontiguousarray(values) if self._nEventIndicators > 0: return FMIL.fmi2_import_get_event_indicators(self._fmu, &values[0], self._nEventIndicators) else: @@ -7835,7 +7788,7 @@ cdef class FMUModelME2(FMUModelBase2): Calls the low-level FMI function: fmiGetEventIndicators """ cdef int status - cdef N.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] values = N.empty(self._nEventIndicators, dtype=N.double) + cdef np.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] values = np.empty(self._nEventIndicators, dtype=np.double) status = self._get_event_indicators(values) @@ -8009,7 +7962,7 @@ cdef class FMUModelME2(FMUModelBase2): The continuous states. """ cdef int status - cdef N.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] ndx = N.zeros(self._nContinuousStates, dtype=N.double) + cdef np.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] ndx = np.zeros(self._nContinuousStates, dtype=np.double) status = self._get_continuous_states_fmil(ndx) if status != 0: @@ -8023,7 +7976,7 @@ cdef class FMUModelME2(FMUModelBase2): else: return FMIL.fmi2_status_ok - def _set_continuous_states(self, N.ndarray[FMIL.fmi2_real_t, ndim=1, mode="c"] values): + def _set_continuous_states(self, np.ndarray[FMIL.fmi2_real_t, ndim=1, mode="c"] values): """ Set the values of the continuous states. @@ -8033,9 +7986,9 @@ cdef class FMUModelME2(FMUModelBase2): The new values of the continuous states. """ cdef int status - cdef N.ndarray[FMIL.fmi2_real_t, ndim=1,mode='c'] ndx = values + cdef np.ndarray[FMIL.fmi2_real_t, ndim=1,mode='c'] ndx = values - if N.size(ndx) != self._nContinuousStates: + if np.size(ndx) != self._nContinuousStates: raise FMUException( 'Failed to set the new continuous states. ' \ 'The number of values are not consistent with the number of '\ @@ -8064,7 +8017,7 @@ cdef class FMUModelME2(FMUModelBase2): The nominal values. """ cdef int status - cdef N.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] xn = N.zeros(self._nContinuousStates, dtype=N.double) + cdef np.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] xn = np.zeros(self._nContinuousStates, dtype=np.double) status = self._get_nominal_continuous_states_fmil( xn.data, self._nContinuousStates) if status != 0: @@ -8118,7 +8071,7 @@ cdef class FMUModelME2(FMUModelBase2): Calls the low-level FMI function: fmi2GetDerivatives """ cdef int status - cdef N.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] values = N.empty(self._nContinuousStates, dtype = N.double) + cdef np.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] values = np.empty(self._nContinuousStates, dtype = np.double) status = self._get_derivatives(values) @@ -8283,9 +8236,9 @@ cdef class FMUModelME2(FMUModelBase2): cdef double tmp_nominal, fac, tmp cdef int method = FORWARD_DIFFERENCE if self.force_finite_differences is True or self.force_finite_differences == 0 else CENTRAL_DIFFERENCE cdef double RUROUND = FORWARD_DIFFERENCE_EPS if method == FORWARD_DIFFERENCE else CENTRAL_DIFFERENCE_EPS - cdef N.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] dfpert, df, eps, nominals - cdef N.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode='c'] v_ref = N.array(var_ref, copy=False, dtype = N.uint32) - cdef N.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode='c'] z_ref = N.array(func_ref, copy=False, dtype = N.uint32) + cdef np.ndarray[FMIL.fmi2_real_t, ndim=1, mode='c'] dfpert, df, eps, nominals + cdef np.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode='c'] v_ref = np.array(var_ref, copy=False, dtype = np.uint32) + cdef np.ndarray[FMIL.fmi2_value_reference_t, ndim=1, mode='c'] z_ref = np.array(func_ref, copy=False, dtype = np.uint32) cdef int ind_local = 5 if add_diag else 4 cdef list local_group @@ -8330,11 +8283,11 @@ cdef class FMUModelME2(FMUModelBase2): else: # First time extraction of nominals #If we are using the states, then the nominals should instead be picked up from the C callback function for nominals if self._states_references and len_v == len(self._states_references) and (self._states_references[i] == var_ref[i] for i in range(len_v)): - group["nominals"] = N.array(self.nominal_continuous_states, dtype=float) + group["nominals"] = np.array(self.nominal_continuous_states, dtype=float) nominals = group["nominals"] nominals_pt = PyArray_DATA(nominals) else: - group["nominals"] = N.empty(len_v, dtype=float) + group["nominals"] = np.empty(len_v, dtype=float) nominals = group["nominals"] nominals_pt = PyArray_DATA(nominals) for i in range(len_v): @@ -8349,7 +8302,7 @@ cdef class FMUModelME2(FMUModelBase2): if group is not None: if output_matrix is not None: - if not isinstance(output_matrix, sp.csc_matrix): + if not isinstance(output_matrix, sps.csc_matrix): output_matrix = None else: output_matrix_data_pt = PyArray_DATA(output_matrix.data) @@ -8442,23 +8395,23 @@ cdef class FMUModelME2(FMUModelBase2): A = output_matrix else: if len(data) == 0: - A = sp.csc_matrix((len_f,len_v)) + A = sps.csc_matrix((len_f,len_v)) else: - A = sp.csc_matrix((data, (row, col)), (len_f,len_v)) + A = sps.csc_matrix((data, (row, col)), (len_f,len_v)) return A else: if output_matrix is None or \ - (not isinstance(output_matrix, N.ndarray)) or \ - (isinstance(output_matrix, N.ndarray) and (output_matrix.shape[0] != len_f or output_matrix.shape[1] != len_v)): - A = N.zeros((len_f,len_v)) + (not isinstance(output_matrix, np.ndarray)) or \ + (isinstance(output_matrix, np.ndarray) and (output_matrix.shape[0] != len_f or output_matrix.shape[1] != len_v)): + A = np.zeros((len_f,len_v)) else: A = output_matrix if len_v == 0 or len_f == 0: return A - dfpert = N.zeros(len_f, dtype = N.double) + dfpert = np.zeros(len_f, dtype = np.double) df = df[:len_f] #Should be removed in the future for i in range(len_v): tmp = v_pt[i] @@ -8497,80 +8450,6 @@ cdef class FMUModelME2(FMUModelBase2): return A -cdef class _ForTestingFMUModelME2(FMUModelME2): - cdef int _get_real_by_ptr(self, FMIL.fmi2_value_reference_t* vrefs, size_t size, FMIL.fmi2_real_t* values): - vr = N.zeros(size) - for i in range(size): - vr[i] = vrefs[i] - - try: - vv = self.get_real(vr) - except Exception: - return FMIL.fmi2_status_error - - for i in range(size): - values[i] = vv[i] - - return FMIL.fmi2_status_ok - - cdef int _set_real(self, FMIL.fmi2_value_reference_t* vrefs, FMIL.fmi2_real_t* values, size_t size): - vr = N.zeros(size) - vv = N.zeros(size) - for i in range(size): - vr[i] = vrefs[i] - vv[i] = values[i] - - try: - self.set_real(vr, vv) - except Exception: - return FMIL.fmi2_status_error - - return FMIL.fmi2_status_ok - - cdef int _get_real_by_list(self, FMIL.fmi2_value_reference_t[:] valueref, size_t size, FMIL.fmi2_real_t[:] values): - try: - tmp = self.get_real(valueref) - for i in range(size): - values[i] = tmp[i] - except Exception: - return FMIL.fmi2_status_error - return FMIL.fmi2_status_ok - - cdef int _get_integer(self, FMIL.fmi2_value_reference_t[:] valueref, size_t size, FMIL.fmi2_integer_t[:] values): - try: - tmp = self.get_integer(valueref) - for i in range(size): - values[i] = tmp[i] - except Exception: - return FMIL.fmi2_status_error - return FMIL.fmi2_status_ok - - cdef int _get_boolean(self, FMIL.fmi2_value_reference_t[:] valueref, size_t size, FMIL.fmi2_real_t[:] values): - try: - tmp = self.get_boolean(valueref) - for i in range(size): - values[i] = tmp[i] - except Exception: - return FMIL.fmi2_status_error - return FMIL.fmi2_status_ok - - cdef int _get_nominal_continuous_states_fmil(self, FMIL.fmi2_real_t* xnominal, size_t nx): - for i in range(nx): - if self._initialized_fmu == 1: - # Set new values to test that atol gets auto-corrected. - xnominal[i] = 3.0 - else: - # Set some illegal values in order to test the fallback/auto-correction. - xnominal[i] = ((( i) % 3) - 1) * 2.0 # -2.0, 0.0, 2.0, - return FMIL.fmi2_status_ok - - cpdef set_initialized_fmu(self, int value): - self._initialized_fmu = value - - def __dealloc__(self): - # Avoid segfaults in dealloc. The FMU binaries should never be loaded for this - # test class, so we should never try to terminate or deallocate the FMU instance. - self._initialized_fmu = 0 def _handle_load_fmu_exception(fmu, log_data): for log in log_data: @@ -8856,22 +8735,22 @@ cdef class WorkerClass2: self._dim = 0 def _update_work_vectors(self, dim): - self._tmp1_val = N.zeros(dim, dtype = N.double) - self._tmp2_val = N.zeros(dim, dtype = N.double) - self._tmp3_val = N.zeros(dim, dtype = N.double) - self._tmp4_val = N.zeros(dim, dtype = N.double) + self._tmp1_val = np.zeros(dim, dtype = np.double) + self._tmp2_val = np.zeros(dim, dtype = np.double) + self._tmp3_val = np.zeros(dim, dtype = np.double) + self._tmp4_val = np.zeros(dim, dtype = np.double) - self._tmp1_ref = N.zeros(dim, dtype = N.uint32) - self._tmp2_ref = N.zeros(dim, dtype = N.uint32) - self._tmp3_ref = N.zeros(dim, dtype = N.uint32) - self._tmp4_ref = N.zeros(dim, dtype = N.uint32) + self._tmp1_ref = np.zeros(dim, dtype = np.uint32) + self._tmp2_ref = np.zeros(dim, dtype = np.uint32) + self._tmp3_ref = np.zeros(dim, dtype = np.uint32) + self._tmp4_ref = np.zeros(dim, dtype = np.uint32) cpdef verify_dimensions(self, int dim): if dim > self._dim: self._update_work_vectors(dim) - cdef N.ndarray get_real_numpy_vector(self, int index): - cdef N.ndarray ret = None + cdef np.ndarray get_real_numpy_vector(self, int index): + cdef np.ndarray ret = None if index == 0: ret = self._tmp1_val @@ -8897,8 +8776,8 @@ cdef class WorkerClass2: return ret - cdef N.ndarray get_value_reference_numpy_vector(self, int index): - cdef N.ndarray ret = None + cdef np.ndarray get_value_reference_numpy_vector(self, int index): + cdef np.ndarray ret = None if index == 0: ret = self._tmp1_ref diff --git a/src/pyfmi/fmi_algorithm_drivers.py b/src/pyfmi/fmi_algorithm_drivers.py index d68065ab..1f0f4869 100644 --- a/src/pyfmi/fmi_algorithm_drivers.py +++ b/src/pyfmi/fmi_algorithm_drivers.py @@ -19,10 +19,10 @@ pyfmi.fmi.FMUModel*.simulate. """ -#from abc import ABCMeta, abstractmethod import logging as logging_module import time -import numpy as N +import numpy as np +import scipy.optimize as spopt import pyfmi.fmi as fmi import pyfmi.fmi_coupled as fmi_coupled @@ -36,8 +36,8 @@ from timeit import default_timer as timer default_int = int -int = N.int32 -N.int = N.int32 +int = np.int32 +np.int = np.int32 PYFMI_JACOBIAN_LIMIT = 10 PYFMI_JACOBIAN_SPARSE_SIZE_LIMIT = 100 @@ -584,10 +584,10 @@ def _set_options(self): self.solver_options['rtol'] = rtol #rtol was provided as a vector - if isinstance(self.solver_options["rtol"], N.ndarray) or isinstance(self.solver_options["rtol"], list): + if isinstance(self.solver_options["rtol"], np.ndarray) or isinstance(self.solver_options["rtol"], list): #rtol all are all equal -> set it as scalar and use that - if N.all(N.isclose(self.solver_options["rtol"], self.solver_options["rtol"][0])): + if np.all(np.isclose(self.solver_options["rtol"], self.solver_options["rtol"][0])): self.solver_options["rtol"] = self.solver_options["rtol"][0] self.rtol = self.solver_options["rtol"] @@ -640,7 +640,7 @@ def _set_options(self): except KeyError: #Need to calculate the nnz. [derv_state_dep, derv_input_dep] = self.model.get_derivatives_dependencies() - nnz = N.sum([len(derv_state_dep[key]) for key in derv_state_dep.keys()])+fnbr + nnz = np.sum([len(derv_state_dep[key]) for key in derv_state_dep.keys()])+fnbr if nnz/float(fnbr*fnbr) <= PYFMI_JACOBIAN_SPARSE_NNZ_LIMIT: self.solver_options["linear_solver"] = "SPARSE" else: @@ -666,7 +666,7 @@ def _set_absolute_tolerance_options(self): self.solver_options["atol"] = 0.01*self.rtol else: self.solver_options["atol"] = 0.01*self.rtol*self.model.nominal_continuous_states - elif isinstance(preinit_nominals, N.ndarray) and (N.size(preinit_nominals) > 0): + elif isinstance(preinit_nominals, np.ndarray) and (np.size(preinit_nominals) > 0): # Heuristic: # Try to find if atol was specified as "atol = factor * model.nominal_continuous_states", # and if that's the case, recompute atol with nominals from after initialization. @@ -713,7 +713,7 @@ def _set_solver_options(self): solver_options["maxh"] = float(self.final_time - self.start_time) / float(self.options["ncp"]) if "rtol" in solver_options: - rtol_is_vector = (isinstance(self.solver_options["rtol"], N.ndarray) or isinstance(self.solver_options["rtol"], list)) + rtol_is_vector = (isinstance(self.solver_options["rtol"], np.ndarray) or isinstance(self.solver_options["rtol"], list)) rtol_vector_support = self.simulator.supports.get("rtol_as_vector", False) if rtol_is_vector and not rtol_vector_support and self._rtol_as_scalar_fallback: @@ -1095,7 +1095,7 @@ def solve(self): """ result_handler = self.result_handler h = (self.final_time-self.start_time)/self.ncp - grid = N.linspace(self.start_time,self.final_time,self.ncp+1)[:-1] + grid = np.linspace(self.start_time,self.final_time,self.ncp+1)[:-1] status = 0 final_time = self.start_time @@ -1277,7 +1277,7 @@ def _set_options(self): scale = [] for parameter in self.parameters: scale.append(self.model.get_variable_nominal(parameter)) - self.options["scaling"] = N.array(scale) + self.options["scaling"] = np.array(scale) if self.options["simulate_options"] == "Default": self.options["simulate_options"] = self.model.simulate_options() @@ -1302,8 +1302,6 @@ def solve(self): """ Runs the estimation. """ - import scipy as sci - import scipy.optimize as sciopt from pyfmi.fmi_util import parameter_estimation_f #Define callback @@ -1323,13 +1321,13 @@ def parameter_estimation_callback(y): p0 = [] for i,parameter in enumerate(self.parameters): p0.append(self.model.get(parameter)/self.options["scaling"][i]) - p0 = N.array(p0).flatten() + p0 = np.array(p0).flatten() print('\nRunning solver: ' + self.options["method"]) print(' Initial parameters (scaled): ' + str(p0)) print(' ') - res = sciopt.minimize(parameter_estimation_f, p0, + res = spopt.minimize(parameter_estimation_f, p0, args=(self.parameters, self.measurements, self.model, self.input, self.options), method=self.options["method"], bounds=None, diff --git a/src/pyfmi/fmi_coupled.pyx b/src/pyfmi/fmi_coupled.pyx index debfb55f..c821917b 100644 --- a/src/pyfmi/fmi_coupled.pyx +++ b/src/pyfmi/fmi_coupled.pyx @@ -17,25 +17,18 @@ # distutils: define_macros=NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION +import time +import numpy as np +cimport numpy as np + import pyfmi.fmi as fmi from pyfmi.fmi cimport FMUModelME2 cimport fmil_import as FMIL -from pyfmi.fmi_util import cpr_seed, enable_caching, Graph +from pyfmi.fmi_util import enable_caching, Graph from collections import OrderedDict -import time -import warnings -import numpy as np -cimport numpy as np -import scipy.optimize as sopt -import scipy - -try: - from numpy.lib import NumpyVersion - USE_ROOT = NumpyVersion(scipy.version.version) >= "0.11.0" -except ImportError: #Numpy version is < 1.9.0 so assume scipy version is the same - USE_ROOT = False +import scipy.optimize as spopt def init_f_block(u, coupled, block): @@ -1986,12 +1979,8 @@ cdef class CoupledFMUModelME2(CoupledFMUModelBase): u = np.array(u).ravel() success = False - if USE_ROOT: - res = sopt.root(init_f_block, u, args=(self,block)) - success = res["success"] - else: - [res, info, ier, msg] = sopt.fsolve(init_f_block, u, args=(self,block), full_output=True) - success = True if ier == 1 else False + res = spopt.root(init_f_block, u, args=(self,block)) + success = res["success"] if not success: raise fmi.FMUException("Failed to converge the block.") @@ -2000,10 +1989,7 @@ cdef class CoupledFMUModelME2(CoupledFMUModelBase): for model in block["outputs"].keys(): self.get_specific_connection_outputs(model, block["outputs_mask"][model], y) - if USE_ROOT: - res = sopt.root(init_f_block, y[block["global_outputs_mask"]], args=(self,block)) - else: - res = sopt.fsolve(init_f_block, y[block["global_outputs_mask"]], args=(self,block)) + res = spopt.root(init_f_block, y[block["global_outputs_mask"]], args=(self,block)) if not res["success"]: print res raise Exception("Failed to converge the initialization system.") diff --git a/src/pyfmi/fmi_extended.pyx b/src/pyfmi/fmi_extended.pyx index 01ee7045..894e5693 100644 --- a/src/pyfmi/fmi_extended.pyx +++ b/src/pyfmi/fmi_extended.pyx @@ -20,22 +20,15 @@ """ Module containing the FMI interface Python wrappers. """ -import os -import sys -import logging -import fnmatch -import re -from collections import OrderedDict - -import numpy as N -cimport numpy as N -N.import_array() +import logging +import numpy as np +cimport numpy as np cimport fmil_import as FMIL from pyfmi.fmi cimport FMUModelME1 from pyfmi.fmi import FMUException -from pyfmi.fmi import FMI_OK, FMI_DEFAULT_LOG_LEVEL, FMI_ME +from pyfmi.fmi import FMI_OK, FMI_DEFAULT_LOG_LEVEL cdef class FMUModelME1Extended(FMUModelME1): @@ -45,7 +38,7 @@ cdef class FMUModelME1Extended(FMUModelME1): cdef public list _input_value_refs, _input_alias_type, _input_factorials cdef public int _input_active, _input_order cdef public dict _input_derivatives, _options - cdef public N.ndarray _input_tmp + cdef public np.ndarray _input_tmp def __init__(self, fmu, log_file_name="", log_level=FMI_DEFAULT_LOG_LEVEL, _connect_dll=True): #Instantiate the FMU @@ -59,7 +52,7 @@ cdef class FMUModelME1Extended(FMUModelME1): for name in vars.keys(): input_value_refs.append(self.get_variable_valueref(name)) input_alias_type.append(-1.0 if self.get_variable_alias(name)[name] == -1 else 1.0) - assert not N.any(input_alias_type == -1) + assert not np.any(input_alias_type == -1) self._input_derivatives = {} for val_ref in input_value_refs: @@ -104,7 +97,7 @@ cdef class FMUModelME1Extended(FMUModelME1): cdef void _eval_input(self, double time): cdef int i,j - cdef N.ndarray input_tmp = self._input_tmp.copy() + cdef np.ndarray input_tmp = self._input_tmp.copy() for i,ref in enumerate(self._input_value_refs): for j in range(self._input_order): @@ -133,7 +126,7 @@ cdef class FMUModelME1Extended(FMUModelME1): Calls the low-level FMI function: fmiGetDerivatives """ cdef int status - cdef N.ndarray[FMIL.fmi1_real_t, ndim=1,mode='c'] values = N.empty(self._nContinuousStates,dtype=N.double) + cdef np.ndarray[FMIL.fmi1_real_t, ndim=1,mode='c'] values = np.empty(self._nContinuousStates,dtype=np.double) if self._input_active: self._eval_input(self.time) @@ -288,12 +281,12 @@ cdef class FMUModelME1Extended(FMUModelME1): """ cdef int status cdef FMIL.size_t nref - cdef N.ndarray[FMIL.fmi1_integer_t, ndim=1,mode='c'] np_orders = N.array(orders, dtype=N.int32, ndmin=1).flatten() - cdef N.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] value_refs - cdef N.ndarray[FMIL.fmi1_real_t, ndim=1,mode='c'] val = N.array(values, dtype=float, ndmin=1).flatten() + cdef np.ndarray[FMIL.fmi1_integer_t, ndim=1,mode='c'] np_orders = np.array(orders, dtype=np.int32, ndmin=1).flatten() + cdef np.ndarray[FMIL.fmi1_value_reference_t, ndim=1,mode='c'] value_refs + cdef np.ndarray[FMIL.fmi1_real_t, ndim=1,mode='c'] val = np.array(values, dtype=float, ndmin=1).flatten() nref = len(val) - orders = N.array([0]*nref, dtype=N.int32) + orders = np.array([0]*nref, dtype=np.int32) if nref != len(np_orders): raise FMUException("The number of variables must be the same as the number of orders.") @@ -305,10 +298,10 @@ cdef class FMUModelME1Extended(FMUModelME1): self._input_order = np_orders[i] if isinstance(variables,str): - value_refs = N.array([0], dtype=N.uint32,ndmin=1).flatten() + value_refs = np.array([0], dtype=np.uint32,ndmin=1).flatten() value_refs[0] = self.get_variable_valueref(variables) elif isinstance(variables,list) and isinstance(variables[-1],str): - value_refs = N.array([0]*nref, dtype=N.uint32,ndmin=1).flatten() + value_refs = np.array([0]*nref, dtype=np.uint32,ndmin=1).flatten() for i in range(nref): value_refs[i] = self.get_variable_valueref(variables[i]) else: diff --git a/src/pyfmi/fmi_util.pyx b/src/pyfmi/fmi_util.pyx index e126eb57..deae039b 100644 --- a/src/pyfmi/fmi_util.pyx +++ b/src/pyfmi/fmi_util.pyx @@ -21,44 +21,29 @@ Module containing the FMI interface Python wrappers. """ import collections -from collections import OrderedDict import itertools -from operator import attrgetter -import numpy as np -from numpy.compat import asbytes - -from pyfmi.common import encode +import numpy as np cimport numpy as np -cimport fmil_import as FMIL -from cpython cimport array -from pyfmi.fmi cimport FMUModelME2, FMUModelBase +cimport fmil_import as FMIL +from pyfmi.fmi cimport FMUModelME2 import functools import marshal import pyfmi.fmi as fmi -import sys - -python3_flag = True if sys.hexversion > 0x03000000 else False cpdef decode(x): - if python3_flag: - if isinstance(x, bytes): - return x.decode(errors="replace") - else: - return x + if isinstance(x, bytes): + return x.decode(errors="replace") else: return x cpdef encode(x): - if python3_flag: - if isinstance(x, str): - return x.encode() - else: - return x + if isinstance(x, str): + return x.encode() else: - return x.encode("utf-8") + return x def enable_caching(obj): @functools.wraps(obj, ('__name__', '__doc__')) @@ -97,10 +82,7 @@ cpdef cpr_seed(dependencies, list column_keys, dict interested_columns = None): data_index = {} data_index_with_diag = {} for i in range(n_col): - if python3_flag: - data_index[i] = list(range(k, k + len(column_dict[i]))) - else: - data_index[i] = range(k, k + len(column_dict[i])) + data_index[i] = list(range(k, k + len(column_dict[i]))) k = k + len(column_dict[i]) data_index_with_diag[i] = [] @@ -224,17 +206,11 @@ cpdef list convert_array_names_list_names(np.ndarray names): cpdef list convert_array_names_list_names_int(np.ndarray[int, ndim=2] names): cdef int max_length = names.shape[0] cdef int nbr_items = names.shape[1] - cdef int i, py3, j = 0, ch + cdef int i, j = 0, ch cdef char *tmp = FMIL.calloc(max_length,sizeof(char)) cdef list output = [] cdef bytes py_str - # This if-statement is contributes to a performance gain within the for-loop that follows - if python3_flag: - py3 = 1 - else: - py3 = 0 - for i in range(nbr_items): for j in range(max_length): ch = names[j,i] @@ -245,10 +221,7 @@ cpdef list convert_array_names_list_names_int(np.ndarray[int, ndim=2] names): py_str = tmp[:j] if j == max_length - 1: - if py3: - py_str = py_str.replace(b" ", b"") - else: - py_str = py_str.replace(" ", "") + py_str = py_str.replace(b" ", b"") output.append(py_str) FMIL.free(tmp) @@ -667,7 +640,7 @@ class Graph: if self.graph_info[node]["type"] == GRAPH_OUTPUT: model = self.graph_info[node]["model"] if not (model in trees): - trees[model] = OrderedDict() + trees[model] = collections.OrderedDict() trees[model][node] = self.dfs(node) joined_nodes[node] = [node] else: @@ -1029,14 +1002,14 @@ class Graph: cdef class DumpData: def __init__(self, model, filep, real_var_ref, int_var_ref, bool_var_ref, with_diagnostics): - if type(model) != FMUModelME2: - self.real_var_ref = np.array(real_var_ref, ndmin=1).ravel() - self.int_var_ref = np.array(int_var_ref, ndmin=1).ravel() - self.bool_var_ref = np.array(bool_var_ref, ndmin=1).ravel() - else: + if type(model) == FMUModelME2: self.real_var_ref = np.array(real_var_ref, dtype=np.uint32, ndmin=1).ravel() self.int_var_ref = np.array(int_var_ref, dtype=np.uint32, ndmin=1).ravel() self.bool_var_ref = np.array(bool_var_ref, dtype=np.uint32, ndmin=1).ravel() + else: + self.real_var_ref = np.array(real_var_ref, ndmin=1).ravel() + self.int_var_ref = np.array(int_var_ref, ndmin=1).ravel() + self.bool_var_ref = np.array(bool_var_ref, ndmin=1).ravel() self.real_size = np.size(self.real_var_ref) self.int_size = np.size(self.int_var_ref) @@ -1065,7 +1038,7 @@ cdef class DumpData: if self._with_diagnostics: self.dump_data(np.array(float(1.0))) if self.model_me2_instance: - self.time_tmp[0] = self.model_me2._get_time() + self.time_tmp[0] = self.model_me2.time self.dump_data(self.time_tmp) if self.real_size > 0: @@ -1099,7 +1072,7 @@ cdef class DumpData: """ Saves a point of diagnostics data to the result. """ self.dump_data(np.array(float(2.0))) if self.model_me2_instance: - self.time_tmp[0] = self.model_me2._get_time() + self.time_tmp[0] = self.model_me2.time self.dump_data(self.time_tmp) else: self.dump_data(np.array(float(self.model.time))) @@ -1330,17 +1303,12 @@ def read_name_list(file_name, int file_position, int nbr_variables, int max_leng A dict with the names as key and an index as value """ - cdef int i = 0, j = 0, py3, need_replace = 0 + cdef int i = 0, j = 0, need_replace = 0 cdef FILE* cfile cdef char *tmp = FMIL.calloc(max_length,sizeof(char)) cdef bytes py_str cdef dict data = {} - # This if-statement contributes to a performance gain within the for-loop that follows - if python3_flag: - py3 = 1 - else: - py3 = 0 if tmp == NULL: raise fmi.IOException("Couldn't allocate memory to read name list.") @@ -1355,10 +1323,7 @@ def read_name_list(file_name, int file_position, int nbr_variables, int max_leng need_replace = 1 if need_replace: - if py3: - py_str = py_str.replace(b" ", b"") - else: - py_str = py_str.replace(" ", "") + py_str = py_str.replace(b" ", b"") data[py_str] = i fclose(cfile) diff --git a/src/pyfmi/master.pyx b/src/pyfmi/master.pyx index 4d0a9a89..29e205d8 100644 --- a/src/pyfmi/master.pyx +++ b/src/pyfmi/master.pyx @@ -17,33 +17,28 @@ # distutils: define_macros=NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION -import pyfmi.fmi as fmi -from pyfmi.common.algorithm_drivers import OptionBase, InvalidAlgorithmOptionException, AssimuloSimResult -from pyfmi.common.io import ResultDymolaTextual, ResultHandlerFile, ResultHandlerDummy, ResultHandlerBinaryFile, ResultDymolaBinary -from pyfmi.common.core import TrajectoryLinearInterpolation -from pyfmi.common.core import TrajectoryUserFunction - -from timeit import default_timer as timer - import fnmatch import sys -import re -from collections import OrderedDict import time -import numpy as np import warnings +from collections import OrderedDict +from timeit import default_timer as timer +from cpython cimport bool +from cython.parallel import prange, parallel + +import numpy as np cimport numpy as np -import scipy.sparse as sp -import scipy.linalg as lin -import scipy.sparse.linalg as splin -import scipy.optimize as sopt -import scipy.version +import scipy as sp +import scipy.sparse as sps +import scipy.optimize as spopt +import pyfmi.fmi as fmi +from pyfmi.common.algorithm_drivers import OptionBase, InvalidAlgorithmOptionException, AssimuloSimResult +from pyfmi.common.io import ResultHandlerFile, ResultHandlerDummy, ResultHandlerBinaryFile +from pyfmi.common.core import TrajectoryLinearInterpolation, TrajectoryUserFunction from pyfmi.fmi cimport FMUModelCS2 -from cpython cimport bool cimport fmil_import as FMIL from pyfmi.fmi_util import Graph -from cython.parallel import prange, parallel IF WITH_OPENMP: cimport openmp @@ -51,12 +46,6 @@ IF WITH_OPENMP: DEF SERIAL = 0 DEF PARALLEL = 1 -try: - from numpy.lib import NumpyVersion - USE_ROOT = NumpyVersion(scipy.version.version) >= "0.11.0" -except ImportError: #Numpy version is < 1.9.0 so assume scipy version is the same - USE_ROOT = False - cdef reset_models(list models): for model in models: model.reset() @@ -469,7 +458,7 @@ cdef class Master: self.y_prev = None self.input_traj = None - self._ident_matrix = sp.eye(self._len_inputs, self._len_outputs, format="csr") #y = Cx + Du , u = Ly -> DLy DL[inputsXoutputs] + self._ident_matrix = sps.eye(self._len_inputs, self._len_outputs, format="csr") #y = Cx + Du , u = Ly -> DLy DL[inputsXoutputs] self._error_data = {"time":[], "error":[], "step-size":[], "rejected":[]} @@ -568,8 +557,8 @@ cdef class Master: col_discrete.append(self.models_dict[src]["global_index_outputs_discrete"]+self.models_dict[src]["local_output_discrete"].index(src_var)) len_connections_discrete = len_connections_discrete + 1 - self.L = sp.csr_matrix((data, (row, col)), (len_connections,len_connections), dtype=np.float64) - self.L_discrete = sp.csr_matrix((data_discrete, (row_discrete, col_discrete)), (len_connections_discrete,len_connections_discrete), dtype=np.float64) + self.L = sps.csr_matrix((data, (row, col)), (len_connections,len_connections), dtype=np.float64) + self.L_discrete = sps.csr_matrix((data_discrete, (row_discrete, col_discrete)), (len_connections_discrete,len_connections_discrete), dtype=np.float64) cpdef compute_global_D(self): cdef list data = [] @@ -610,7 +599,7 @@ cdef class Master: col = self._storedDcol if self._D is None: - self._D = sp.csr_matrix((data, (row, col)))#, (len(col),len(row))) + self._D = sps.csr_matrix((data, (row, col)))#, (len(col),len(row))) else: self._D.data = np.array(data, dtype=np.float64) @@ -631,7 +620,7 @@ cdef class Master: data.extend(local_C) col.extend([self.models_dict[model]["global_index_states"]+i]*len(local_C)) row.extend(np.array([self.models_dict[model]["global_index_outputs"]]*len(self.models_dict[model]["local_output_vref"]))+np.array(range(len(self.models_dict[model]["local_output_vref"])))) - return sp.csr_matrix((data, (row, col))) + return sps.csr_matrix((data, (row, col))) def compute_global_A(self): cdef list data = [] @@ -647,7 +636,7 @@ cdef class Master: data.extend(local_A) col.extend([self.models_dict[model]["global_index_states"]+i]*len(local_A)) row.extend(np.array([self.models_dict[model]["global_index_derivatives"]]*len(self.models_dict[model]["local_derivative_vref"]))+np.array(range(len(self.models_dict[model]["local_derivative_vref"])))) - return sp.csr_matrix((data, (row, col))) + return sps.csr_matrix((data, (row, col))) def compute_global_B(self): cdef list data = [] @@ -663,7 +652,7 @@ cdef class Master: data.extend(local_B) col.extend([self.models_dict[model]["global_index_inputs"]+i]*len(local_B)) row.extend(np.array([self.models_dict[model]["global_index_derivatives"]]*len(self.models_dict[model]["local_derivative_vref"]))+np.array(range(len(self.models_dict[model]["local_derivative_vref"])))) - return sp.csr_matrix((data, (row, col))) + return sps.csr_matrix((data, (row, col))) def connection_setup(self, connections): for connection in connections: @@ -854,7 +843,7 @@ cdef class Master: else: return C.dot(xd)+D.dot(ud) else: #First step - return splin.spsolve((self._ident_matrix-D.dot(self.L)),C.dot(xd)).reshape((-1,1)) + return sps.linalg.spsolve((self._ident_matrix-D.dot(self.L)),C.dot(xd)).reshape((-1,1)) y_last = self.get_last_y() if y_last is not None: @@ -899,7 +888,7 @@ cdef class Master: if ud is not None and udd is not None: return C.dot(A.dot(xd))+C.dot(B.dot(ud+self.get_current_step_size()*udd))+D.dot(udd) else: #First step - return splin.spsolve((self._ident_matrix-D.dot(self.L)),C.dot(A.dot(xd)+B.dot(self.L.dot(yd_cur)))).reshape((-1,1)) + return sps.linalg.spsolve((self._ident_matrix-D.dot(self.L)),C.dot(A.dot(xd)+B.dot(self.L.dot(yd_cur)))).reshape((-1,1)) yd_last = self.get_last_yd() if yd_last is not None: @@ -966,7 +955,7 @@ cdef class Master: z = yd - D.dot(uhat) - yd = splin.spsolve((self._ident_matrix-DL),z).reshape((-1,1)) + yd = sps.linalg.spsolve((self._ident_matrix-DL),z).reshape((-1,1)) """ return ydd @@ -981,7 +970,7 @@ cdef class Master: z = yd - D.dot(uhat) - yd = splin.spsolve((self._ident_matrix-DL),z).reshape((-1,1)) + yd = sps.linalg.spsolve((self._ident_matrix-DL),z).reshape((-1,1)) return yd @@ -993,10 +982,7 @@ cdef class Master: JM_FMUS = False break if JM_FMUS: - if USE_ROOT: - res = sopt.root(init_f, y, args=(self)) - else: - res = sopt.fsolve(init_f, y, args=(self)) + res = spopt.root(init_f, y, args=(self)) if not res["success"]: print(res) raise fmi.FMUException("Failed to converge the output system.") @@ -1009,16 +995,11 @@ cdef class Master: if self.opts["extrapolation_order"] > 0: uold, udold, uddold = self.get_last_us() uhat = uold + (self.get_current_step_size()*udold if udold is not None else 0.0) - z = y - D.dot(uhat) - #z = y - matvec(D,uhat.ravel()) else: - z = y - DL.dot(y_prev) - #z = y - matvec(DL, y_prev.ravel()) - y = splin.spsolve((self._ident_matrix-DL),z).reshape((-1,1)) - #y = splin.lsqr((sp.eye(*DL.shape)-DL),z)[0].reshape((-1,1)) + y = sps.linalg.spsolve((self._ident_matrix-DL),z).reshape((-1,1)) elif self.algebraic_loops and self.support_directional_derivatives: pass @@ -1125,10 +1106,7 @@ cdef class Master: for model in block["outputs"].keys(): self.get_specific_connection_outputs(model, block["outputs_mask"][model], y) - if USE_ROOT: - res = sopt.root(init_f_block, y[block["global_outputs_mask"]], args=(self,block)) - else: - res = sopt.fsolve(init_f_block, y[block["global_outputs_mask"]], args=(self,block)) + res = spopt.root(init_f_block, y[block["global_outputs_mask"]], args=(self,block)) if not res["success"]: print(res) raise fmi.FMUException("Failed to converge the initialization system.") @@ -1150,15 +1128,9 @@ cdef class Master: if self.algebraic_loops: #If there is an algebraic loop, solve the resulting system if self.support_directional_derivatives: - if USE_ROOT: - res = sopt.root(init_f, self.get_connection_outputs(), args=(self), jac=init_jac) - else: - res = sopt.fsolve(init_f, self.get_connection_outputs(), args=(self), jac=init_jac) + res = spopt.root(init_f, self.get_connection_outputs(), args=(self), jac=init_jac) else: - if USE_ROOT: - res = sopt.root(init_f, self.get_connection_outputs(), args=(self)) - else: - res = sopt.fsolve(init_f, self.get_connection_outputs(), args=(self)) + res = spopt.root(init_f, self.get_connection_outputs(), args=(self)) if not res["success"]: print(res) raise fmi.FMUException("Failed to converge the initialization system.") @@ -1334,27 +1306,25 @@ cdef class Master: if opts["logging"]: D = self.compute_global_D() DL = D.dot(self.L) - import numpy.linalg - import scipy.linalg as slin - print("At time: %E , rho(DL)=%s"%(tcur + step_size, str(numpy.linalg.eig(DL.todense())[0]))) + print("At time: %E , rho(DL)=%s"%(tcur + step_size, str(np.linalg.eig(DL.todense())[0]))) C = self.compute_global_C() if C is not None: C = C.todense() _ident_matrix = np.eye(*DL.shape) - LIDLC = self.L.dot(lin.solve(_ident_matrix-DL,C)) - print(" , rho(L(I-DL)^(-1)C)=%s"%(str(numpy.linalg.eig(LIDLC)[0]))) + LIDLC = self.L.dot(np.linalg.solve(_ident_matrix-DL,C)) + print(" , rho(L(I-DL)^(-1)C)=%s"%(str(np.linalg.eig(LIDLC)[0]))) A = self.compute_global_A() B = self.compute_global_B() if C is not None and A is not None and B is not None: A = A.todense(); B = B.todense() - eAH = slin.expm(A*step_size) - K1 = lin.solve(_ident_matrix-DL,C) - K2 = lin.solve(A,(eAH-np.eye(*eAH.shape)).dot(B.dot(self.L.todense()))) + eAH = sp.linalg.expm(A*step_size) + K1 = np.linalg.solve(_ident_matrix-DL,C) + K2 = np.linalg.solve(A,(eAH-np.eye(*eAH.shape)).dot(B.dot(self.L.todense()))) R1 = np.hstack((eAH, K1)) R2 = np.hstack((K2.dot(eAH), K2.dot(K1))) G = np.vstack((R1,R2)) G1 = K2.dot(K1) - print(" , rho(G)=%s"%(str(numpy.linalg.eig(G1)[0]))) + print(" , rho(G)=%s"%(str(np.linalg.eig(G1)[0]))) def specify_external_input(self, input): diff --git a/src/pyfmi/simulation/assimulo_interface.pxd b/src/pyfmi/simulation/assimulo_interface.pxd index 91f7c0d6..531615e7 100644 --- a/src/pyfmi/simulation/assimulo_interface.pxd +++ b/src/pyfmi/simulation/assimulo_interface.pxd @@ -16,8 +16,8 @@ # along with this program. If not, see . -import numpy as N -cimport numpy as N +import numpy as np +cimport numpy as np import logging from pyfmi.fmi cimport FMUModelME2 @@ -49,16 +49,16 @@ cdef class FMIODE2(cExplicit_Problem): cdef public object _model, problem_name, result_file_name, __input, _A, debug_file_name, debug_file_object cdef public object export, _sparse_representation, _with_jacobian, _logging, _write_header, _start_time cdef public dict timings - cdef public N.ndarray y0, input_real_mask, input_other_mask + cdef public np.ndarray y0, input_real_mask, input_other_mask cdef public list input_names, input_real_value_refs, input_other, _logg_step_event cdef public double t0, _synchronize_factor cdef public jac_use, state_events_use, time_events_use cdef public FMUModelME2 model_me2 cdef public int model_me2_instance - cdef public N.ndarray _state_temp_1, _event_temp_1 + cdef public np.ndarray _state_temp_1, _event_temp_1 cdef int _logging_as_dynamic_diagnostics cdef int _number_of_diagnostics_variables cpdef _set_input_values(self, double t) - cdef _update_model(self, double t, N.ndarray[double, ndim=1, mode="c"] y) - cdef int _compare(self, double t, N.ndarray[double, ndim=1, mode="c"] y) + cdef _update_model(self, double t, np.ndarray[double, ndim=1, mode="c"] y) + cdef int _compare(self, double t, np.ndarray[double, ndim=1, mode="c"] y) diff --git a/src/pyfmi/simulation/assimulo_interface.pyx b/src/pyfmi/simulation/assimulo_interface.pyx index 62d82610..db7debea 100644 --- a/src/pyfmi/simulation/assimulo_interface.pyx +++ b/src/pyfmi/simulation/assimulo_interface.pyx @@ -24,24 +24,17 @@ required by Assimulo. import logging as logging_module from operator import index -import numpy as N -from numpy.core.einsumfunc import einsum - -from pyfmi.fmi import FMUException - -cimport numpy as N -import numpy.linalg as LIN -import scipy.sparse as sp +import numpy as np +cimport numpy as np +import scipy.sparse as sps import time -from pyfmi.common.io import ResultWriterDymola, ResultHandlerBinaryFile +from pyfmi.common.io import ResultWriterDymola import pyfmi.fmi as fmi +from pyfmi.fmi import FMUException from pyfmi.fmi cimport FMUModelME2 -from pyfmi.common import python3_flag -from pyfmi.common.core import TrajectoryLinearInterpolation from timeit import default_timer as timer -import time cimport fmil_import as FMIL try: @@ -79,17 +72,17 @@ def write_data(simulator,write_scaled_result=False, result_file_name=''): model = simulator.problem._model - t = N.array(simulator.problem._sol_time) - r = N.array(simulator.problem._sol_real) - data = N.c_[t,r] + t = np.array(simulator.problem._sol_time) + r = np.array(simulator.problem._sol_real) + data = np.c_[t,r] if len(simulator.problem._sol_int) > 0 and len(simulator.problem._sol_int[0]) > 0: - i = N.array(simulator.problem._sol_int) - data = N.c_[data,i] + i = np.array(simulator.problem._sol_int) + data = np.c_[data,i] if len(simulator.problem._sol_bool) > 0 and len(simulator.problem._sol_bool[0]) > 0: - #b = N.array(simulator.problem._sol_bool).reshape( + #b = np.array(simulator.problem._sol_bool).reshape( # -1,len(model._save_bool_variables_val)) - b = N.array(simulator.problem._sol_bool) - data = N.c_[data,b] + b = np.array(simulator.problem._sol_bool) + data = np.c_[data,b] export = ResultWriterDymola(model) export.write_header(file_name=result_file_name) @@ -151,7 +144,7 @@ class FMIODE(Explicit_Problem): #If there is no state in the model, add a dummy #state der(y)=0 if f_nbr == 0: - self.y0 = N.array([0.0]) + self.y0 = np.array([0.0]) #Determine the result file name if result_file_name == '': @@ -201,7 +194,7 @@ class FMIODE(Explicit_Problem): input_value_refs.append(self._model.get_variable_valueref(name)) input_alias_type.append(-1.0 if self._model.get_variable_alias(name)[name] == -1 else 1.0) self.input_value_refs = input_value_refs - self.input_alias_type = input_alias_type if N.any(input_alias_type==-1) else 1.0 + self.input_alias_type = input_alias_type if np.any(input_alias_type==-1) else 1.0 self.input = input def rhs(self, t, y, sw=None): @@ -226,7 +219,7 @@ class FMIODE(Explicit_Problem): #If there is no state, use the dummy if self._f_nbr == 0: - rhs = N.array([0.0]) + rhs = np.array([0.0]) return rhs @@ -300,7 +293,7 @@ class FMIODE(Explicit_Problem): #Sets the inputs, if any if self.input is not None: - self._model.set_real(self.input_value_refs, self.input[1].eval(N.array([solver.t]))[0,:]*self.input_alias_type) + self._model.set_real(self.input_value_refs, self.input[1].eval(np.array([solver.t]))[0,:]*self.input_alias_type) #Evaluating the rhs (Have to evaluate the values in the model) rhs = self._model.get_derivatives() @@ -391,8 +384,8 @@ class FMIODE(Explicit_Problem): #Sets the inputs, if any if self.input is not None: - self._model.set_real(self.input_value_refs, self.input[1].eval(N.array([solver.t]))[0,:]*self.input_alias_type) - #self._model.set(self.input[0],self.input[1].eval(N.array([solver.t]))[0,:]) + self._model.set_real(self.input_value_refs, self.input[1].eval(np.array([solver.t]))[0,:]*self.input_alias_type) + #self._model.set(self.input[0],self.input[1].eval(np.array([solver.t]))[0,:]) #Evaluating the rhs (Have to evaluate the values in the model) rhs = self._model.get_derivatives() @@ -526,8 +519,8 @@ class FMIODESENS(FMIODE): if parameters is not None: if not isinstance(parameters,list): raise FMIModel_Exception("Parameters must be a list of names.") - self.p0 = N.array(model.get(parameters)).flatten() - self.pbar = N.array([N.abs(x) if N.abs(x) > 0 else 1.0 for x in self.p0]) + self.p0 = np.array(model.get(parameters)).flatten() + self.pbar = np.array([np.abs(x) if np.abs(x) > 0 else 1.0 for x in self.p0]) self.parameters = parameters @@ -570,7 +563,7 @@ class FMIODESENS(FMIODE): #Sets the parameters, if any if self.parameters is not None: - p_data = N.array(solver.interpolate_sensitivity(t, 0)).flatten() + p_data = np.array(solver.interpolate_sensitivity(t, 0)).flatten() self.export.integration_point(solver)#parameter_data=p_data) @@ -594,7 +587,7 @@ cdef class FMIODE2(cExplicit_Problem): self.input_names = [] self.timings = {"handle_result": 0.0} - if type(model) == FMUModelME2: #isinstance(model, FMUModelME2): + if type(model)==FMUModelME2: #if isinstance(model, FMUModelME2): self.model_me2 = model self.model_me2_instance = 1 else: @@ -620,7 +613,7 @@ cdef class FMIODE2(cExplicit_Problem): #If there is no state in the model, add a dummy state der(y)=0 if f_nbr == 0: - self.y0 = N.array([0.0]) + self.y0 = np.array([0.0]) #Determine the result file name if result_file_name == '': @@ -650,12 +643,12 @@ cdef class FMIODE2(cExplicit_Problem): #Need to calculate the nnz. [derv_state_dep, derv_input_dep] = model.get_derivatives_dependencies() - self.jac_nnz = N.sum([len(derv_state_dep[key]) for key in derv_state_dep.keys()])+f_nbr + self.jac_nnz = np.sum([len(derv_state_dep[key]) for key in derv_state_dep.keys()])+f_nbr if extra_equations: self._extra_f_nbr = extra_equations.get_size() self._extra_y0 = extra_equations.y0 - self.y0 = N.append(self.y0, self._extra_y0) + self.y0 = np.append(self.y0, self._extra_y0) self._extra_equations = extra_equations if hasattr(self._extra_equations, "jac"): @@ -679,8 +672,8 @@ cdef class FMIODE2(cExplicit_Problem): else: self._synchronize_factor = 0.0 - self._state_temp_1 = N.empty(f_nbr, dtype = N.double) - self._event_temp_1 = N.empty(g_nbr, dtype = N.double) + self._state_temp_1 = np.empty(f_nbr, dtype = np.double) + self._event_temp_1 = np.empty(g_nbr, dtype = np.double) def _adapt_input(self, input): if input is not None: @@ -705,8 +698,8 @@ cdef class FMIODE2(cExplicit_Problem): self.input_other.append(name) input_other_mask.append(i) - self.input_real_mask = N.array(input_real_mask) - self.input_other_mask = N.array(input_other_mask) + self.input_real_mask = np.array(input_real_mask) + self.input_other_mask = np.array(input_other_mask) self._input_activated = 1 else: @@ -723,7 +716,7 @@ cdef class FMIODE2(cExplicit_Problem): if self.input_other: self._model.set(self.input_other, values[self.input_other_mask]) - cdef _update_model(self, double t, N.ndarray[double, ndim=1, mode="c"] y): + cdef _update_model(self, double t, np.ndarray[double, ndim=1, mode="c"] y): if self.model_me2_instance: #Moving data to the model self.model_me2._set_time(t) @@ -740,7 +733,7 @@ cdef class FMIODE2(cExplicit_Problem): #Sets the inputs, if any self._set_input_values(t) - cdef int _compare(self, double t, N.ndarray[double, ndim=1, mode="c"] y): + cdef int _compare(self, double t, np.ndarray[double, ndim=1, mode="c"] y): cdef int res if self.model_me2_instance: @@ -760,7 +753,7 @@ cdef class FMIODE2(cExplicit_Problem): else: return t != self._model.time or (not self._f_nbr == 0 and not (self._model.continuous_states == y).all()) - def rhs(self, double t, N.ndarray[double, ndim=1, mode="c"] y, sw=None): + def rhs(self, double t, np.ndarray[double, ndim=1, mode="c"] y, sw=None): """ The rhs (right-hand-side) for an ODE problem. """ @@ -790,14 +783,14 @@ cdef class FMIODE2(cExplicit_Problem): #If there is no state, use the dummy if self._f_nbr == 0: - der = N.array([0.0]) + der = np.array([0.0]) if self._extra_f_nbr > 0: - der = N.append(der, self._extra_equations.rhs(y_extra)) + der = np.append(der, self._extra_equations.rhs(y_extra)) return der - def jac(self, double t, N.ndarray[double, ndim=1, mode="c"] y, sw=None): + def jac(self, double t, np.ndarray[double, ndim=1, mode="c"] y, sw=None): """ The jacobian function for an ODE problem. """ @@ -822,7 +815,7 @@ cdef class FMIODE2(cExplicit_Problem): msg = preface + ''%(solver_info_tag) self._model.append_log_message("Model", 6, msg) - return N.array([[0.0]]) + return np.array([[0.0]]) A = self._model._get_A(add_diag=True, output_matrix=self._A) if self._A is None: @@ -835,16 +828,16 @@ cdef class FMIODE2(cExplicit_Problem): Jac = A.tocoo() #Convert to COOrdinate A2 = self._extra_equations.jac(y_extra).tocoo() - data = N.append(Jac.data, A2.data) - row = N.append(Jac.row, A2.row+self._f_nbr) - col = N.append(Jac.col, A2.col+self._f_nbr) + data = np.append(Jac.data, A2.data) + row = np.append(Jac.row, A2.row+self._f_nbr) + col = np.append(Jac.col, A2.col+self._f_nbr) #Convert to compresssed sparse column - Jac = sp.coo_matrix((data, (row, col))) + Jac = sps.coo_matrix((data, (row, col))) Jac = Jac.tocsc() else: - Jac = N.zeros((self._f_nbr+self._extra_f_nbr,self._f_nbr+self._extra_f_nbr)) - Jac[:self._f_nbr,:self._f_nbr] = A if isinstance(A, N.ndarray) else A.toarray() + Jac = np.zeros((self._f_nbr+self._extra_f_nbr,self._f_nbr+self._extra_f_nbr)) + Jac[:self._f_nbr,:self._f_nbr] = A if isinstance(A, np.ndarray) else A.toarray() Jac[self._f_nbr:,self._f_nbr:] = self._extra_equations.jac(y_extra) else: raise fmi.FMUException("No Jacobian provided for the extra equations") @@ -857,7 +850,7 @@ cdef class FMIODE2(cExplicit_Problem): return Jac - def state_events(self, double t, N.ndarray[double, ndim=1, mode="c"] y, sw=None): + def state_events(self, double t, np.ndarray[double, ndim=1, mode="c"] y, sw=None): """ The event indicator function for a ODE problem. """ @@ -880,7 +873,7 @@ cdef class FMIODE2(cExplicit_Problem): else: return self._model.get_event_indicators() - def time_events(self, double t, N.ndarray[double, ndim=1, mode="c"] y, sw=None): + def time_events(self, double t, np.ndarray[double, ndim=1, mode="c"] y, sw=None): """ Time event function. """ @@ -981,7 +974,7 @@ cdef class FMIODE2(cExplicit_Problem): msg = preface + ''%(event_info_tag) self._model.append_log_message("Model", 6, msg) else: - diag_data = N.ndarray(self._number_of_diagnostics_variables, dtype=float) + diag_data = np.ndarray(self._number_of_diagnostics_variables, dtype=float) index = 0 diag_data[index] = solver.t index +=1 @@ -1156,7 +1149,7 @@ cdef class FMIODE2(cExplicit_Problem): msg = preface + ''%(solver_info_tag) self._model.append_log_message("Model", 6, msg) else: - diag_data = N.ndarray(self._number_of_diagnostics_variables, dtype=float) + diag_data = np.ndarray(self._number_of_diagnostics_variables, dtype=float) index = 0 diag_data[index] = solver.t index +=1 @@ -1336,8 +1329,8 @@ class FMIODESENS2(FMIODE2): if parameters is not None: if not isinstance(parameters,list): raise FMIModel_Exception("Parameters must be a list of names.") - self.p0 = N.array(model.get(parameters)).flatten() - self.pbar = N.array([N.abs(x) if N.abs(x) > 0 else 1.0 for x in self.p0]) + self.p0 = np.array(model.get(parameters)).flatten() + self.pbar = np.array([np.abs(x) if np.abs(x) > 0 else 1.0 for x in self.p0]) self.param_valref = [model.get_variable_valueref(x) for x in parameters] for param in parameters: @@ -1346,10 +1339,7 @@ class FMIODESENS2(FMIODE2): raise FMIModel_Exception("The sensitivity parameters must be specified as inputs!") self.parameters = parameters - if python3_flag: - self.derivatives = [v.value_reference for i,v in model.get_derivatives_list().items()] - else: - self.derivatives = [v.value_reference for i,v in model.get_derivatives_list().iteritems()] + self.derivatives = [v.value_reference for i,v in model.get_derivatives_list().items()] if self._model.get_capability_flags()['providesDirectionalDerivatives']: use_rhs_sens = True diff --git a/src/pyfmi/tests/__init__.py b/src/pyfmi/tests/__init__.py new file mode 100644 index 00000000..8962836d --- /dev/null +++ b/src/pyfmi/tests/__init__.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (C) 2024 Modelon AB +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . diff --git a/src/pyfmi/tests/test_util.pxd b/src/pyfmi/tests/test_util.pxd new file mode 100644 index 00000000..bd175471 --- /dev/null +++ b/src/pyfmi/tests/test_util.pxd @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Copyright (C) 2014-2024 Modelon AB +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, version 3 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +""" Collection of classes used for testing purposes.""" +cimport pyfmi.fmil_import as FMIL +from pyfmi.fmi cimport FMUModelME1, FMUModelME2 + +cdef class _ForTestingFMUModelME1(FMUModelME1): + cdef int _get_nominal_continuous_states_fmil(self, FMIL.fmi1_real_t* xnominal, size_t nx) + cpdef set_allocated_fmu(self, int value) + +cdef class _ForTestingFMUModelME2(FMUModelME2): + cdef int _get_real_by_ptr(self, FMIL.fmi2_value_reference_t* vrefs, size_t _size, FMIL.fmi2_real_t* values) + cdef int _set_real(self, FMIL.fmi2_value_reference_t* vrefs, FMIL.fmi2_real_t* values, size_t _size) + cdef int _get_real_by_list(self, FMIL.fmi2_value_reference_t[:] valueref, size_t _size, FMIL.fmi2_real_t[:] values) + cdef int _get_integer(self, FMIL.fmi2_value_reference_t[:] valueref, size_t _size, FMIL.fmi2_integer_t[:] values) + cdef int _get_boolean(self, FMIL.fmi2_value_reference_t[:] valueref, size_t _size, FMIL.fmi2_real_t[:] values) + cdef int _get_nominal_continuous_states_fmil(self, FMIL.fmi2_real_t* xnominal, size_t nx) + cpdef set_initialized_fmu(self, int value) diff --git a/tests/test_util.py b/src/pyfmi/tests/test_util.pyx similarity index 72% rename from tests/test_util.py rename to src/pyfmi/tests/test_util.pyx index b87abf04..95f2ebe9 100644 --- a/tests/test_util.py +++ b/src/pyfmi/tests/test_util.pyx @@ -15,15 +15,37 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +# distutils: define_macros=NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION + import os import numpy as np +cimport pyfmi.fmil_import as FMIL -from pyfmi.fmi import (FMUException, FMUModelME1, _ForTestingFMUModelME1, FMUModelCS1, - FMUModelCS2, FMUModelME2, _ForTestingFMUModelME2) +from pyfmi.fmi import FMUException, FMUModelME1, FMUModelCS1, FMUModelCS2, FMUModelME2 def get_examples_folder(): return os.path.join(os.path.dirname(__file__), '..', 'examples') +cdef class _ForTestingFMUModelME1(FMUModelME1): + cdef int _get_nominal_continuous_states_fmil(self, FMIL.fmi1_real_t* xnominal, size_t nx): + for i in range(nx): + if self._allocated_fmu == 1: # If initialized + # Set new values to test that atol gets auto-corrected. + xnominal[i] = 3.0 + else: + # Set some illegal values in order to test the fallback/auto-correction. + xnominal[i] = ((( i) % 3) - 1) * 2.0 # -2.0, 0.0, 2.0, + return FMIL.fmi1_status_ok + + cpdef set_allocated_fmu(self, int value): + self._allocated_fmu = value + + def __dealloc__(self): + # Avoid segfaults in dealloc. The FMU binaries should never be loaded for this + # test class, so we should never try to terminate or deallocate the FMU instance. + self._allocated_fmu = 0 + + class Dummy_FMUModelME1(_ForTestingFMUModelME1): # If true, makes use of the real _ForTesting implementation for nominal_continuous_states, # else just returns 1.0 for each. @@ -127,6 +149,82 @@ def get_integer(self, vref): def get_boolean(self, vref): return self.get_real(vref) + +cdef class _ForTestingFMUModelME2(FMUModelME2): + cdef int _get_real_by_ptr(self, FMIL.fmi2_value_reference_t* vrefs, size_t _size, FMIL.fmi2_real_t* values): + vr = np.zeros(_size) + for i in range(_size): + vr[i] = vrefs[i] + + try: + vv = self.get_real(vr) + except Exception: + return FMIL.fmi2_status_error + + for i in range(_size): + values[i] = vv[i] + + return FMIL.fmi2_status_ok + + cdef int _set_real(self, FMIL.fmi2_value_reference_t* vrefs, FMIL.fmi2_real_t* values, size_t _size): + vr = np.zeros(_size) + vv = np.zeros(_size) + for i in range(_size): + vr[i] = vrefs[i] + vv[i] = values[i] + + try: + self.set_real(vr, vv) + except Exception: + return FMIL.fmi2_status_error + + return FMIL.fmi2_status_ok + + cdef int _get_real_by_list(self, FMIL.fmi2_value_reference_t[:] valueref, size_t _size, FMIL.fmi2_real_t[:] values): + try: + tmp = self.get_real(valueref) + for i in range(_size): + values[i] = tmp[i] + except Exception: + return FMIL.fmi2_status_error + return FMIL.fmi2_status_ok + + cdef int _get_integer(self, FMIL.fmi2_value_reference_t[:] valueref, size_t _size, FMIL.fmi2_integer_t[:] values): + try: + tmp = self.get_integer(valueref) + for i in range(_size): + values[i] = tmp[i] + except Exception: + return FMIL.fmi2_status_error + return FMIL.fmi2_status_ok + + cdef int _get_boolean(self, FMIL.fmi2_value_reference_t[:] valueref, size_t _size, FMIL.fmi2_real_t[:] values): + try: + tmp = self.get_boolean(valueref) + for i in range(_size): + values[i] = tmp[i] + except Exception: + return FMIL.fmi2_status_error + return FMIL.fmi2_status_ok + + cdef int _get_nominal_continuous_states_fmil(self, FMIL.fmi2_real_t* xnominal, size_t nx): + for i in range(nx): + if self._initialized_fmu == 1: + # Set new values to test that atol gets auto-corrected. + xnominal[i] = 3.0 + else: + # Set some illegal values in order to test the fallback/auto-correction. + xnominal[i] = ((( i) % 3) - 1) * 2.0 # -2.0, 0.0, 2.0, + return FMIL.fmi2_status_ok + + cpdef set_initialized_fmu(self, int value): + self._initialized_fmu = value + + def __dealloc__(self): + # Avoid segfaults in dealloc. The FMU binaries should never be loaded for this + # test class, so we should never try to terminate or deallocate the FMU instance. + self._initialized_fmu = 0 + class Dummy_FMUModelCS2(FMUModelCS2): #Override properties time = None @@ -288,7 +386,7 @@ def get_real(self, vref, evaluate = True): if evaluate: self.get_derivatives() vals = [] - if type(vref) == int: + if isinstance(vref, int): vref = [vref] for v in vref: vals.append(self.values[v]) diff --git a/tests/__init__.py b/tests/__init__.py index 8e501f09..e7c78986 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# Copyright (C) 2018 Modelon AB +# Copyright (C) 2018-2024 Modelon AB # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by diff --git a/tests/test_fmi_coupled.py b/tests/test_fmi_coupled.py index d0b26f88..b1b622a8 100644 --- a/tests/test_fmi_coupled.py +++ b/tests/test_fmi_coupled.py @@ -17,16 +17,12 @@ import nose import os -import numpy as np from pyfmi import testattr -from pyfmi.fmi import FMUException, FMUModelME1, FMUModelCS1, load_fmu, FMUModelCS2, FMUModelME2, PyEventInfo +from pyfmi.fmi import FMUModelME2 from pyfmi.fmi_coupled import CoupledFMUModelME2 -import pyfmi.fmi_util as fmi_util import pyfmi.fmi as fmi -import pyfmi.fmi_algorithm_drivers as fmi_algorithm_drivers from pyfmi.tests.test_util import Dummy_FMUModelME2 -from pyfmi.common.io import ResultHandler assimulo_installed = True try: diff --git a/tests/test_fmi_extended.py b/tests/test_fmi_extended.py index 884bb1f9..b0655012 100644 --- a/tests/test_fmi_extended.py +++ b/tests/test_fmi_extended.py @@ -15,19 +15,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import nose import os import numpy as np from pyfmi import testattr -from pyfmi.fmi import FMUException, FMUModelME1, FMUModelCS1, load_fmu, FMUModelCS2, FMUModelME2, PyEventInfo -from pyfmi.fmi_coupled import CoupledFMUModelME2 from pyfmi.fmi_extended import FMUModelME1Extended -import pyfmi.fmi_util as fmi_util -import pyfmi.fmi as fmi -import pyfmi.fmi_algorithm_drivers as fmi_algorithm_drivers -from pyfmi.tests.test_util import Dummy_FMUModelME2 -from pyfmi.common.io import ResultHandler file_path = os.path.dirname(os.path.abspath(__file__)) diff --git a/tests/test_fmi_master.py b/tests/test_fmi_master.py index 811c4b01..c8f04dc2 100644 --- a/tests/test_fmi_master.py +++ b/tests/test_fmi_master.py @@ -19,12 +19,10 @@ import os import numpy as np -from pyfmi import testattr -from pyfmi.fmi import FMUException, FMUModelME1, FMUModelCS1, load_fmu, FMUModelCS2, FMUModelME2 -import pyfmi.fmi_util as fmi_util -import pyfmi.fmi as fmi -from pyfmi import Master -from pyfmi.tests.test_util import Dummy_FMUModelME2, Dummy_FMUModelCS2 +from pyfmi import testattr, Master +from pyfmi.fmi import FMUException, FMUModelCS2, FMUModelME2 +from pyfmi.tests.test_util import Dummy_FMUModelCS2 +from pyfmi.common.algorithm_drivers import UnrecognizedOptionError file_path = os.path.dirname(os.path.abspath(__file__)) @@ -169,8 +167,6 @@ def test_basic_simulation_mat_file(self): @testattr(stddist = True) def test_basic_simulation_mat_file_naming(self): - from pyfmi.common.algorithm_drivers import UnrecognizedOptionError - opts = {"result_handling":"binary", "result_file_name": "Should fail..."} try: @@ -327,151 +323,3 @@ def do_step2(current_t, step_size, new_step=True): assert abs(res[model_sub1].final("x1")) > 100 assert abs(res[model_sub2].final("x2")) > 100 - - -""" -To be migrated: - - -class Test_Master_Simulation: - @classmethod - def setUpClass(cls): - file_name = os.path.join(get_files_path(), 'Modelica', 'LinearCoSimulation.mo') - - cls.linear_full = compile_fmu("LinearCoSimulation.LinearFullSystem", file_name, target="cs", version="2.0") - cls.linear_sub1 = compile_fmu("LinearCoSimulation.LinearSubSystem1", file_name, target="cs", version="2.0") - cls.linear_sub2 = compile_fmu("LinearCoSimulation.LinearSubSystem2", file_name, target="cs", version="2.0") - - compiler_options={"generate_ode_jacobian": True} - - cls.linear_sub1_dir = compile_fmu("LinearCoSimulation.LinearSubSystem1", file_name, target="cs", version="2.0", - compiler_options={"generate_ode_jacobian": True}, compile_to="LinearSub1Dir.fmu") - cls.linear_sub2_dir = compile_fmu("LinearCoSimulation.LinearSubSystem2", file_name, target="cs", version="2.0", - compiler_options={"generate_ode_jacobian": True}, compile_to="LinearSub2Dir.fmu") - - @testattr(stddist = True) - def test_linear_correction_simulation(self): - model = load_fmu(self.linear_full) - - model_sub1 = load_fmu(self.linear_sub1_dir) - model_sub2 = load_fmu(self.linear_sub2_dir) - - models = [model_sub1, model_sub2] - connections = [(model_sub1,"y1",model_sub2,"u2"), - (model_sub2,"y2",model_sub1,"u1")] - - master = Master(models, connections) - - opts = master.simulate_options() - opts["step_size"] = 0.0005 - opts["extrapolation_order"] = 1 - opts["linear_correction"] = True - - res = master.simulate(options=opts) - - res_full = model.simulate() - - nose.tools.assert_almost_equal(res[model_sub1].final("x1"), res_full.final("p1.x1"), 2) - nose.tools.assert_almost_equal(res[model_sub2].final("x2"), res_full.final("p2.x2"), 2) - - @testattr(stddist = True) - def test_basic_simulation_extrapolation(self): - model = load_fmu(self.linear_full) - - model.set("p1.d1", 0.1) - - model_sub1 = load_fmu(self.linear_sub1) - model_sub2 = load_fmu(self.linear_sub2) - - model_sub1.set("d1", 0.1) - - models = [model_sub1, model_sub2] - connections = [(model_sub1,"y1",model_sub2,"u2"), - (model_sub2,"y2",model_sub1,"u1")] - - master = Master(models, connections) - - opts = master.simulate_options() - opts["step_size"] = 0.0005 - opts["extrapolation_order"] = 1 - - res = master.simulate(options=opts) - - res_full = model.simulate() - - nose.tools.assert_almost_equal(res[model_sub1].final("x1"), res_full.final("p1.x1"), 2) - nose.tools.assert_almost_equal(res[model_sub2].final("x2"), res_full.final("p2.x2"), 2) - - @testattr(stddist = True) - def test_unstable_simulation_extrapolation(self): - model = load_fmu(self.linear_full) - - model_sub1 = load_fmu(self.linear_sub1) - model_sub2 = load_fmu(self.linear_sub2) - - models = [model_sub1, model_sub2] - connections = [(model_sub1,"y1",model_sub2,"u2"), - (model_sub2,"y2",model_sub1,"u1")] - - master = Master(models, connections) - - opts = master.simulate_options() - opts["step_size"] = 0.0005 - opts["extrapolation_order"] = 1 - - res = master.simulate(final_time=0.2, options=opts) - - res_full = model.simulate() - - #The coupled system is unstable with extrapolation 1 - assert abs(res[model_sub1].final("x1")) > 100 - assert abs(res[model_sub2].final("x2")) > 100 - - #import pylab as plt - #plt.plot(res[model_sub1]["time"], res[model_sub1]["x1"]) - #plt.plot(res_full["time"], res_full["p1.x1"]) - #plt.show() - - @testattr(stddist = True) - def test_initialize(self): - model = load_fmu(self.linear_full) - model.setup_experiment() - model.initialize() - - model_sub1 = load_fmu(self.linear_sub1) - model_sub2 = load_fmu(self.linear_sub2) - - models = [model_sub1, model_sub2] - connections = [(model_sub1,"y1",model_sub2,"u2"), - (model_sub2,"y2",model_sub1,"u1")] - - master = Master(models, connections) - - opts = master.simulate_options() - opts["step_size"] = 0.0005 - opts["extrapolation_order"] = 1 - - master.initialize(0, 1, opts) - - nose.tools.assert_almost_equal(model_sub1.get("y1"), model.get("p1.y1"), 2) - nose.tools.assert_almost_equal(model_sub2.get("y2"), model.get("p2.y2"), 2) - - model_sub1 = load_fmu(self.linear_sub1) - model_sub2 = load_fmu(self.linear_sub2) - - models = [model_sub1, model_sub2] - connections = [(model_sub1,"y1",model_sub2,"u2"), - (model_sub2,"y2",model_sub1,"u1")] - - master = Master(models, connections) - - opts = master.simulate_options() - opts["step_size"] = 0.0005 - opts["extrapolation_order"] = 1 - opts["block_initialization"] = True - - master.initialize(0, 1, opts) - - nose.tools.assert_almost_equal(model_sub1.get("y1"), model.get("p1.y1"), 2) - nose.tools.assert_almost_equal(model_sub2.get("y2"), model.get("p2.y2"), 2) -""" diff --git a/tests/test_fmi_util.py b/tests/test_fmi_util.py index eb969edb..5c03a930 100644 --- a/tests/test_fmi_util.py +++ b/tests/test_fmi_util.py @@ -19,15 +19,11 @@ Module containing the tests for the FMI interface. """ -import nose -import os import numpy as np from collections import OrderedDict from pyfmi import testattr -from pyfmi.fmi import FMUException, FMUModelME1, FMUModelCS1, load_fmu, FMUModelCS2, FMUModelME2, PyEventInfo import pyfmi.fmi_util as fmi_util -import pyfmi.fmi as fmi class Test_FMIUtil: diff --git a/tests/test_stream.py b/tests/test_stream.py index a517eb51..758c7af1 100644 --- a/tests/test_stream.py +++ b/tests/test_stream.py @@ -277,4 +277,4 @@ def test_extract_xml_log_into_stream(self): xml_log = fmu.extract_xml_log() err_msg = "Unequal xml files, please compare the contents of:\n{}\nand\n{}".format(xml_file1, xml_log) - nose.tools.assert_true(compare_files(xml_file1, xml_log), err_msg) \ No newline at end of file + nose.tools.assert_true(compare_files(xml_file1, xml_log), err_msg)