1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
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
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
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