FreeCAD as pre-post processor for MBDyn

About the development of the FEM module/workbench.

Moderator: bernd

T-Garnier
Posts: 18
Joined: Sat Jun 27, 2020 5:30 am

Re: FreeCAD as pre-post processor for MBDyn

Post by T-Garnier »

Hi,


Maybe add obj.Proxy = self in the onDocumentRestored method. (https://wiki.freecadweb.org/FeaturePython_methods)


And for the onChanged method a simpler way to do it could be by changing the obj.type strings as follow (add the curly bracket "{" and "}"] to replace each {variable} in the onchanged method with one call to fp.type.format(variable1=fp.variable1.value, variable2=fp.variable2,....).

Code: Select all

        obj.type=['const, <{const_coef}>',
                  'cosine, <{initial_time}>, <{angular_vel}>, <{amplitude}>, half, <{initial_value}>',
                  'cosine, <{initial_time}>, <{angular_vel}>, <{amplitude}>, one, <{initial_value}>',
                  'cosine, <{initial_time}>, <{angular_vel}>, <{amplitude}>, forever, <{initial_value}>',
                  'cosine, <{initial_time}>, <{angular_vel}>, <{amplitude}>, <{number_of_cycles}>, <{initial_value}>',                              
                  'cubic, <{const_coef}>, <{linear_coef}>, <{parabolic_coef}>, <{cubic_coef}>',
                  'direct',
                  'double ramp, <{a_slope}>, <{a_initial_time}>, <{a_final_time}>, <{d_slope}>, <{d_initial_time}>, forever, <{initial_value}>',
                  'double ramp, <{a_slope}>, <{a_initial_time}>, <{a_final_time}>, <{d_slope}>, <{d_initial_time}>, <{d_final_time}>, <{initial_value}>',
                  'double step, <{initial_time}>, <{final_time}>, <{step_value}>, <{initial_value}>',
                  'linear, <{const_coef}>, <{slope_coef}>',
                  'ramp, <{slope}>, <{initial_time}>, forever, <{initial_value}>',
                  'ramp, <{slope}>, <{initial_time}>, <{final_time}>, <{initial_value}>',
                  'sine, <{initial_time}>, <{angular_vel}>, <{amplitude}>, half, <{initial_value}>',
                  'sine, <{initial_time}>, <{angular_vel}>, <{amplitude}>, one, <{initial_value}>',
                  'sine, <{initial_time}>, <{angular_vel}>, <{amplitude}>, forever, <{initial_value}>',
                  'sine, <{initial_time}>, <{angular_vel}>, <{amplitude}>, <{number_of_cycles}>, <{initial_value}>',
                  'step, <{initial_time}>, <{step_value}>, <{initial_value}>',
                  'string, {string}',
                  'time',
                  'timestep',
                  'unit']
                  
and change the onChanged method as follow:

Code: Select all

fp.expression = fp.type.format(initial_time=fp.initial_time,
                               final_time=fp.final_time,
                               step_value=fp.step_value,
                               initial_value=fp.initial_value,
                               angular_vel=fp.angular_vel,
                               amplitude=fp.amplitude,
                               number_of_cycles=fp.number_of_cycles,
                               a_slope=fp.a_slope,
                               a_initial_time=fp.a_initial_time,
                               a_final_time=fp.a_final_time,
                               d_slope=fp.d_slope,
                               d_initial_time=fp.d_initial_time,
                               d_final_time=fp.d_final_time,
                               slope_coef=fp.slope_coef,
                               slope=fp.slope,
                               const_coef=fp.const_coef,
                               linear_coef=fp.linear_coef,
                               parabolic_coef=fp.parabolic_coef,
                               cubic_coef=fp.cubic_coef,
                               string=fp.string
                               )
Don't forget the .value everywhere it is needed. (quantity property)
Regards
josegegas
Posts: 241
Joined: Sat Feb 11, 2017 12:54 am
Location: New Zealand

Re: FreeCAD as pre-post processor for MBDyn

Post by josegegas »

Hi, thanks.

I wanted to ask you about how do you deal with orientations in the FreeCAD-MBDyn workbench you have programmed. Probably the biggest problem my workbench has is that I assume that all the nodes are parallel to the global reference frame. This makes things simpler when defining joints, because as you know, in MBDyn most joints require both, an absolute orientation and one or two relative orientation matrices (relative to the node or nodes involved). I use SymPy (https://www.sympy.org/en/index.html) to calculate the absolute orientation matrix of the joints, and since the nodes are assumed to be parallel to the global reference frame (initial conditions), the absolute orientation matrix is the same as the relative orientation matrix.

Some time ago I was able to put together your double rigid pendulum tutorial and run the simulation, however I have tried again and I was not able to successfully run it. I saw that you convert the FreeCAD orientation into an orientation in a format acceptable for MBDdyn, so that the nodes are automatically oriented as their bodies. I instead would like to allow the user define any random initial orientation, but I still did not find the way to calculate the relative orientation that most of the joints require.

I also wanted to ask you if you have tried to implement modal joints into FreeCAD. I think the next big step for this project would be to implement modal joints, which would allow the interaction with FEM, and thus modeling flexible bodies among the rigid ones. For this we also need the ability of producing a FEM file, as described in the input file manual, which recommends Code Aster or NASTRAN. I think this should ideally be done from within FreeCAD, but Im not sure if it is even possible to do so using the FEM workbench... What are your thoughts on this?

Regards.
josegegas
Posts: 241
Joined: Sat Feb 11, 2017 12:54 am
Location: New Zealand

Re: FreeCAD as pre-post processor for MBDyn

Post by josegegas »

I'll post this in case someone can guide me to a solution.

This is the input file that my workbench generates for a simple pendulum using a revolute pin joint:

Code: Select all

#-----------------------------------------------------------------------------
 # [Data Block]

 begin: data;
     problem: initial value;
 end: data;

 #-----------------------------------------------------------------------------
 # [Problem Block]

 begin: initial value;
     initial time: 0.0;
     final time: 6.0;
     time step: 0.01;
     max iterations: 100;
     tolerance: 1e-06;
     derivatives tolerance: 0.0001;
     derivatives max iterations: 100;
     derivatives coefficient: auto;
 end: initial value;

 #-----------------------------------------------------------------------------
 # [Control Data Block]

 begin: control data;
     default orientation: euler321;
     initial stiffness: 1.0, 1.0;
     structural nodes: 1;
     rigid bodies: 1;
     joints: 1;
     gravity;
 end: control data;

 #-----------------------------------------------------------------------------
 # [Design Variables]

     #User-defined variables
 
     #Gears

     #Generic bodies

         #body: 1
             set: real mass_1 = 66.67460147487209; #mass [kg]
             set: real volume_1 = 0.008439822971502796; #volume [m^3]
 
     #Cylinders

     #Spheres

     #Blocks

 #-----------------------------------------------------------------------------
 # [Intermediate Variables]

     #Moment of inertia

         #body 1: 
             set: real Ixx_1 = 0.9605252350251569; #moment of inertia [kg*m^2]
             set: real Ixy_1 = -0.024355294012603407; #moment of inertia [kg*m^2]
             set: real Ixz_1 = -0.8656268946264546; #moment of inertia [kg*m^2]

             set: real Iyx_1 = -0.024355294012603407; #moment of inertia [kg*m^2]
             set: real Iyy_1 = 1.8940142150778283; #moment of inertia [kg*m^2]
             set: real Iyz_1 = 0.028017560780677686; #moment of inertia [kg*m^2]

             set: real Izx_1 = -0.8656268946264546; #moment of inertia [kg*m^2]
             set: real Izy_1 = 0.028017560780677686; #moment of inertia [kg*m^2]
             set: real Izz_1 = 1.2038370876484414; #moment of inertia [kg*m^2]

 #-----------------------------------------------------------------------------
 # [Scalar functions]

 #-----------------------------------------------------------------------------
 # [Drive callers]

     drive caller: 1, name,"drive:1", const, 10.0;

 #-----------------------------------------------------------------------------
 # [Constitutive laws]

 #-----------------------------------------------------------------------------
 # [Nodes Block]

 begin: nodes;

     structural: 1,
                 dynamic,
                 0.2500000000000014, 1.459093333467299e-15, 1.0516032489249482e-15, #<absolute_position> [m]
                 3, 0., 0., 1., 2, 0, 1., 0., #<absolute_orientation_matrix>
                 0.0, 0.0, 0.0, #<absolute_velocity> [m/s]
                 0.0, 0.0, 0.0; #<absolute_angular_velocity> [rad/s]

 end: nodes;

 #-----------------------------------------------------------------------------
 # [Elements Block]

 begin: elements;

     #-----------------------------------------------------------------------------
     # [Bodies]

         body: 1,
               1, #<node_label> 
               mass_1, #<mass> [kg]
               -2.842170943040401e-17, -7.945098564120661e-18, -8.526512829121202e-17, #<relative_center_of_mass> [m]
               Ixx_1, Ixy_1, Ixz_1, #<inertia_matrix> [kg*m^2]
               Iyx_1, Iyy_1, Iyz_1,
               Izx_1, Izy_1, Izz_1;

     #-----------------------------------------------------------------------------
     # [Joints]

             joint: 1,
                    revolute pin,
                    1, #<node_label> 
                    -0.18867739505569478, -1.3223138568334799e-15, -0.16401475724762743, #<relative_offset> [m]
                    hinge, 3, 0.594591406729800, -0.422618261740699, -0.683999169507060, 2, guess, #<relative_orientation_matrix> 
                    0.06132260494430659, 1.3677947663381928e-16, -0.1640147572476264, #<absolute_pin_position> [m]
                    hinge, 3, 0.594591406729800, -0.422618261740699, -0.683999169507060, 2, guess; #<absolute_pin_orientation_matrix> 

     #-----------------------------------------------------------------------------
     # [Beams]

     #-----------------------------------------------------------------------------
     # [Plugin variables]

         #node: 1
 
     #-----------------------------------------------------------------------------
     # [Forces and couples]

         gravity: uniform, 0, -1.00000000000000, 0, string, "model::drive(1, Time)"; #<gravity_acceleration> [m/s^2]

     #-----------------------------------------------------------------------------
     # [Genels]

 end: elements;
As can be seen, the node is parallel to the global reference frame:

Code: Select all

3, 0., 0., 1., 2, 0, 1., 0., #<absolute_orientation_matrix>
and the hinge is pointing to a random direction relative to the global frame:

Code: Select all

hinge, 3, 0.594591406729800, -0.422618261740699, -0.683999169507060, 2, guess; #<absolute_pin_orientation_matrix> 
now, since the node is parallel to the global frame, the hinge's relative orientation is the same as its absolute orientation:

Code: Select all

hinge, 3, 0.594591406729800, -0.422618261740699, -0.683999169507060, 2, guess, #<relative_orientation_matrix> 
I use objects of the Line3D class, part of Sympy:

http://lidavidm.github.io/sympy/module ... ne3d.html

to calculate the orientations, as follows:

Code: Select all

        ##############################################################################Calculate the new absolute orientation:            
        ZZ = FreeCAD.ActiveDocument.getObjectsByLabel("z: joint: "+fp.label)[0]#get the joint´s rotation axis
        #Two 3D points that define the joint´s line:
        p1, p2 = Point3D(ZZ.Start[0], ZZ.Start[1], ZZ.Start[2]), Point3D(ZZ.End[0], ZZ.End[1], ZZ.End[2]) 
        l1 = Line3D(p1, p2)#Line that defines the joint
        
        magnitude = (l1.direction[0]**2+l1.direction[1]**2+l1.direction[2]**2)**0.5#Calculate the vector´s magnitude, so tat I can get the unitary vector
        
        #generate the orientation matrix:
        fp.absolute_pin_orientation_matrix = "3, "+ str(l1.direction[0]/magnitude) +", "+ str(l1.direction[1]/magnitude) + ", " + str(l1.direction[2]/magnitude) + ", " +"2, guess" 
The problem is that I still cannot calculate the relative orientation of the joint, so that if the user changes the initial orientation of the node, the simulation breaks.

So the question is, given the node's and the joint´s absolute orientations, in the format above:

Code: Select all

3, 0., 0., 1., 2, 0, 1., 0., #<absolute_orientation_matrix>
hinge, 3, 0.594591406729800, -0.422618261740699, -0.683999169507060, 2, guess; #<absolute_pin_orientation_matrix>
How can I calculate the hinge's relative orientation? It would be fantastic if it could be calculated only from these orientations as provided, in the same format. This would save me from a lot of work in changing the code of all the joints...

Any ideas will be very appreciated...
T-Garnier
Posts: 18
Joined: Sat Jun 27, 2020 5:30 am

Re: FreeCAD as pre-post processor for MBDyn

Post by T-Garnier »

Could you provide an access to your wip workbench ? I would like to take a look if I have some time.

For the question related to the orientation, it was mfasano who worked on it. So without check the code I can't tel you who it is done.

For the modal join yes it could be a nice feature. The problem, as you mentionned, is that mbdyn need a specific fileto to be able to run. Actually, from the mbdyn doc, the file can be createddirectly withcode_aster or nastran.
Nastran is a commercial finite element analysis package so a valid licence will be needed to create the file (and a prepost software to createthe model)
Code_aster is not supported in the FEM workbench (the last time I checked)
If i am not mistaking freecad FEM workbench is mainly for calculix and elmer.

So 2 script will be needed (1 per solver) to create the required file for mbdyn.
The workflow should be:
Create the fem model
Run a modal analysis
Run the TBD script to create the file
Link the file to the mbdyn model
Add postprocessing of finite element motion to mbdyn

(This is just my guess)
rock.vice
Posts: 22
Joined: Sat Jan 02, 2021 6:12 pm

Re: FreeCAD as pre-post processor for MBDyn

Post by rock.vice »

Hello,
I am trying to test your MBDyn workbench, but the FreeCAD 0.19.2 appimage does not include the sympy module and I have no idea if it is possible to install it externally and link the module to the workbench in some way.
I have seen other users getting the "No module named sympy" error, but I was not able to find a clear solution that could work with the appimage.

I am also wondering if we can ask the developers to include sympy (and the other relevant python modules for this workbench) by default in the upcoming 0.19.3.
This could simplify a lot our life... ;)

Regards and thank you for your effort.
Rocco V.

OS: KDE neon User - Plasma 25th Anniversary Edition (KDE/plasma)
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.19.24291 (Git) AppImage
Build type: Release
Branch: (HEAD detached at 0.19.2)
Hash: 7b5e18a0759de778b74d3a5c17eba9cb815035ac
Python version: 3.8.8
Qt version: 5.12.9
Coin version: 4.0.0
OCC version: 7.4.0
Locale: English/United States (en_US)
josegegas
Posts: 241
Joined: Sat Feb 11, 2017 12:54 am
Location: New Zealand

Re: FreeCAD as pre-post processor for MBDyn

Post by josegegas »

rock.vice wrote: Sun Nov 21, 2021 3:20 pm Hello,
I am trying to test your MBDyn workbench, but the FreeCAD 0.19.2 appimage does not include the sympy module and I have no idea if it is possible to install it externally and link the module to the workbench in some way.
I have seen other users getting the "No module named sympy" error, but I was not able to find a clear solution that could work with the appimage.

I am also wondering if we can ask the developers to include sympy (and the other relevant python modules for this workbench) by default in the upcoming 0.19.3.
This could simplify a lot our life... ;)

