Commit eee4c059 authored by Louis Beauloye's avatar Louis Beauloye
Browse files

[Ctypes] reset_data, load_from_file and get results from buffers

parent 6655a74b
......@@ -15,5 +15,6 @@ Portable Python interface to MBsysC using Ctypes.
from .mbsysc_loader import *
from .mbsyspy import *
from .mbs_utilities import *
__version__ = "1.11.2"
\ No newline at end of file
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
-------------------------------
(c) Universite catholique de Louvain, 2019
Creation : 2019 by O. Lantsoght
Last update : 2019
version MBsysC v1.11.2
-------------------------------
Portable Python interface to MBsysC using Ctypes.
"""
# importing libraries
from .mbsysc_loader.loadlibs import libutilities
def set_output(var , file_name):
file_name_c = file_name.encode('utf-8')
libutilities.set_output(var, file_name_c)
......@@ -20,5 +20,6 @@ from .mbs_load_c import *
from .mbs_data_c import *
from .mbs_part_c import *
from .mbs_dirdyn_c import *
from .mbs_buffer_c import *
from .mbs_aux_c import *
from .mbs_sensor_c import *
......@@ -66,4 +66,6 @@ class MbsAux_c(ctypes.Structure):
class MbsEquil_c(ctypes.Structure):
pass
class MbsSensor_c(ctypes.Structure):
pass
class AnimInfo_c(ctypes.Structure):
pass
\ No newline at end of file
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
-------------------------------
(c) Universite catholique de Louvain, 2019
Creation : 2019
Last update : 2019
version MBsysC v1.11.2
-------------------------------
Portable Python interface to MBsysC using Ctypes.
Declaration of MBsysC structure related to mbs_buffer.h header file in MBsysC.
"""
import ctypes
from .forward_decl import MbsBuffer_c
from .forward_decl import MbsGrowingBuffer_c
from .forward_decl import AnimInfo_c
#==============================================================================
# MbsBuffer_c
#==============================================================================
MbsBuffer_c._fields_ =[
("tx", ctypes.POINTER(ctypes.c_double)),
("last_x", ctypes.POINTER(ctypes.c_double)),
("last_t", ctypes.c_double),
("flag_no_print", ctypes.c_int),
("filename", ctypes.c_char_p),
("index", ctypes.c_int),
("size", ctypes.c_int),
("nx", ctypes.c_int),
("id", ctypes.c_int),
("anim", ctypes.POINTER(AnimInfo_c))
]
#==============================================================================
# MbsGrowingBuffer_c
#==============================================================================
MbsGrowingBuffer_c._fields_ =[
("t", ctypes.POINTER(ctypes.c_double)),
("X", ctypes.POINTER(ctypes.POINTER(ctypes.c_double))),
("names", ctypes.POINTER(ctypes.c_char_p)),
("index", ctypes.c_int),
("size", ctypes.c_int),
("nx", ctypes.c_int),
("max_nx", ctypes.c_int),
("respath", ctypes.c_char_p)
]
\ No newline at end of file
......@@ -44,6 +44,9 @@ __DEBUG__ = True
libutilities.mbs_print_data.argtypes =[ctypes.POINTER(MbsData_c)]
libutilities.mbs_print_data.restype = None
libutilities.mbs_reset_data.argtypes =[ctypes.POINTER(MbsData_c)]
libutilities.mbs_reset_data.restype = None
libutilities.mbs_set_nb_userc.argtypes =[ctypes.POINTER(MbsData_c), ctypes.c_int]
libutilities.mbs_set_nb_userc.restype = None
......@@ -65,6 +68,9 @@ libutilities.mbs_set_qv.restype = None
libutilities.mbs_unset_qa.argtypes =[ctypes.POINTER(MbsData_c), ctypes.c_int]
libutilities.mbs_unset_qa.restype = None
libutilities.set_output.argtypes =[ctypes.c_double, ctypes.c_char_p]
libutilities.set_output.restypes = None
# LoadXML
libloadXML.mbs_info_reader.argtypes =[ctypes.c_char_p]
libloadXML.mbs_info_reader.restype = ctypes.POINTER(MbsInfos_c)
......@@ -88,3 +94,12 @@ libmodules.mbs_new_dirdyn.restype = ctypes.POINTER(MbsDirdyn_c)
libmodules.mbs_run_dirdyn.argtypes =[ctypes.POINTER(MbsDirdyn_c), ctypes.POINTER(MbsData_c)]
libmodules.mbs_run_dirdyn.restype = None
libmodules.mbs_dirdyn_init.argtypes =[ctypes.POINTER(MbsDirdyn_c), ctypes.POINTER(MbsData_c)]
libmodules.mbs_dirdyn_init.restype = None
libmodules.mbs_dirdyn_loop.argtypes =[ctypes.POINTER(MbsDirdyn_c), ctypes.POINTER(MbsData_c)]
libmodules.mbs_dirdyn_loop.restype = None
libmodules.mbs_dirdyn_finish.argtypes =[ctypes.POINTER(MbsDirdyn_c), ctypes.POINTER(MbsData_c)]
libmodules.mbs_dirdyn_finish.restype = None
\ No newline at end of file
......@@ -701,6 +701,116 @@ class MbsData(object):
else:
libutilities.mbs_set_qv(self.mbs_data_ptr, indices)
def mbs_reset_data(self,verbose=True):
"""
Reset mbs_data to its inital value
"""
libutilities.mbs_reset_data(self.mbs_data_ptr)
if verbose :
print("mbs_data reseted to initial value")
def mbs_load_from_file(self, baseFileName=None, result_path=None, time = -1):
""" Load a state to MbsData instance from files for specific time.
If the time specified is not found in the file, the last time step lower than the specification is taken.
The fieds q, qd, qdd, ux, uxd, q0, qd0, qdd0, ux0 ant tsim are set.
:param baseFileName The path and resfilename containing the state to load. The suffix _q, _qd, _ux.res will be added.
default = "dirdyn" if not specified
:param result_path The path of the result folder, default = "ResultR" if not specified
:param time The time corresponding to the state to load, defaut value is the last state.
"""
def find_index(temp, t):
if (t == -1):
index = -1
else:
# Look the specified time
index = np.nonzero(temp[:,0]>=t)
if (np.size(index)):
index=index[0][0]
if not temp[index,0]==t:
if __DEBUG__ : print ("Time specified not found, take the last occurence where t<time")
index = index-1
else:
if __DEBUG__ : print ("Time specified greather than time in files, taking the last state.")
index = -1
return(index)
project_path = self.project_path
if baseFileName == None:
baseFileName = "dirdyn"
if result_path == None:
result_path = os.path.join(project_path, "ResultR")
else :
result_path = os.path.join(project_path, result_path)
# Error handeling
if not os.path.isdir(result_path):
if __DEBUG__ : print ('DEBUG>> The result directory does not exist: "'+ result_path+'"')
index = -2
# Generalized coordinates
CurFile = baseFileName+'_q.res'
path = os.path.abspath(os.path.join(result_path, CurFile))
if (os.path.isfile(path) ):
temp = np.loadtxt(path)
index = find_index(temp, time)
self.q[1:] = temp[index, 1:]
self.q0[1:] = self.q[1:]
self.tsim = temp[index, 0]
else:
if __DEBUG__ : print( "DEBUG>> file '"+CurFile+"' not found in folder '"+os.path.dirname(path))
# Generalized velocities
# Assumption: index is still valid
CurFile = baseFileName+'_qd.res'
path = os.path.abspath(os.path.join(result_path, CurFile))
if (os.path.isfile(path)):
temp = np.loadtxt(path)
if index == -2:
index = find_index(temp, time)
self.qd[1:] = temp[index, 1:]
self.qd0[1:] = self.qd[1:]
else:
if __DEBUG__ : print( "DEBUG>> file '"+CurFile+"' not found in folder '"+os.path.dirname(path))
# Generalized accelerations
# Assumption: index is still valid
CurFile = baseFileName+'_qdd.res'
path = os.path.abspath(os.path.join(result_path, CurFile))
if (os.path.isfile(path)):
temp = np.loadtxt(path)
if index == -2:
index = find_index(temp, time)
self.qdd[1:] = temp[index, 1:]
self.qdd0[1:] = self.qdd[1:]
else:
if __DEBUG__ : print( "DEBUG>> file '"+CurFile+"' not found in folder '"+os.path.dirname(path))
# Generalized user state
# Assumption: index is still valid
if self.Nux:
CurFile = baseFileName+'_ux.res'
path = os.path.abspath(os.path.join(result_path, CurFile))
if (os.path.isfile(path) ):
temp = np.loadtxt(path)
if index == -2:
index = find_index(temp, time)
self.ux[1:] = temp[index, 1:]
self.ux0[1:] = self.ux[1:]
else:
if __DEBUG__ : print( "DEBUG>> file '"+CurFile+"' not found in folder '"+os.path.dirname(path))
CurFile = baseFileName+'_uxd.res'
path = os.path.abspath(os.path.join(result_path, CurFile))
if (os.path.isfile(path)):
temp = np.loadtxt(path)
if index == -2:
index = find_index(temp, time)
self.uxd[1:] = temp[index, 1:]
else:
if __DEBUG__ : print( "DEBUG>> file '"+CurFile+"' not found in folder '"+os.path.dirname(path))
#==========================================================================
......
......@@ -121,6 +121,10 @@ class MbsDirdyn(object):
self.mbs_invdyna = None
self.mbs_dirdyna = None
# Storing Results
self.results = MbsResult(self.mbs)
self.mbs_get_results = False
# Exposing some memory
if __DEBUG__ : print( "DEBUG>> Exposing MbsDirdyn fields")
# Constraints
......@@ -190,7 +194,7 @@ class MbsDirdyn(object):
path = os.path.abspath(os.path.join(template_path, user_file))
module = imp.load_source(user_file[:-3], path)
self.user_cons_jdqd = module.user_cons_jdqd
self.ptrs_to_user_fcts["user_cons_jdqd"] = user_cons_jdqd_wrap(lambda h,Jac,mbs,tsim : self.user_cons_jdqd(self._jdqduserc, self.mbs))
self.ptrs_to_user_fcts["user_cons_jdqd"] = user_cons_jdqd_wrap(lambda jdqd,mbs,tsim : self.user_cons_jdqd(self._jdqduserc, self.mbs))
# user_dirdyn
user_file = "user_dirdyn.py"
......@@ -311,7 +315,60 @@ class MbsDirdyn(object):
self.mbs.mbs_dirdyna = self.mbs_dirdyna
self.mbs.mbs_data_ptr.contents.mbs_dirdyna = self.ptrs_to_symb_fcts["mbs_dirdyna"]
libmodules.mbs_run_dirdyn(self.mbs_dirdyn_ptr, self.mbs.mbs_data_ptr)
if not self.mbs_get_results:
libmodules.mbs_run_dirdyn(self.mbs_dirdyn_ptr, self.mbs.mbs_data_ptr)
else:
#save2file forced to 1 because if buffers don't have the complete results, results are loaded from files
self.set_options(save2file = 1)
libmodules.mbs_dirdyn_init(self.mbs_dirdyn_ptr, self.mbs.mbs_data_ptr)
libmodules.mbs_dirdyn_loop(self.mbs_dirdyn_ptr, self.mbs.mbs_data_ptr)
# Results (buffer) memory is kept BUT FILES WILL BE WRITTEN LATER
if self.get_options("save2file"):
#c_mbs_dirdyn_write_buffers(self.mbs_dirdyn_ptr)
size1 = self.mbs_dirdyn_ptr.contents.buffers[0].contents.index
size2 = self.mbs_dirdyn_ptr.contents.buffers[0].contents.nx+1
# array are initialized to the time pointer so as to start index of joints at 1 (we have to ensure contiguity between t and x in buffers ! ! !)
self.results.q = np.copy(np.ctypeslib.as_array(self.mbs_dirdyn_ptr.contents.buffers[0].contents.tx ,(size1, size2)))
# get time array from the q buffer
self.results.t = self.results.q[:,0]
if not self.results.t[0] == self.get_options("t0"):
print("The beginning of the integration is not available in the buffer.\n The complete results have to be loaded from files.")
self.results.load_results_from_file()
# get qd and qdd buffer
self.results.qd = np.copy(np.ctypeslib.as_array(self.mbs_dirdyn_ptr.contents.buffers[1].contents.tx ,(size1, size2)))
self.results.qdd = np.copy(np.ctypeslib.as_array(self.mbs_dirdyn_ptr.contents.buffers[2].contents.tx ,(size1, size2)))
size2 = self.mbs_dirdyn_ptr.contents.buffers[3].contents.nx+1
self.results.Qq = np.copy(np.ctypeslib.as_array(self.mbs_dirdyn_ptr.contents.buffers[3].contents.tx ,(size1, size2)))
if self.mbs.mbs_data_ptr.contents.Nux:
size2 = self.mbs_dirdyn_ptr.contents.buffers[4].contents.nx+1
self.results.ux = np.copy(np.ctypeslib.as_array(self.mbs_dirdyn_ptr.contents.buffers[4].contents.tx ,(size1, size2)))
self.results.uxd = np.copy(np.ctypeslib.as_array(self.mbs_dirdyn_ptr.contents.buffers[5].contents.tx ,(size1, size2)))
if self.mbs.mbs_data_ptr.contents.Nlink:
size2 = self.mbs_dirdyn_ptr.contents.buffers[6].contents.nx+1
self.results.Z = np.copy(np.ctypeslib.as_array(self.mbs_dirdyn_ptr.contents.buffers[6].contents.tx ,(size1, size2)))
self.results.Zd = np.copy(np.ctypeslib.as_array(self.mbs_dirdyn_ptr.contents.buffers[7].contents.tx ,(size1, size2)))
self.results.Fl = np.copy(np.ctypeslib.as_array(self.mbs_dirdyn_ptr.contents.buffers[8].contents.tx ,(size1, size2)))
else :
if self.mbs.mbs_data_ptr.contents.Nlink:
size2 = self.mbs_dirdyn_ptr.contents.buffers[4].contents.nx+1
self.results.Z = np.copy(np.ctypeslib.as_array(self.mbs_dirdyn_ptr.contents.buffers[4].contents.tx ,(size1, size2)))
self.results.Zd = np.copy(np.ctypeslib.as_array(self.mbs_dirdyn_ptr.contents.buffers[5].contents.tx ,(size1, size2)))
self.results.Fl = np.copy(np.ctypeslib.as_array(self.mbs_dirdyn_ptr.contents.buffers[6].contents.tx ,(size1, size2)))
if self.mbs_dirdyn_ptr.contents.user_buffer.contents.nx:
size = self.mbs_dirdyn_ptr.contents.user_buffer.contents.index
nbOutput = self.mbs_dirdyn_ptr.contents.user_buffer.contents.nx
user_out = np.copy(np.ctypeslib.as_array(self.mbs_dirdyn_ptr.contents.user_buffer.contents.X[0],(nbOutput, size)))
for i in np.arange(nbOutput):
name = self.mbs_dirdyn_ptr.contents.user_buffer.contents.names[i]
name = name.decode('utf-8')
self.results.outputs[name] = user_out[i,:]
libmodules.mbs_dirdyn_finish(self.mbs_dirdyn_ptr, self.mbs.mbs_data_ptr)
# Anassign user functions
self.mbs.user_cons_hJ = None
......@@ -448,6 +505,9 @@ class MbsDirdyn(object):
n_freeze : int
number of time step when the jacobian is freezed (computed once at the start of the n_freeze time steps)
default = 0
mbs_get_results : int
1 to save a copy of the results from the buffers
default = 0
"""
......@@ -543,6 +603,8 @@ class MbsDirdyn(object):
self.mbs_dirdyn_ptr.contents.options.contents.dt_max = value
elif key == "n_freeze":
self.mbs_dirdyn_ptr.contents.options.contents.n_freeze = value
elif key == "mbs_get_results":
self.mbs_get_results = value
else:
print(">>DIRDYN>> The option "+key+ " is not defined in this module")
......@@ -643,6 +705,8 @@ class MbsDirdyn(object):
options.append(self.mbs_dirdyn_ptr.contents.options.contents.dt_max)
elif key == "n_freeze":
options.append(self.mbs_dirdyn_ptr.contents.options.contents.n_freeze)
elif key == "mbs_get_results":
options.append(self.mbs_get_results)
else:
print(">>DIRDYN>> The option "+key+ " is not defined in this module")
......@@ -652,8 +716,8 @@ class MbsDirdyn(object):
return options[0]
return tuple(options)
#==========================================================================
# Defining properties
#==========================================================================
......@@ -668,3 +732,111 @@ class MbsDirdyn(object):
@property
def mbs_name(self):
return self.mbs.mbs_name
class MbsResult(object):
def __init__(self,mbs):
self.q=[]
self.qd=[]
self.qdd=[]
self.Fl=[]
self.Z=[]
self.Zd=[]
self.Qq=[]
self.t=[]
self.ux=[]
self.uxd=[]
self.outputs={}
self.mbs=mbs
def load_results_from_file(self, baseFileName=None, result_path=None):
project_path = self.mbs.project_path
if baseFileName == None:
baseFileName = "dirdyn"
if result_path == None:
result_path = os.path.join(project_path, "ResultR")
else :
result_path = os.path.join(project_path, result_path)
# Error handeling
if not os.path.isdir(result_path):
if __DEBUG__ : print ('DEBUG>> The result directory does not exist: "'+ result_path+'"')
# Generalized coordinates
CurFile = baseFileName+'_q.res'
path = os.path.abspath(os.path.join(result_path, CurFile))
if (os.path.isfile(path) ):
self.results.q = np.loadtxt(path)
self.results.t = self.results.q[:,0]
else:
if __DEBUG__ : print( "DEBUG>> file '"+CurFile+"' not found in folder '"+os.path.dirname(path))
# Generalized velocities
CurFile = baseFileName+'_qd.res'
path = os.path.abspath(os.path.join(result_path, CurFile))
if (os.path.isfile(path)):
self.results.qd = np.loadtxt(path)
else:
if __DEBUG__ : print( "DEBUG>> file '"+CurFile+"' not found in folder '"+os.path.dirname(path))
# Generalized accelerations
CurFile = baseFileName+'_qdd.res'
path = os.path.abspath(os.path.join(result_path, CurFile))
if (os.path.isfile(path)):
self.results.qdd = np.loadtxt(path)
else:
if __DEBUG__ : print( "DEBUG>> file '"+CurFile+"' not found in folder '"+os.path.dirname(path))
CurFile = baseFileName+'_Qq.res'
path = os.path.abspath(os.path.join(result_path, CurFile))
if (os.path.isfile(path)):
self.results.Qq = np.loadtxt(path)
else:
if __DEBUG__ : print( "DEBUG>> file '"+CurFile+"' not found in folder '"+os.path.dirname(path))
# Generalized user state
if self.mbs.mbs_data_ptr.contents.Nux:
CurFile = baseFileName+'_ux.res'
path = os.path.abspath(os.path.join(result_path, CurFile))
if (os.path.isfile(path) ):
self.results.ux = np.loadtxt(path)
else:
if __DEBUG__ : print( "DEBUG>> file '"+CurFile+"' not found in folder '"+os.path.dirname(path))
CurFile = baseFileName+'_uxd.res'
path = os.path.abspath(os.path.join(result_path, CurFile))
if (os.path.isfile(path)):
self.results.uxd = np.loadtxt(path)
else:
if __DEBUG__ : print( "DEBUG>> file '"+CurFile+"' not found in folder '"+os.path.dirname(path))
if self.mbs.mbs_data_ptr.contents.Nlink:
CurFile = baseFileName+'_linkF.res'
path = os.path.abspath(os.path.join(result_path, CurFile))
if (os.path.isfile(path) ):
self.results.Fl = np.loadtxt(path)
else:
if __DEBUG__ : print( "DEBUG>> file '"+CurFile+"' not found in folder '"+os.path.dirname(path))
CurFile = baseFileName+'_linkZ.res'
path = os.path.abspath(os.path.join(result_path, CurFile))
if (os.path.isfile(path)):
self.results.Z = np.loadtxt(path)
else:
if __DEBUG__ : print( "DEBUG>> file '"+CurFile+"' not found in folder '"+os.path.dirname(path))
CurFile = baseFileName+'_linkZd.res'
path = os.path.abspath(os.path.join(result_path, CurFile))
if (os.path.isfile(path)):
self.results.Zd = np.loadtxt(path)
else:
if __DEBUG__ : print( "DEBUG>> file '"+CurFile+"' not found in folder '"+os.path.dirname(path))
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment