Package mbdyn :: Package bindings :: Module groups
[hide private]

Source Code for Module mbdyn.bindings.groups

  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  """The definition of all the MBDyn groups. The top class  
 23  of that module is L{ItemGroup}, an abstract class that will  
 24  be the base of a list of nodes, L{NodeGroup}, or a list of elements,  
 25  L{ElementGroup}. The motivation is to access any object inside  
 26  a group by a list syntax once the parsing of the MBDyn input file 
 27  done. As the simplest example:: 
 28   
 29      >>> wm = WraptMBDyn("input_file") 
 30      >>> wm.init() 
 31      >>> node = wm.nodes.structurals[0] 
 32   
 33  C{node} is a reference to the first structural node written in the input file. 
 34  Another example:: 
 35   
 36      >>> for node in wm.nodes.structurals: 
 37              print node.label 
 38   
 39          1001 
 40          1002 
 41          1003 
 42      >>> node = wm.nodes.structurals.get_from_label(1002) 
 43   
 44  The groups can be iterated as list. Moreover by knowing the MBDyn label 
 45  used in the input file, any reference to the C++ instance can be got  
 46  as a Python object.  
 47       
 48  The work of the group is also to answer to the  
 49  C{convert} method called by L{Groups}, and thus get down from the  
 50  MBDyn polymorphism. 
 51   
 52  Note also L{GROUP_TABLE}, a dictionary gathering the group descriptions  
 53  for nodes and elements in a table (or list of tuples). 
 54  Inside a table,  
 55  the first field is the MBDyn name of the group (used as an  
 56  enumeration in the C++ code). The second is the attribute name  
 57  that will be set in the L{Groups} class. The third and last field  
 58  is the class reference of the group, so then L{WraptMBDyn} will be  
 59  able to create the group class during its  
 60  L{init<mbdyn.bindings.main.WraptMBDyn.init>} method. 
 61  """ 
 62  from types import ListType 
 63   
 64  import mbdyn.bindings.swigModule as swigModule 
 65  from mbdyn.bindings.nodes import NODE_CLASS 
 66  from mbdyn.bindings.elements import ELEM_CLASS 
 67   
 68  from mbdyn.bindings.forces import FORCE_CLASS 
 69  from mbdyn.bindings.joints import JOINT_CLASS 
 70   
 71  CLASS = {} 
 72  CLASS["ELEM"] = ELEM_CLASS 
 73  CLASS["NODE"] = NODE_CLASS 
 74   
 75  # Will be updated with the time, when more than one 'general' class 
 76  # is written for the MBDyn bindings. Until now just different 
 77  # forces and joints are used. 
 78  CLASS["ELEM"]["FORCE"] = FORCE_CLASS 
 79  CLASS["ELEM"]["JOINT"] = JOINT_CLASS 
 80   
 81   