Regards and thank you for your effort.
Rocco V.

OS: KDE neon User - Plasma 25th Anniversary Edition (KDE/plasma)
Word size of OS: 64-bit
Word size of FreeCAD: 64-bit
Version: 0.19.24291 (Git) AppImage
Build type: Release
Branch: (HEAD detached at 0.19.2)
Hash: 7b5e18a0759de778b74d3a5c17eba9cb815035ac
Python version: 3.8.8
Qt version: 5.12.9
Coin version: 4.0.0
OCC version: 7.4.0
Locale: English/United States (en_US)
Hi. Have a look at the installation instructions in the GitLab page:

https://gitlab.com/josegegas/freecad-mb ... -workbench

You basically have to download, un-compress and paste both Sympy and mpmath into your bin folder...
rock.vice
Posts: 22
Joined: Sat Jan 02, 2021 6:12 pm

Re: FreeCAD as pre-post processor for MBDyn

Post by rock.vice »

Hi Jose,
thank you for your reply:
You basically have to download, un-compress and paste both Sympy and mpmath into your bin folder...
I read your notes for the installation on gitlab, but I do not understand how I can find the /bin directory in the FreeCAD archive since I just have a single appimage file used to run the program. My /home/<user>/.FreeCAD folder does not include a /bin folder as well. :?:
Probably I am missing/failing a very basic step.... I kindly ask you to point out and detail better the procedure I should follow

