Package mbdyn :: Module common
[hide private]

Source Code for Module mbdyn.common

  1  #!/usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3  # 
  4  # This file is part of MBDyn sim suite. 
  5  # Copyright (C) 2007 André ESPAZE, as part of a Master thesis supervised by 
  6  # Martin O.L.Hansen (DTU) and Nicolas Chauvat (Logilab) 
  7   
  8  # MBDyn sim suite is free software; you can redistribute it and/or modify 
  9  # it under the terms of the GNU General Public License as published by 
 10  # the Free Software Foundation; either version 2 of the License, or 
 11  # (at your option) any later version. 
 12  # 
 13  # This program is distributed in the hope that it will be useful, 
 14  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 15  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 16  # GNU General Public License for more details. 
 17  # 
 18  # You should have received a copy of the GNU General Public License 
 19  # along with this program; if not, write to the Free Software 
 20  # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 
 21  # 
 22  """All the common objects used all over the MBDyn package.  
 23  They are mainly used for writing the MBDyn input file. 
 24  """ 
 25   
 26  import os 
 27  import numpy as N 
 28  from mbdyn.record import Record 
 29  from mbdyn.general import EYE_NAME, VECTOR_NAMES, MATRIX_NAMES 
 30   
 31  # Certainly to be removed 
 32  #def get_norm(array): 
 33  #    norm = N.sqrt(N.dot(array.transpose(), array)) 
 34  #    return float(norm[0][0]) 
 35   
