Package mbdyn
[hide private]

Source Code for Package mbdyn

  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  """This package is based on the top of 
 23  U{MBDyn<http://www.aero.polimi.it/~mbdyn/>}, a MultiBody Dynamics software 
 24  written at the university Politecnico di Milano. In MBDyn, a simulation is 
 25  started by providing an input file describing reference frames, nodes and 
 26  elements. This package motivation is to turn MBDyn into a multibody 
 27  dynamics library for U{Python<http://www.python.org>}, 
 28  so then the user communicates with objects during the whole simulation. 
 29  He does not describe its problem by a MBDyn input file any more. 
 30  But moreover he can interact with objects at run time. 
 31   
 32  Such project requires some vector and matrix manipulation, that will be 
 33  provided by the U{Numpy<http://numpy.scipy.org>} package.  
 34  To plot the results, the U{Matplotlib<http://matplotlib.sourceforge.net>} 
 35  package is suggested (and used during some examples) but not needed for 
 36  running a simulation. The communication with MBDyn is achieved and 
 37  documented in the L{mbdyn.bindings} package. The next section is  
 38  an overview about the MBDyn way of work and why the development  
 39  was started around it. The second section explains how Python was used 
 40  for getting new functionalities. What are the current achievements? 
 41   
 42  1 MBDyn description 
 43  =================== 
 44   
 45  MBDyn can also be defined as a multi physics application, with an aerodynamic, 
 46  electric, hydraulic and structural library. In this package, the work 
 47  has been limited to the structural one because the software was used in 
 48  mechanical engineering. The same approach could however been used for the 
 49  others fields.  
 50  Before explaining the reasons for developing new functionalities, the MBDyn 
 51  software in its current version deserves many credits. But the second section 
 52  will expose the problems encountered. 
 53   
 54  1.1 Thanks for this public service 
 55  ---------------------------------- 
 56   
 57  The first credit is surely the gathering 
 58  of a multibody dynamics community under a public 
 59  software. Realising the code under the General Public License (GPL) has opened 
 60  innovative and exhilarating development opportunities that a strategic 
 61  patenting approach would have completely denied. This point of view completely 
 62  fits the author status, that has developed this project as a part  
 63  of a Master thesis. All the others credits are to inherit from a significant 
 64  work for simulating multibody dynamics problem. Each library has been  
 65  developed by being based on three items: reference frames, nodes and elements. 
 66  The reference frames are only used to describe the problem, they will not 
 67  be part of the integration, but they allow to set the initial conditions 
 68  on nodes and elements. The nodes are the problem unknowns, they introduce 
 69  degrees of freedom. In structural mechanics (it was the only library 
 70  studied so far), each node represent 6 degrees of freedom: 3 translations 
 71  and 3 rotations. For solving the problem, those degrees of freedom need 
 72  to get constraints, so then there are as much equations as unknowns, and 
 73  moreover the equations need to be described. Those two roles are met by  
 74  elements as a consequence attached to nodes. 
 75  The elements available in this package are bodies, for introducing mass 
 76  and inertia quantities, forces, for supplying external works, joints, 
 77  for setting constraints and beams, for describing flexible multibody  
 78  problems. That approach deserves many credits because  
 79  the usual problems to start an integration from scratch have been 
 80  encapsulated into an interface. The theoretical part of MBDyn 
 81  is described in many  
 82  U{publications<http://www.aero.polimi.it/~mbdyn/publications.html>}, 
 83  the main one used during the development was the 
 84  U{Phd thesis of Pierangelo Masarati< 
 85  http://www.aero.polimi.it/~masarati/Publications/thesis.pdf>}. The software 
 86  is mature for mechanical engineering. Why was it needed to develop 
 87  functionalities? 
 88   
 89  1.2 Communication problematic with objects 
 90  ------------------------------------------ 
 91   
 92  As described, MBDyn allows a problem description by abstract items 
 93  (reference frames, nodes and elements) written in an input file, 
 94  but the user will certainly deal with a specific model. 
 95  Thus it could be convenient to describe  
 96  meaningful objects for the problem, manipulating the abstract ones.  
 97  The following section will introduce this problematic more in details. 
 98  Moreover once the MBDyn process starts, an interaction with its objects 
 99  is not available as an interface, but requires C++ development of the sources. 
100  This part is however addressed in the L{mbdyn.bindings} module. 
101   
102  User requirements 
103  ~~~~~~~~~~~~~~~~~ 
104   
105  By using a general description with nodes and elements, almost all 
106  the quantities computed were output in text files. Just some of the objects 
107  could write optional results, like for example dynamic structural nodes, 
108  but it could not be specified for every integrated quantity. It sounds 
109  really optional. Why does the user need such feature? Because he knows 
110  its model and useless operations at run time are critical as many iterations 
111  are involved. 
112  Some of the items are used only for the model building 
113  but will not output any interesting results. 
114  A variant would be to perform different simulations 
115  for the same model, a particular behavior being investigated each time.  
116  For example, a node under constraints does not need to output all 
117  its degrees of freedom, some of them will inherently be out of interest. 
118  If the user just want to know about the position of a node, there is no  
119  need to output the rotation matrix, velocity and angular velocity. C++ 
120  is fast but why does it do many useless operations? 
121  The reason comes from the input file. The user has already to supply 
122  a value for every field. If moreover he has to specify each quantity to save, 
123  or may want a particular degree of freedom, the parameters to write 
124  are too numerous.  
125   
126  Forcing the user to supply every field is furthermore relevant for a beginner, 
127  but not so convenient for an end user. 
128  For example for every node, the user has to write the position, rotation 
129  matrix, velocity and angular velocity relative to a reference frame. But a node 
130  is supposed to inherit from the reference frame attributes. 
131  If those last ones already described the node, 
132  the values entered will be a null position, 
133  velocity and angular velocity, the rotation matrix will be the identity one.  
134  Most of the nodes will be like that because the user needs to set up reference 
135  frames for defining the initial conditions of a complex problem.  
136  Generally just one or two parameters are specified differently between a node 
137  and its reference frame. As a result, it could be convenient to have default 
138  value for every item (reference frame, node or element). 
139  It could also be useful to describe a custom item having default values suited 
140  for the simulation. 
141       
142  The user may also need his own custom class based on an available one. 
143  The advantage is that he will then instantiate the same class in his script, that  
144  will avoid him to repeat the same description on the chosen library item. 
145  This is clearly a problem that developers can not guess, 
146  the goal is only to write a library for solving multibody  
147  problems. A suited template for a specific problem will be 
148  the user job that could as an alternative develop a  
149  corresponding library.  
150  Two requirements seem to be needed for the user: he would 
151  like to specify optional behaviors for some objects and by using the 
152  existing ones, he may need to describe its own class. Could it be easy 
153  for the developers? 
154   
155  Developer difficulties 
156  ~~~~~~~~~~~~~~~~~~~~~~ 
157   
158  The problem is also on the developer side. 
159  Parsing a text file does not really allow to have a field omitted. In the 
160  parser source code, there is a number of keywords expected for each item. By  
161  a series of tests, all the needed values are retrieved from string to C++  
162  U{data types<http://en.wikipedia.org/wiki/Data_type>}. Hence the instance 
163  is created. This method is efficient to find a syntax error or avoid 
164  the user to build an unexpected object. Let's now examine the problem 
165  of the optional fields. Extra tests will have to be added. But in case  
166  the number of parameters varies too much between a minimal and complete 
167  definition, it will be difficult to catch the syntax error. Was it  
168  the main keyword or an option expected? Moreover when the parsing occurs, 
169  the instance is not yet created because the values for initializing  
170  the 
171  U{constructor< 
172  http://en.wikipedia.org/wiki/Constructor_%28computer_science%29>} 
173  are still processed. Then it would not be convenient to have 
174  many optional fields in the constructor. But as an alternative  
175  as soon as the instance created, methods will be applied on  
176  it for setting the optional fields. An advantage of object 
177  oriented programming, dealing with an object without knowing 
178  its implementation, is lost because this is the developer 
179  that set options on an object that he knows. 
180  With a text file, there is furthermore no way that the user 
181  describe its own class from the existing ones. 
182  He has to dive in the C++ code. 
183  The discussion seems to be similar as in the L{mbdyn.bindings} module, 
184  the MBDyn design does not expose its objects structure to the user 
185  as a library does. But would not it be simpler for both users 
186  and developers? 
187   
188  Conclusion 
189  ---------- 
190   
191  To resume MBDyn is a great base for mechanical engineering, and 
192  simulation of multibody problems in general. The user inherits from a work 
193  done by expert researchers and publicly available. This is the gathering of 
194  those two points that really gives value to MBDyn. The limitations encountered 
195  were however in the communication part with the library, that can not be easily 
196  used to its full value. Hence Python is coming. 
197   
198  2 Providing new functionalities 
199  =============================== 
200   
201  The communication problem with MBDyn objects at run time is fully addressed in  
202  L{mbdyn.bindings}. Thus by filling an input file to L{WraptMBDyn}, the MBDyn 
203  integration can be controlled from Python. The next step is to write an interface 
204  to every MBDyn object. The first benefit will be to build a model 
205  by using the language features of Python. Then as the user deals with objects, 
206  it becomes easier to describe each item role than in a MBDyn input file. 
207  Finally the simulation results will be set as object attributes, facilitating 
208  the post processing. 
209   
210  2.1 Building models from Python 
211  ------------------------------- 
212   
213  The first point to highlight, is that the situation is simpler than in 
214  the L{mbdyn.bindings} module for the reason that the MBDyn service is not  
215  run. In the pre processing part, the task is finally to write a text file  
216  from Python in an object oriented way. 
217  This input file will start L{WraptMBDyn} and once 
218  the interaction finished, the post processing is also done without a running  
219  MBDyn. This point makes the development simpler because it can always 
220  been done in Python. Thus there is not all the work of compiling a C++  
221  U{shared library< 
222  http://en.wikipedia.org/wiki/Library_(computer_science)#Shared_library>} 
223  and  
224  U{SWIG<http://www.swig.org/>} 
225  extension with 
226  U{SCons<http://www.scons.org/>} 
227  , debugging memory allocation problems with  
228  U{GDB<http://sourceware.org/gdb/>} and so on. From here, how was Python used? 
229   
230  Python was used to describe an interface to every MBDyn object. The first 
231  advantage was the syntax (for example a class or function is defined 
232  by one keyword) and language features 
233  (list, dictionaries, everything object, third part packages). 
234  The crucial point is that Python allows  
235  U{references<http://en.wikipedia.org/wiki/Reference_%28computer_science%29>} 
236  to objects. It would have been difficult, and also surely obscure, to write 
237  an interface to a C++ code in a language that does not support this  
238  feature because the MBDyn design uses it heavily. The disadvantage is  
239  for the user coming from a language that never deals with references, 
240  that is to say  
241  U{Matlab<http://en.wikipedia.org/wiki/MATLAB>}. In that case the language 
242  will of course be simpler (so commercial advertisements are more attractive) 
243  but also very limited. On that point Python does well because it only  
244  simplifies the  
245  U{pointer<http://en.wikipedia.org/wiki/Pointer>} mechanism. For the user 
246  this is however very important to understand that once he has created  
247  an 
248  U{instance<http://en.wikipedia.org/wiki/Instantiation_%28computer_science%29>} 
249  , he will always manipulate references to it. This is where 
250  the interface really starts to make sense. By using this package, 
251  the user first describes an object suited for his problem. Then only  
252  the MBDyn ones are going to be simulated but at each time step,  
253  in his script, he will have references to the objects current status and can 
254  use them to solve its specific problem. All the Python libraries and services 
255  are moreover available.  
256   
257  A level of abstraction becomes possible, in the sense that the user writes 
258  a suited object, handling the MBDyn results that he wants. Then he can 
259  dialog with this new object, solving only a small part of the problem, 
260  and forgets about the MBDyn abstract objects (reference frames, nodes 
261  and elements). By connecting different 
262  small pieces together, the whole problem is getting solved. Moreover  
263  useful parts can be shared by different simulations by writing a specific 
264  module. Examples of this approach are used in the 
265  U{wind-sim-suite 
266  <http://mbdynsimsuite.sourceforge.net/windSimSuite/index.html>} 
267  project. 
268  The next section explains in details the pre-processing work 
269  with Python objects. 
270   
271  2.2 Pre-processing 
272  ------------------ 
273   
274  During the pre-processing part, the main progress is the possibility 
275  to deal with objects instead of having to write a MBDyn input file. 
276  Then how is this input file written? If the simulation is now  
277  started by a Python script, it should also be easier to describe 
278  each object role for both users and developers. The next paragraphs  
279  expose the package organisation on those points. 
280   
281  Input file writing 
282  ~~~~~~~~~~~~~~~~~~ 
283   
284  Each object is responsible of writing its part of the input file. 
285  Those informations finally represent how MBDyn will instantiate  
286  the C++ objects. This process could certainly be done by Python but 
287  it will require further development. Moreover the input file 
288  is maybe an intermediate step to keep. First it allows to check how 
289  the Python package is working. The user could ignore the input file 
290  syntax but in case of a simulation crash, he can test it independently 
291  on the MBDyn executable. 
292  Moreover the C++ parser checks 
293  also for model consistency by requiring a 'control data' section. 
294  As a resume, the input file is probably a good idea for the 
295  systematic process of a solver. 
296   
297  For making the simulation flexible, 
298  the Python interface does not require the control data any more, 
299  this work is done in the L{mbdyn.control_data} module. An user mistake  
300  will thus be issued by the MBDyn parser. Moreover every  
301  reference frames is supposed to have a distinct label, an integer,  
302  in order to describe the connectivity in the input file. The same remark 
303  applied for every item inside a group of nodes or elements. The groups 
304  are defined in the L{mbdyn.bindings.groups} module. As explained in the  
305  previous section, the user will now use references to describe 
306  the topology of its model. As a result, the L{mbdyn.groups} module 
307  will handle an automatic labelling of every item. That's why 
308  the C{BasicObject} of the L{mbdyn.common} module has a label as attribute. 
309  It will be the top class of every MBDyn item. The same label will also be 
310  used to retrieved the MBDyn instance generated by L{WraptMBDyn} when 
311  parsing the input file (this step is performed by the  
312  C{get_mbdyn_instance} method for each item). Finally, every information  
313  required by MBDyn needs also to be provided by the interface. The  
314  difference is that this last one will keep the information  
315  entered as Python object while it will need to be transformed as string 
316  for the text input file. This job is done by the C{ManagerObject}  
317  in L{mbdyn.common} that assures to have a Python value and a corresponding 
318  MBDyn one for every attribute concerned by the input file. The last 
319  step is to add every item to a L{Simulation<mbdyn.main.Simulation>} 
320  instance. What about the other interface problems? 
321   
322  Object description 
323  ~~~~~~~~~~~~~~~~~~ 
324   
325  Another design philosophy is that the user is supposed to know what he  
326  wants to simulate and as a consequence he has also an idea about 
327  the results.  
328  Clearly, the user knows which objects he wants (or he may be in a research 
329  phase) but he is anyway supposed to write a description in the input file. 
330  He will choose an item from the library, he has to, else there is 
331  no simulation. So this idea can be expressed by creating an instance and 
332  keeping a reference to it. For the user, doing:: 
333   
334      node1 = StructuralNode() 
335      node1.set_type("static") 
336      node2 = StructulalNode() 
337   
338      # Description to continue 
339   
340  is not not more painful than writing:: 
341   
342      begin: nodes; 
343          structural: 1, static, 
344          # description of node 1 goes here 
345           
346          structural: 1, dynamic, 
347          # description of node 2 goes here 
348       
349      end: nodes; 
350   
351  For the developers the situation becomes however really easier, 
352  because this is the user that choose the class from the library 
353  and create the instance. Thus he expresses more ideas 
354  than in a plain text file and he will directly dialog with 
355  the instance. In that case no tests are needed, 
356  if he fails in that part he will get a Python error. For  
357  scientists dealing with multibody dynamics problem, the Python bases 
358  are accessible very quickly. Similar simulations as the usual 
359  input files could be reproduced without many efforts. 
360   
361  But more can be done from that approach. When the  
362  user creates an instance, default settings are applied on it. 
363  They are described in the C{set_default} method of every object, 
364  as a start the reader can see L{mbdyn.nodes} and L{mbdyn.elements_base}. 
365  If the user sets the node or element relative to a reference frame, 
366  the default properties will be updated in that base. There  
367  are however still some problems, warned in  
368  L{that place<mbdyn.elements_base.ElementWithNode.set_relative_from>}. 
369  But the design idea is to apply method on the object for handling 
370  options. For example the attributes that need to be saved on 
371  the item will be specified by the C{will_save}, C{will_save_only} 
372  and C{will_save_nothing} methods applied on the 
373  L{Record<mbdyn.record.Record>} class (base of the 
374  L{BasicObject<mbdyn.common.BasicObject>} 
375  and thus every item). Then the internal saving process is addressed 
376  in details in the post-processing section. 
377   
378  Finally the Python syntax is a convenient way to build  
379  custom objects. In the section 1, the last user requirement 
380  is finally to re use the work done on the  
381  available library, hiding the complex implementation of each object, 
382  but then extend one of them to his problem. How is this idea 
383  achieved in computer science? By  
384  U{an inheritance 
385  <http://en.wikipedia.org/wiki/Inheritance_(computer_science)>}. 
386  How is it done  
387  in Python? In one line (including the class definition) or 
388  two lines in case of a custom constructor needed. The last section 
389  illustrates this idea by an example. 
390  If the user can now describe its problem from Python, how can  
391  he retrieves the results? 
392   
393  2.3 Post processing 
394  ------------------- 
395   
396  During the iterations, the results are added on Python objects 
397  and not saved in text files anymore. As a consequence 
398  the post-processing is now different because results are attributes 
399  of objects. But how is a simulation exactly saved? Is this approach 
400  really easier for exploring MBDyn outputs? 
401   
402  Python interaction 
403  ~~~~~~~~~~~~~~~~~~ 
404   
405  As described in the previous section, the user chooses the properties 
406  that he wants to save on an object. Thus he gets back  
407  his results according to the description of its problem, without  
408  the step to process text files. This step is achieved by the  
409  C{Record} class in L{mbdyn.record}. Then the results need to be 
410  saved at each time step, for this each concerned object has as 
411  a C{save} method. The main C{save} method, that will save all 
412  the object tree is performed by the  
413  L{Simulation<mbdyn.main.Simulation>}. However the C{Simulation} 
414  object is not aware about when a time step has been finished, 
415  because this part deals with the MBDyn service. That's why 
416  the C{save} method of the C{Simulation} is called by  
417  L{WraptMBDyn} in the L{mbdyn.bindings} module. At the end  
418  of the simulation, the complete object tree has been filled 
419  with results. The L{PyMBDynFile<mbdyn.main>} class is for 
420  that reason a container that will save simulations into 
421  a file. Then the user can load his simulation with results in another 
422  script. He has the same objects tree 
423  but that time filled with results. 
424  The usual MBDyn behavior, saving all the results 
425  in a file, can nevertheless be find back by the method 
426  C{write_mbdyn_files} on L{WraptMBDyn}. Thanks to the Python 
427  syntax, it is already easier 
428  to achieve post-processing in an interactive section 
429  than having to process text files. Is is possible to do more 
430  from that object-oriented approach? 
431   
432  Graphical exploration of results 
433  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
434   
435  Integrating MBDyn as an application programming interface in Python 
436  has open new doors for a graphical user interface. 
437  It was not the first objective but 
438  developing new functionalities bring often to such results.  
439  Programing in Python is easy comparing to the C++ language, 
440  with a minimum of efforts it directly brings the problem 
441  to the point of interest. As a result in the  
442  L{interface<mbdyn.interface>} package MBDyn objects has become 
443  able to deal with graphical libraries. The object tree organisation 
444  makes the interface design very evident. Each group will be 
445  stored as a part of a tree. Each item will have actions to offer 
446  from a menu according to its available results.  
447  The toolkit used for the graphical user interface is 
448  U{GTK<http://www.gtk.org/>}, the representation of 3D quantities 
449  is assured by 
450  U{VTK<http://www.vtk.org/>} and the figures are plotted with 
451  U{Matplotlib<http://matplotlib.sourceforge.net/>}. This is actually 
452  one more advantage of Python to be a popular language in free software 
453  projects. Most of the important libraries have Python bindings, 
454  moreover supplied in very reliable packages. For example many projects 
455  are using U{pyGTK<http://www.pygtk.org/>}.  
456  The development of the  
457  L{mbdyn.interface} package was started to solve mechanical problems 
458  in wind turbine engineering. The running application is only available 
459  in the  
460  U{wind-sim-suite project 
461  <http://mbdynsimsuite.sourceforge.net/windSimSuite/index.html>} 
462  but the work done could be re-used to visualize MBDyn results. 
463   
464  Project for final animation 
465  ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
466   
467  Another project has been started for realizing a graphical user 
468  interface with  
469  U{Blender<http://www.blender.org/>}:  
470  U{Blended MBDyn<http://www.osengineer.com/>} by John Kollman. With the 3D 
471  environment, the user describes his problem geometry and from it 
472  defined MBDyn objects. An input file is written, run, and each 
473  defined node will get results as  
474  U{Blender IPO curves 
475  <http://wiki.blender.org/index.php/Manual/Ipo_Curves_and_Keyframes>}. 
476  This work has inspired 
477  a big part of this package. However the problems encountered were 
478  the same as described in the section 1. The user would like to deal with  
479  a specific object for its problem (like a blade or a tower for a wind turbine) 
480  but the MBDyn simulation used only three kinds of items: reference frames, 
481  nodes and elements. During a research phase, the final geometry is not the most 
482  important because the physical model is still being implemented. Instead 
483  an interactive visualization of MBDyn items is needed, mainly reference frames 
484  and nodes, but in that case a custom graphical user interface needs 
485  to be developed. That's why the last problem is actually a programing fact: 
486  Blender is an application, not a library. This is a suit of tools 
487  for creating 3D contents, thus it has not been designed for multibody problems.  
488  Developing graphical interface is not easy because specific 
489  U{OpenGL<http://en.wikipedia.org/wiki/OpenGL>} 
490  widgets are used. For example this is difficult to implement a tree or set  
491  a menu on a custom object, it would require development of the C sources  
492  as a Blender extension. The application has however a very important 
493  functionality: a 3D scene can be described from Python.  
494  The MBDyn items that make a simulation could deformed a geometry. 
495  Only the position  of the nodes will be needed 
496  in that case and they will deform a mesh representing the user model. Two 
497  requirements arise: the geometry description is part of the user work 
498  (done with the Blender interface or from Python) and then the node results 
499  will somehow deform it. 
500  This solution will be the final step of a MBDyn model: when the simulation 
501  run correctly, illustrative results with meshes, textures and lights are 
502  rendered from Blender. The current package and the Blended MBDyn project 
503  are glue by Python but the connection has not yet been done. 
504   
505  2.4 A resuming example 
506  ---------------------- 
507   
508  At that step it may be difficult to follow what represents each  
509  section and what has been concretely achieved. The following 
510  example try to illustrate it. It could be bombarded with criticisms 
511  for being actually too simple and idealistic. It is true 
512  that the package has not yet 
513  reached a mature status and some solutions are probably more 
514  complicated than what they should be. But this section aims at giving 
515  a picture of the functionalities researched. 
516   
517  If the user wants to design a rotor, he will certainly set a hub node. 
518  The subject is dealing with mechanical engineering, so 
519  this node will be a structural node. First, let's create it:: 
520   
521      class HubNode(StructuralNode): 
522          pass 
523   
524  The inheritance is done but the new class has nothing new to offer. 
525  The node will be dynamic because it will deal with acceleration 
526  quantities and be attached to a body element for setting an inertia:: 
527   
528      class HubNode(StructuralNode): 
529   
530          def __init__(self, name="hub node"): 
531              StructuralNode.__init__(self, name) 
532              self.set_type("dynamic") 
533   
534  Notice the inheritance from the  
535  L{StructuralNode<mbdyn.nodes.StructuralNode>} achieved in two lines. 
536  The present application programming interface will give you the definition 
537  of every object. As the node is at the hub, it is supposed that 
538  only the rotational speed needs to be saved during the simulation.  
539  The too big simplicity of this example is here. In case the user 
540  wants to save the default quantities (position, rotation matrix..) and 
541  its own, he has also to customize the C{init_results} method of 
542  the L{Record<mbdyn.common.Record>} class for executing all the 
543  needed actions before saving the results. But the present 
544  example stays only with one quantity:: 
545   
546      class HubNode(StructuralNode): 
547   
548          def __init__(self, name="hub node"): 
549              StructuralNode.__init__(self, name) 
550              self.set_type("dynamic") 
551              self.rotational_speed = 0. 
552              self.will_save_only("rotational_speed") 
553   
554  Now the save method of the L{Simulation<mbdyn.main.Simulation>} will be 
555  called at each time step by L{WraptMBDyn}. The one of the C{HubNode} 
556  will be overriden:: 
557   
558      class HubNode(StructuralNode): 
559   
560          def __init__(self, name="hub node"): 
561              StructuralNode.__init__(self, name) 
562              self.set_type("dynamic") 
563              self.rotational_speed = 0. 
564              self.will_save_only("rotational_speed") 
565   
566          def save(self): 
567              rot_array = self.mbdyn_inst.get_rotational_speed() 
568              self.rotational_speed = rot_array[2][0] 
569              self.save_results() 
570   
571  The C{mbdyn_inst} is a reference to the MBDyn instance computed 
572  by the C++ code. This work is provided by the C{Simulation}. As 
573  a result, its rotational speed vector will be got at each time step 
574  but the user knows from its problem description that only the value 
575  along the M{z} axis is relevant. For the C{HubNode}, this is the 
576  only result saved. The hub node will now be used for a simulation 
577  description:: 
578   
579      hub_node = HubNode("hub node") 
580      # initial conditions go here (reference frame,  
581      # position, rotation_matrix...) 
582   
583      # Problem description with others nodes and elements 
584       
585      simu = Simulation() 
586      simu.add_node(hub_node) 
587      # others items are added 
588   
589      simu.run() 
590   
591      pyf = pyMBDynFile("rotor_simu.pymb", "w") 
592      pyf.add(simu) 
593      pyf.close() 
594   
595  All this code will be written in a Python script, for example  
596  'simulate_rotor.py' and the run will be achieved by  
597  C{python simulate_rotot.py}. It will create a file 'rotor_simu.pymb' 
598  with the run simulation contained inside. An important remark:  
599  the simulation does not know a C{HubNode} but the user has inherited 
600  from the C{StructuralNode} class so it works. Moreover, his code 
601  described in the C{save} method is executed at each time step. 
602  At the end, everything is saved in the C{pyMBDynFile} container, it  
603  can now be used in a loading script, 'load.py' :: 
604   
605      pyf = pyMBDynFile("rotor_simu.pymb") 
606      simu = pyf.simulations[0] 
607      strnodes = simu.nodes.structurals 
608   
609  Now 
610  U{IPython<http://ipython.scipy.org/>} 
611  can be used for interaction. The command C{ipython load.py} will 
612  open a session after executing the script:: 
613   
614      >>> hub = strnodes.get("hub node") 
615      >>> hub.results 
616      [rotational_speed] 
617   
618      >>> import pylab as P 
619      >>> P.plot(simu.results.time, hub.results.rotational_speed) 
620      >>> P.show() 
621   
622  The rotational speed is available through the C{results} attribute, 
623  instance of C{Results} defined in L{mbdyn.quantity}. With the 
624  three last lines, a figure showing the rotational speed 
625  according to the time should be plotted. 
626   
627  An drawnback can also be noticed, the user has created 
628  a specific object but at the end it is saved like any 
629  other node by the MBDyn simulation. That's why the node 
630  reference needs to be got back from its name. The solution would 
631  be that the user writes also its own C{Simulation} class, then  
632  he could handle a special object. Moreover any object could 
633  be saved with the simulation, assuming that it inherits from the 
634  L{Record<mbdyn.record.Record>} one. The next step would be to provide 
635  a neat interface to such requirements. This approach was however 
636  already used in the  
637  U{wind-sim-suite project 
638  <http://mbdynsimsuite.sourceforge.net/windSimSuite/index.html>}, 
639  where a wind turbine object can be added to the simulation. 
640   
641  3 Conclusion 
642  ============ 
643   
644  To conclude Python does not execute any integration but is just  
645  a language replacing the input file to describe a simulation. 
646  Its batteries included are however not a joke.  
647  Imitating the current way to write input files is possible 
648  but a complete programming language is now placed in 
649  the user hands. As a result he can describe its own objects 
650  that manipulate MBDyn ones, keep references of computed items, 
651  define its own and with some  
652  efforts extend the library for post-processing. 
653  This great flexibility has a price: the requirement to learn 
654  Python. But the reward is worth the hassle because the script 
655  is interactive and especially suited to his problem. 
656  Last but not least, third part packages could potentially improve 
657  the scientific usability of MBDyn:  
658  U{SciPy<http://www.scipy.org/>},  
659  U{PyDSTool<http://pydstool.sourceforge.net/>}, 
660  U{IPython<http://ipython.scipy.org/moin/>}, 
661  U{Matplotlib<http://matplotlib.sourceforge.net/>}... 
662  to name a few. Is there still a reason to not 
663  U{dive into Python<http://www.diveintopython.org/>}? 
664   
665  On the developer side, the significant advances are to turn  
666  MBDyn into a Python service and give more responsibility 
667  to the user. He is now supposed to know about an object when 
668  describing a simulation. In clear the parts where MBDyn was assisting 
669  a text file writer is now replaced by a Python interpreter assisting  
670  a script programmer. Is it a developer laziness? No, because 
671  people simulating multibody problems will surely know about 
672  numerical analysis. On that point Python is an user friendly 
673  language that has always powerful concepts hidden for later 
674  use. Concerning the MBDyn service, most of the actions done 
675  at run time should of course be performed in C++  
676  for speed reasons. New Python functionalities should be 
677  translated step by step. Nevertheless when a limitation 
678  is encountered, a Python framework seems more productive 
679  for development than dealing with C++ sources. 
680  """ 
681  __version__ = "0.2-r1" 
682  # Not author because of Epydoc  
683  __author_utf8__ = "André ESPAZE" 
684  __author_email__ = "ded.espaze@laposte.net" 
685  __mbdyn_developers__ = [ 
686  "Paolo Mantegazza", 
687  "Massimiliano Lanz", 
688  "Gian Luca Ghiringhelli", 
689  "Pierangelo Masarati",  
690  "Giuseppe Quaranta",  
691  "Marco Morandini",  
692  "Stefania Gualdi",  
693  "Michele Attolico",  
694  "Matteo Martegani", 
695  "Alessandro Fumagalli" 
696  ] 
697   
698  try: 
699      from mbdyn.bindings.main import WraptMBDyn 
700  except ImportError: 
701      pass 
702   
703  from mbdyn.general import NULL, EYE, MAT_NULL 
704  import mbdyn.law as law 
705   
706  from mbdyn.references import ReferenceFrame, GLOBAL_REF, NONE_REF 
707   
708  from mbdyn.nodes import StructuralNode 
709   
710  # Import of all the class contained in ELEM_CLASS 
711  import sys 
712  from mbdyn.elements import ELEM_CLASS 
713  for group_key in ELEM_CLASS.keys(): 
714      for class_name, ElemClass in ELEM_CLASS[group_key].items(): 
715          setattr(sys.modules[__name__], class_name, ElemClass) 
716  # Removed for not polluting 
717  del sys 
718  del ELEM_CLASS 
719  del group_key 
720  del class_name 
721  del ElemClass 
722   
723  from mbdyn.preprocessing import MultistepIntegrator 
724  from mbdyn.main import List, Simulation, PyMBDynFile 
725