Many thanks,
Rocco V.
JamesLiu
Posts: 26
Joined: Sat Apr 28, 2018 6:23 am

Re: FreeCAD as pre-post processor for MBDyn

Post by JamesLiu »

rock.vice wrote: Mon Nov 22, 2021 12:40 am Hi Jose,
thank you for your reply:
You basically have to download, un-compress and paste both Sympy and mpmath into your bin folder...
I read your notes for the installation on gitlab, but I do not understand how I can find the /bin directory in the FreeCAD archive since I just have a single appimage file used to run the program. My /home/<user>/.FreeCAD folder does not include a /bin folder as well. :?:
Probably I am missing/failing a very basic step.... I kindly ask you to point out and detail better the procedure I should follow

Many thanks,
Rocco V.
Please try following steps:

1. Extract the AppImage

> ./FreeCAD_xxx.AppImage --appimage-extract
> cd squashfs-root/

2. Download and copy sympy and mpmath to squashfs-root/bin

> Download mpmath-1.2.0.tar from https://mpmath.org/
> Download sympy-1.7.1.tar https://github.com/sympy/sympy/releases

3. Repackage AppImage

> chmod +x ~/.local/bin/appimagetool-x86_64.AppImage
> ./appimagetool-x86_64.AppImage squashfs-root
> FreeCAD_Conda-X86_64.AppImage