82 -class ItemGroup(ListType):
83 """An element or node group used by MBDyn. It will contains for sure 84 the pointers to the C++ C{Elem} or C{Node} instances that comes from the 85 MBDyn C{DataManager}. Those instances are however a very low 86 interest for the scripting language interface, the user can just 87 get the MBDyn label from it, see <mbdyn.bindings.basic_objects>. 88 89 To get down of the MBDyn polymorphism, the SWIG module (or C{swigModule} 90 in Python) provides a conversion function, that corresponds to 91 a dynamic cast in C++. At that step the function exists because 92 provided by L{Groups}, the groups manager. 93 """ 94
95 - def __init__(self, item_key, mbdyn_key, idx, nb_items):
96 ListType.__init__(self) 97 self.item_key = item_key 98 self.mbdyn_key = mbdyn_key 99 self.key = self.mbdyn_key.lower() 100 self.idx = idx 101 self.attr_name = GROUP[item_key]["ATTRIBUTES"][idx] 102 self.number = nb_items 103 self.label_list = []
104
105 - def add_item(self, item):
106 """Add an item to the list and keep track of its label""" 107 self.append(item) 108 self.label_list.append(item.label)
109
110 - def get_from_label(self, label):
111 """Return an item from its label""" 112 try: 113 return self[self.label_list.index(label)] 114 except ValueError: 115 mess = "The %s with label '%s' does not " + \ 116 "seem to be present in MBDyn" 117 print mess % (self.key, str(label))
118
119 - def common_conversion(self, convert_to_group_class):
120 """Convert the pointers to the Elem class of MBDyn 121 to the class of the group. Getting down of the MBDyn 122 polymorphism and in the same time add a layer between 123 the c_inst. 124 For example, the pointer Elem, pointing to an Elem 125 instance is converted to the pointer Force, pointing 126 to a Force instance by a dynamic cast""" 127 ItemClass = CLASS[self.item_key][self.mbdyn_key]["general"] 128 for item in self.clean_and_copy(): 129 c_inst = convert_to_group_class(item.c_inst) 130 new_item = ItemClass(c_inst) 131 self.append(new_item)
132
133 - def clean_and_copy(self):
134 """Clean the list, defined by self, and return 135 a copy of it 136 """ 137 self_copy = [] 138 for item in self: 139 self_copy.append(item) 140 for item in self_copy: 141 self.remove(item) 142 return self_copy
143
144 - def convert(self, convert_to_group_class):
145 """Will execute a common conversion. However this method 146 is supposed to be overridden by every specific group.""" 147 self.common_conversion(convert_to_group_class)
148 149
150 -class NodeGroup(ItemGroup):
151 """The top class for all the node group""" 152
153 - def __init__(self, mbdyn_key, idx, nb_elts):
154 ItemGroup.__init__(self, "NODE", mbdyn_key, idx, nb_elts) 155 self.convert_method_name = "convert_to_" + self.key + "_node"
156 157
158 -class Abstracts(NodeGroup):
159 """The "ABSTRACT" node group""" 160 pass
161 162
163 -class Structurals(NodeGroup):
164 """The "STRUCTURAL" node group""" 165 pass
166 167
168 -class NodeElectrics(NodeGroup):
169 """The "ELECTRIC" node group""" 170 pass
171 172
173 -class Parameters(NodeGroup):
174 """The "PARAMETER" node group""" 175 pass
176 177
178 -class NodeHydraulics(NodeGroup):
179 """The "HYDRAULIC" node group""" 180 pass
181 182
183 -class ElementGroup(ItemGroup):
184 """The top class for the element group""" 185
186 - def __init__(self, mbdyn_key, idx, nb_elts):
187 ItemGroup.__init__(self, "ELEM", mbdyn_key, idx, nb_elts) 188 self.convert_method_name = "convert_to_" + self.key
189 190
191 -class Rotors(ElementGroup):
192 """The "ROTOR" element group""" 193 pass
194 195
196 -class AutomaticStructurals(ElementGroup):
197 """The "AUTOMATICSTRUCTURAL" element group""" 198 pass
199 200
201 -class Gravities(ElementGroup):
202 """The "GRAVITY" element group""" 203 pass
204 205
206 -class Bodies(ElementGroup):
207 """The "BODY" element group""" 208 pass
209 210
211 -class Joints(ElementGroup):
212 """The "JOINT" element group""" 213
214 - def convert(self, convert_to_group_class):
215 """Convert a element to a joint""" 216 self.common_conversion(convert_to_group_class) 217 self._try_specific_type()
218
219 - def _get_new_type(self, elt):
220 """Return a new joint instance""" 221 JointClass = CLASS["ELEM"]["JOINT"][elt.class_key] 222 c_inst = getattr(swigModule, "convert_to_" + elt.class_key)(elt.c_inst) 223 return JointClass(c_inst)
224
225 - def _has_specific_type(self, elt):
226 """Test on the SWIG module if there is a function 227 to convert the current general reference to a more specific joint""" 228 conversion = "convert_to_" + elt.class_key 229 try: 230 getattr(swigModule, conversion) 231 return True 232 except AttributeError: 233 return False
234
235 - def _try_specific_type(self):
236 """Try to get the lowest part of the 237 MBDyn polymorphism, when 238 differents types exist inside the same group. 239 Example: DriveHingeJoint from Joint""" 240 for elt in self.clean_and_copy(): 241 if self._has_specific_type(elt): 242 new_elt = self._get_new_type(elt) 243 self.append(new_elt) 244 else: 245 self.append(elt)
246 247
248 -class Beams(ElementGroup):
249 """The "BEAM" element group""" 250 pass
251 252
253 -class Plates(ElementGroup):
254 """The "PLATE" element group""" 255 pass
256 257
258 -class Forces(ElementGroup):
259 """The "FORCE" element group""" 260
261 - def convert(self, convert_to_group_class):
262 """Convert a common element reference to the most specific one""" 263 self.common_conversion(convert_to_group_class) 264 self._try_specific_type()
265
266 - def _get_new_type(self, elt):
267 """Return the new force instance""" 268 force_type = elt.c_inst.get_force_type() 269 ForceClass = CLASS["ELEM"]["FORCE"][force_type] 270 c_inst = getattr(swigModule, "convert_to_" + force_type)(elt.c_inst) 271 return ForceClass(c_inst)
272
273 - def _has_specific_type(self, elt):
274 """Test if there is a conversion function on the SWIG module 275 for converting the reference to a more specific one""" 276 force_type = elt.c_inst.get_force_type() 277 conversion = "convert_to_" + force_type 278 try: 279 getattr(swigModule, conversion) 280 return True 281 except AttributeError: 282 return False
283
284 - def _try_specific_type(self):
285 """Try to get the lowest part of the 286 MBDyn polymorphism, when 287 differents types exist inside the same group. 288 Example: conservative and follower forces for this force group 289 """ 290 for elt in self.clean_and_copy(): 291 if self._has_specific_type(elt): 292 new_elt = self._get_new_type(elt) 293 self.append(new_elt) 294 else: 295 self.append(elt)
296 297
298 -class ElectricBulks(ElementGroup):
299 """The "ELECTRICBULK" element group""" 300 pass
301 302
303 -class Electrics(ElementGroup):
304 """The "ELECTRICS" element group""" 305 pass
306 307
308 -class Hydraulics(ElementGroup):
309 """The "HYDRAULICS" element group""" 310 pass
311 312
313 -class Bulks(ElementGroup):
314 """The "BULKS" element group""" 315 pass
316 317
318 -class Loadables(ElementGroup):
319 """The "LOADABLE" element group""" 320 pass
321 322
323 -class Drivens(ElementGroup):
324 """The "DRIVEN" element group""" 325 pass
326 327
328 -class Externals(ElementGroup):
329 """The "EXTERNAL" element group""" 330 pass
331 332
333 -class AirProperties(ElementGroup):
334 """The "AIRPROPERTIES" element group""" 335 pass
336 337
338 -class Aeromodals(ElementGroup):
339 """The "AEROMODAL" element group""" 340 pass
341 342
343 -class Aerodynamics(ElementGroup):
344 """The "AERODYNAMIC" element group""" 345 pass
346 347
348 -class Genels(ElementGroup):
349 """The "GENEL" element group""" 350 pass
351 352
353 -class SocketStreamOutputs(ElementGroup):
354 """The "SOCKETSTREAM_OUTPUT" element group""" 355 pass
356 357 358 GROUP_TABLE = {} 359 360 GROUP_TABLE["NODE"] = [ 361 ("ABSTRACT", "abstracts", Abstracts), 362 ("STRUCTURAL", "structurals", Structurals), 363 ("ELECTRIC", "electrics", NodeElectrics), 364 ("PARAMETER", "parameters", Parameters), 365 ("HYDRAULIC", "hydraulics", NodeHydraulics) 366 ] 367 368 # The element keys available in MBDyn 369 # it lacks: RTAI_OUTPUT = SOCKETSTREAM_OUTPUT, 370 # LASTELEMTYPE is not of use for the scripting language interface 371 372 GROUP_TABLE["ELEM"] = [ 373 ("ROTOR", "rotors", Rotors), 374 ("AUTOMATICSTRUCTURAL", "automatic_structurals", AutomaticStructurals), 375 ("GRAVITY", "gravities", Gravities), 376 ("BODY", "bodies", Bodies), 377 ("JOINT", "joints", Joints), 378 ("BEAM", "beams", Beams), 379 ("PLATE", "plates", Plates), 380 ("FORCE", "forces", Forces), 381 ("ELECTRICBULK", "electric_bulks", ElectricBulks), 382 ("ELECTRIC", "electrics", Electrics), 383 ("HYDRAULIC", "hydraulics", Hydraulics), 384 ("BULK", "bulks", Bulks), 385 ("LOADABLE", "loadables", Loadables), 386 ("DRIVEN", "drivens", Drivens), 387 ("EXTERNAL", "externals", Externals), 388 ("AIRPROPERTIES", "air_properties", AirProperties), 389 ("AEROMODAL", "aeromodals", Aeromodals), 390 ("AERODYNAMIC", "aerodynamics", Aerodynamics), 391 ("GENEL", "genels", Genels), 392 ("SOCKETSTREAM_OUTPUT", "socketstream_outputs", SocketStreamOutputs) 393 ] 394 395 GROUP = {} 396 397 for item_type in ["NODE", "ELEM"]: 398 GROUP[item_type] = {} 399 GROUP[item_type]["KEYS"] = [] 400 GROUP[item_type]["ATTRIBUTES"] = [] 401 GROUP[item_type]["CLASS"] = [] 402 for key, attr, class_name in GROUP_TABLE[item_type]: 403 GROUP[item_type]["KEYS"].append(key) 404 GROUP[item_type]["ATTRIBUTES"].append(attr) 405 GROUP[item_type]["CLASS"].append(class_name) 406