36 -def get_mbdyn_name(name):
37 """This function returns the MBDyn attribute name. 38 This attribute will be the connection between the Python world 39 and the MBDyn input file""" 40 return "mbdyn" + "_" + name
41
42 -def keyarg_to_mbdyn(name):
43 """MBDyn supports spaces, this function does the conversion from 44 an argument given in a dictionary to MBDyn""" 45 return name.replace(" ", "_")
46
47 -def split_into_pieces_of_3(raw_list):
48 """The length of the list is supposed to be a multiple of 3. 49 """ 50 result_list = [] 51 indices = N.arange(0, len(raw_list), 3) 52 for i in indices: 53 result_list.append([val for val in raw_list[i:i+3]]) 54 return result_list
55 56
57 -class CommonArgument:
58 """An argument used for the MBDyn input file, 59 characterized only by a value without reference. 60 """ 61
62 - def __init__(self, string):
63 self.value = string 64 self.has_comment = False 65 self.comment = None
66
67 - def set_value(self, string):
68 """Set the value of the common argument""" 69 self.value = string
70
71 - def set_comment(self, comment):
72 """Set a comment to the argument.""" 73 self.has_comment = True 74 self.comment = comment
75
76 - def get_line(self, separator=","):
77 """Return the line to write in the input file.""" 78 if self.has_comment: 79 return "%s%s\t# %s" % (self.value, separator, self.comment) 80 else: 81 return "%s%s" % (self.value, separator)
82
83 - def __str__(self):
84 return self.value
85 86
87 -class GeometricArgument(CommonArgument):
88 """A geometric argument is whether a vector or a matrix. 89 This is a particular case because those entites can be set regarding to 90 a referential, which does not exist on a 'CommonArgument'. 91 It will be written in the MBDyn input file. 92 """ 93
94 - def __init__(self, value, ref_obj):
95 CommonArgument.__init__(self, value) 96 self.ref_obj = ref_obj
97
98 - def get_line(self, separator=","):
99 """Return the line to write in the input file.""" 100 if self.ref_obj.name == "None": 101 rep = "" 102 elif self.ref_obj.name == "global": 103 rep = "reference, global, " 104 elif self.ref_obj.name == "node": 105 rep = "reference, node, " 106 else: 107 rep = "reference, %s, " % str(self.ref_obj.label) 108 if self.has_comment: 109 return "%s%s%s # %s" % (rep, self.value, separator, self.comment) 110 else: 111 return "%s%s%s" % (rep, self.value, separator)
112
113 - def __repr__(self):
114 rep = "{Value: %s, Reference: %s}" % (self.value, self.ref_obj.name) 115 return rep
116 117
118 -class BasicObject(Record):
119 """An object that will collect the values of the parameters to save. 120 The name of those parameters are in the 'own_para_names' attribute 121 and will be set specifically for each object. 122 """ 123
124 - def __init__(self, name):
125 Record.__init__(self) 126 self.own_para_names += ["name"] 127 self.set_name(name) 128 129 self.has_comment = False 130 self.comment = None 131 132 self.label = 1 133 self.mbdyn_label = "1" 134 135 self.mbdyn_inst = None 136 # 'label' is not included in the argument name 137 # because some of the objects (like Gravity) do 138 # not have any label 139 self.arg_names = [] 140 141 self.simulation = None
142
143 - def set_name(self, name):
144 """Set the name of the object.""" 145 self.name = name 146 self.mbdyn_name = keyarg_to_mbdyn(name)
147
148 - def set_label(self, label):
149 """Set the label of the object, used by the MBDyn input file.""" 150 self.label = label 151 self.mbdyn_label = CommonArgument(str(label)) 152 self.mbdyn_label.set_comment(self.name)
153
154 - def set_comment(self, comment):
155 """Set a global comment on the object, 156 (takes one line in the MBDyn input file).""" 157 self.has_comment = True 158 self.comment = comment
159
160 - def get_lines(self):
161 """Return all the lines of the argument into a list, 162 used for writing the MBDyn input file.""" 163 lines = [] 164 for arg_name in self.arg_names[:-1]: 165 mbdyn_arg_name = get_mbdyn_name(arg_name) 166 mbdyn_arg = getattr(self, mbdyn_arg_name) 167 lines.append(mbdyn_arg.get_line()) 168 # The end of the last line must not have a comma. 169 # (The object block will close it by a semi-colon). 170 mbdyn_arg_name = get_mbdyn_name(self.arg_names[-1]) 171 mbdyn_arg = getattr(self, mbdyn_arg_name) 172 lines.append( mbdyn_arg.get_line(separator="") ) 173 return lines
174
175 - def set_simulation_ref(self, simu):
176 """Keep a reference of the simulation""" 177 self.simulation = simu
178
179 - def get_mbdyn_instance(self):
180 """Set a reference to the MBDyn instance, from the 181 L{mbdyn.bindings} under the C{mbdyn_inst} attribute. 182 However a general object can not get a MBDyn 183 instance by default. This step will be done according 184 to each group, labelling each object differently.""" 185 pass
186 187
188 -class ManagerObject:
189 """This object will add a vector or a matrix attributes 190 to others MBDyn objects (reference, node, element). 191 The idea is to simplify the tedious work 192 of adding a vector or a matrix to each of the object. 193 For the attribute name given and the users parameters Python value 194 will be created as well as a MBDyn value. 195 """ 196
197 - def __init__(self):
198 self.mbdyn_equivalent = {"one": "1", "two": "2", "three": "3"} 199 self.diagonal_instances = [tuple, list, N.ndarray]
200
201 - def add_argument(self, obj, name, value, com=None, mbdyn_value=None):
202 """Add a common argument to the object""" 203 mbdyn_name = get_mbdyn_name(name) 204 setattr(obj, name, value) 205 if mbdyn_value != None: 206 setattr(obj, mbdyn_name, CommonArgument(mbdyn_value)) 207 else: 208 setattr(obj, mbdyn_name, CommonArgument(value)) 209 if com != None: 210 obj.__dict__[mbdyn_name].set_comment(com)
211
212 - def __set_attr(self, obj, mbdyn_obj, name, mbdyn_name, reference):
213 """The object is in that case a MBDyn object. 214 As a result, the attribute names follow the convention: 215 - 'value' for the value of that object in the Python world 216 - 'name' for the name of that object in the MBDyn input file 217 """ 218 setattr(obj, name, mbdyn_obj.value) 219 geo_arg = GeometricArgument(mbdyn_obj.name, reference) 220 setattr(obj, mbdyn_name, geo_arg)
221
222 - def add_vector(self, obj, name, args, kargs):
223 """Adding a vector to a MBDyn object 224 """ 225 226 # Passing Python list and Numpy array/matrix could be done as well 227 if kargs.has_key("ref"): 228 reference = kargs["ref"] 229 else: 230 reference = obj.ref 231 mbdyn_name = get_mbdyn_name(name) 232 if len(args)==3: 233 value = N.array([arg for arg in args]) 234 setattr(obj, name, value) 235 mbdyn_value = ", ".join([str(arg) for arg in args]) 236 vector = GeometricArgument(mbdyn_value, reference) 237 setattr(obj, mbdyn_name, vector) 238 elif len(args)==1: 239 mbdyn_obj = args[0] 240 mbdyn_obj_name = mbdyn_obj.__class__.__name__ 241 if mbdyn_obj_name in VECTOR_NAMES: 242 self.__set_attr(obj, mbdyn_obj, name, mbdyn_name, reference) 243 if kargs.has_key("com"): 244 obj.__dict__[mbdyn_name].set_comment(kargs["com"])
245
246 - def add_matrix(self, obj, name, args, kargs):
247 """Adding a matrix to a MBDyn object 248 """ 249 if kargs.has_key("ref"): 250 reference = kargs["ref"] 251 else: 252 reference = obj.ref 253 mbdyn_name = get_mbdyn_name(name) 254 if len(args)==9: 255 value = N.array([ [arg for arg in args[0:3]], 256 [arg for arg in args[3:6]], 257 [arg for arg in args[6:9]] ]) 258 setattr(obj, name, value) 259 mbdyn_value = ", ".join([str(arg) for arg in args]) 260 matrix = GeometricArgument(mbdyn_value, reference) 261 setattr(obj, mbdyn_name, matrix) 262 elif len(args)==1: 263 mbdyn_obj = args[0] 264 mbdyn_obj_name = mbdyn_obj.__class__.__name__ 265 if mbdyn_obj_name in MATRIX_NAMES: 266 self.__set_attr(obj, mbdyn_obj, name, mbdyn_name, reference) 267 if kargs.has_key("diag"): 268 self._add_diagonal_matrix(obj, name, mbdyn_name, 269 kargs["diag"], reference) 270 if kargs.has_key("com"): 271 obj.__dict__[mbdyn_name].set_comment(kargs["com"])
272
273 - def _add_diagonal_matrix(self, obj, name, mbdyn_name, diagonal, reference):
274 """Add a diagonal matrix to the object""" 275 for reference_instance in self.diagonal_instances: 276 if isinstance(diagonal, reference_instance): 277 array = N.diag(diagonal) 278 279 setattr(obj, name, array) 280 281 string_args = [] 282 for idx in range(array.shape[0]): 283 string_args.append(str(array[idx][idx])) 284 mbdyn_value = "diag, " + ", ".join(string_args) 285 286 mbdyn_arg = GeometricArgument(mbdyn_value, reference) 287 setattr(obj, mbdyn_name, mbdyn_arg)
288
289 - def _scan_orientation_key(self, key, kargs, mbdyn_value):
290 """Method used for setting the orientation matrix 291 as a MBDyn input format. 292 """ 293 mbdyn_value += "%s, " % self.mbdyn_equivalent[key] 294 if kargs[key] == "guess": 295 mbdyn_value += "guess" 296 elif type(kargs[key]) == tuple: 297 mbdyn_value += ", ".join([str(val) for val in kargs[key]]) 298 else: 299 print "Unknow value '%s' for the key %s." % (str(kargs[key]), key) 300 return mbdyn_value
301
302 - def add_orientation_matrix(self, obj, name, args, kargs):
303 """Add an orientation matrix to the object. 304 """ 305 # TO DO: an orientation matrix should be defined no matter 306 # the input method used. 307 if kargs.has_key("ref"): 308 reference = kargs["ref"] 309 else: 310 reference = obj.ref 311 mbdyn_name = get_mbdyn_name(name) 312 # The case with keywords 313 mbdyn_value = "" 314 if kargs.has_key("one"): 315 mbdyn_value = self._scan_orientation_key("one", kargs, mbdyn_value) 316 if kargs.has_key("two"): 317 if mbdyn_value != "": 318 mbdyn_value += ", " 319 mbdyn_value = self._scan_orientation_key("two", kargs, mbdyn_value) 320 if kargs.has_key("three"): 321 if mbdyn_value != "": 322 mbdyn_value += ", " 323 mbdyn_value = self._scan_orientation_key("three", kargs, 324 mbdyn_value) 325 if mbdyn_value != "": 326 mbdyn_arg = GeometricArgument(mbdyn_value, reference) 327 setattr(obj, name, mbdyn_arg.get_line()) 328 setattr(obj, mbdyn_name, mbdyn_arg) 329 # A complete orientation matrix 330 if len(args)==9: 331 value = N.array([ [arg for arg in args[0:3]], 332 [arg for arg in args[3:6]], 333 [arg for arg in args[6:9]] ]) 334 setattr(obj, name, value) 335 mbdyn_value = ", ".join([str(arg) for arg in args]) 336 matrix = GeometricArgument(mbdyn_value, reference) 337 setattr(obj, mbdyn_name, matrix) 338 elif len(args)==3: 339 print "It should be the Euler angle, not so hard to do" 340 elif len(args)==1: 341 mbdyn_obj = args[0] 342 mbdyn_obj_name = mbdyn_obj.__class__.__name__ 343 if mbdyn_obj_name == EYE_NAME: 344 self.__set_attr(obj, mbdyn_obj, name, mbdyn_name, reference) 345 if kargs.has_key("com"): 346 obj.__dict__[mbdyn_name].set_comment(kargs["com"])
347 348 349 MANAGER = ManagerObject() 350
351 -class Block:
352 """The object for writing a block of arguments in the MBDyn input file 353 """ 354
355 - def __init__(self):
356 import sys 357 if sys.platform == "win32": 358 self.indent_char = "" 359 else: 360 self.indent_char = " "*4 361 self.indent_nb = 0 362 self.name = None 363 self.file = None
364
365 - def set_name(self, name):
366 """Set the name of the block 367 """ 368 self.name = name
369
370 - def indent(self):
371 """Indent the cursor of one more step.""" 372 self.indent_nb += 1
373
374 - def dedent(self):
375 """Dedent the cursor of a step.""" 376 self.indent_nb -= 1
377
378 - def set_file(self, file_to_write):
379 """Set the file on which the block will be written.""" 380 self.file = file_to_write
381
382 - def begin(self, name=None):
383 """Start the block in the MBDyn way, with 'begin:'""" 384 block_name = self.name 385 if name != None: 386 block_name = name 387 self.write_line("begin: %s;" % block_name) 388 self.indent()
389
390 - def end(self, name=None):
391 """End the MBDyn block with a 'end;'""" 392 block_name = self.name 393 if name != None: 394 block_name = name 395 self.dedent() 396 self.write_line("end: %s;" % block_name)
397
398 - def write_line(self, line):
399 """Write a line in the file with the right indentation 400 and the lineseparator of the operative system""" 401 #self.file.write(self.indent_char*self.indent_nb + line + os.linesep) 402 self.file.write(self.indent_char*self.indent_nb + line + "\n")
403
404 - def write_mbdyn_objects(self, obj_list):
405 """Write all the objects given in the list into the file, 406 manage the indentations""" 407 for obj in obj_list: 408 if obj.has_comment: 409 self.write_line("# %s" % obj.comment) 410 self.write_line("%s:" % obj.mbdyn_type) 411 self.indent() 412 for line in obj.get_lines(): 413 self.write_line(line) 414 self.dedent() 415 self.write_line(";")
416