GOOD LUCK!
JamesLiu
Posts: 26
Joined: Sat Apr 28, 2018 6:23 am

Re: FreeCAD as pre-post processor for MBDyn

Post by JamesLiu »

josegegas wrote: Sun Aug 08, 2021 2:00 pm Hi

So this has been probably the most challanging part of this project, at least so far. To simulate a CAM-follower such as in this example:

https://www.sky-engin.jp/en/MBDynExampl ... /ex13.html

The thing is that one needs a scalar function containig the shape of the cam. In FreeCAD of course the shape of the cam is determined by the CAD of the cam, so the challanging part was to convert the CAD shape of the cam into a scalar function. It took more than a month but finally got it. The algrithm will take the outer edges of the cam (or any other set of edges from a part), and generate a scalar function that follows the shape enclosed by the edges. This function can then be used for any purpose, in this case moving the followers:

The hole thing happens in the "AddScalarFunction" method of the "dynamics" class...
Is there any tutorial or instruction on this subject? I am trying to simulate gear transmission using your WB.
rock.vice
Posts: 22
Joined: Sat Jan 02, 2021 6:12 pm

Re: FreeCAD as pre-post processor for MBDyn

Post by rock.vice »

JamesLiu wrote: Fri Nov 26, 2021 6:33 am
Please try following steps:

1. Extract the AppImage

> ./FreeCAD_xxx.AppImage --appimage-extract
> cd squashfs-root/

2. Download and copy sympy and mpmath to squashfs-root/bin

> Download mpmath-1.2.0.tar from https://mpmath.org/
> Download sympy-1.7.1.tar https://github.com/sympy/sympy/releases

3. Repackage AppImage

> chmod +x ~/.local/bin/appimagetool-x86_64.AppImage
> ./appimagetool-x86_64.AppImage squashfs-root
> FreeCAD_Conda-X86_64.AppImage

GOOD LUCK!
Thank you very much for the clarification: I was not aware of the possibility to extract and to modify the AppImage
Your procedure worked perfectly!
Post Reply