A Tutorial of The SixDofRigidBodyMotion Library
A Tutorial of The SixDofRigidBodyMotion Library
Project work:
Disclaimer: This is a student project work, done as part of a course where OpenFOAM and some
other OpenSource software are introduced to the students. Any reader should be aware that it
might not be free of errors. Still, it might be useful for someone who would like learn some details
similar to the ones presented in the report and in the accompanying files. The material has gone
through a review process. The role of the reviewer is to go through the tutorial and make sure that
it works, that it is possible to follow, and to some extent correct the writing. The reviewer has no
responsibility for the contents.
1
Contents
Chapter 3 Discussion 20
3.1 Future work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Chapter 4 References 21
2
Chapter 1
Tutorial sixDoFRigidBodyMotion
1.1 Introduction
This tutorial describes how the sixDoFRigidBodyMotion library works and how to use the library
for several coupled and uncoupled rigid bodies. It also describes how to modify and implement
your own sixDoFRidigBodyMotion library to output the rotational Euler angles of a rotating solid
body. A short guide describing useful commands and mesh refinements for snappyHexMesh is also
included the tutorial.
The use of the uncoupled and coupled sixDoFRigidBodyLibrary will be demonstrated on a tutorial
case in OpenFOAM called floatingObject. The tutorial is modified to have two floating objects as in
figure 1.1a. One of the implementations will be shown on a 2D case consiting of a boat with a hydro-
foil (figure 1.1b) demonstrating the use of snappyHexMesh and when the sixDoFRigidBodyMotion
coupled solver is useful.
3
1.2. BACKGROUND CHAPTER 1. TUTORIAL SIXDOFRIGIDBODYMOTION
1.2 Background
By solving the motion of a solid body caused by the forces acting on it we can for example predict
the transient behaviour of a boat or the output power of a turbine more accurately. OpenFOAM
improved the capability of the sixDoFRigidBodyMotion solver in version 2.3.x which can now handle
mesh motion and several rigidly coupled bodies. The purpose of this report is to give the reader
insight in how to use the coupled and uncoupled sixDoFRigidBodyMotion solver and in which
situations they’re useful for the user.
1.3 Theory
OpenFOAMs sixDoFRigidBodyMotion solver is capable of solving translational and rotational move-
ment of a solid body in the three axises xyz. SixDoFRigidBodyMotion solves the motion of a body
based on the forces acting on it. The user is able to use the sixDoFRigidBodyMotion library with
the solvers using dynamic mesh such as pimpleDyMFoam or interDyMFoam.
here m denotes the mass and I denotes the inertia. By intergrating the angular and translational
acceleration over the time step as
Z t
ω new = αdt = ω old + α∆t
told
Z t
vnew = adt = vold + a∆t, (1.2)
told
we get the current angular velocity ω new and velocity v new . From ω new and v new we can get the
angle rotated and the distance traveled from the last time step.
4
1.4. TUTORIAL - SIXDOF CHAPTER 1. TUTORIAL SIXDOFRIGIDBODYMOTION
In OpenFOAM 2.4.x it is possible to use both uncoupled and coupled (introduced in 2.3.x) motion
of several patches. The sixDoFRigidBodyMotion library has two seperate solvers to handle coupled
or uncoupled movement. The following tutorials will show the user how the coupled and uncou-
pled solver of sixDoFRigidBodyMotion can be used. To show the differences between coupled and
uncoupled rigid body motion for seperate patches we will use the floatingObject tutorial as our
base. The floatingObject tutorial shows how to simulate the motion of a floating body due to
disturbed water with the use of sixDoFRigidBodyMotion. We will add a second floating object to
this tutorial and simulate their motion both as a coupled rigid body and as two seperate uncou-
pled rigid bodies. Switching between coupled and uncoupled motion requires modifications to the
0\pointDisplacement and dynamicMeshDict file which will be shown in the tutorial.
The standard tutorial uses topoSet to extract and remove a box of cells located in the domain
forming the floating object. To get two floating objects we add a second system/topoSetDict file
so that we can create the two floating objects needed. Copy the system/topoSetDict file with the
following.
cp system/topoSetDict system/topoSetDict2
We need to make modifications to the system/topoSetDict2 file to reposition the second object
as well as rename the cellSet. Edit the system/topoSetDict2 with a text editor and change the
name from c0 to c1 in both locations as well as decrease the distance in x-direction of the box by
one meter. After the changes your system/topoSetDict2 should look like Code 1.1.
5
1.4. TUTORIAL - SIXDOF CHAPTER 1. TUTORIAL SIXDOFRIGIDBODYMOTION
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
actions
(
{
name c1;
type cellSet;
action new;
source boxToCell;
sourceInfo
{
box (-0.65 0.35 0.1) (-0.35 0.55 0.6);
}
}
{
name c1;
type cellSet;
action invert;
}
);
// ************************************************************************* //
To fit the new floatingObject2 in our computational domain we need to make the appropriate
changes to the domain size in the constant/polyMesh/blockMeshDict file. We increase the length
of the domain in x-direction by moving the vertices located at x = 0 to x = -1. In order to keep
the same cell dimensions as previously we increase the cell count in x-direction from 20 to 40.
Finally we also need to add the second floating object by copying the first one and renaming it to
floatingObject2. With all the changes made the constant/polyMesh/blockMeshDict file should
look like Code 1.2 (notice the changes in vertices, blocks and the added floatingObject2).
6
1.4. TUTORIAL - SIXDOF CHAPTER 1. TUTORIAL SIXDOFRIGIDBODYMOTION
convertToMeters 1;
vertices
(
(-1 0 0)
(1 0 0)
(1 1 0)
(-1 1 0)
(-1 0 1)
(1 0 1)
(1 1 1)
(-1 1 1)
);
blocks
(
hex (0 1 2 3 4 5 6 7) (40 20 30) simpleGrading (1 1 1)
);
edges
(
);
boundary
(
stationaryWalls
{
type wall;
faces
(
(0 3 2 1)
(2 6 5 1)
(1 5 4 0)
(3 7 6 2)
(0 4 7 3)
);
}
atmosphere
{
type patch;
faces
(
(4 5 6 7)
);
}
floatingObject
{
type wall;
faces ();
}
floatingObject2
{
type wall;
faces ();
}
);
mergePatchPairs
(
);
// ************************************************************************* //
7
1.4. TUTORIAL - SIXDOF CHAPTER 1. TUTORIAL SIXDOFRIGIDBODYMOTION
The boundary conditions for the second floating object, floatingObject2, are set in the 0.org\
folder. The alpha.water, epsilon, k, nut, pointDisplacement, p_rgh, and U files in the 0.org\
need to be modified so that they contain boundary conditions for floatingObject2. Copy and use
the same values for floatingObject2 as for floatingObject in each of the files. Once the second
floating object has all the boundary conditions edit the pointDisplacement file. To use the coupled
solver for sixDoFRigidBodyMotion we add the second object to the constants/dynamicMeshDict
as a patch. The physical properties need to be changed since the two floating objects are treated
as one body. For the sake of simplicity we will change the mass and centreOfMass only. The mass
is trippled and the centreOfMass is moved by 0.5 meter in the negative x-direction. Note that
this does not represent real physical properties of the floating objects but is used in order run the
simulation and build upon this case for the uncoupled movement.
// Cuboid dimensions
Lx 0.3;
Ly 0.2;
Lz 0.5;
// Cuboid mass
mass #calc "$rho*$Lx*$Ly*$Lz*3"; //Change mass
Code 1.3 shows part of the constants/dynamicMeshDict file with the neccesary changes to patches,
centreOfMass and mass. The case is now ready to be run manually however to make it easier to
run we modify the Allrun script so it can be used for this case. The script is modified to make two
objects, floatingObject from cellSet c0 and floatingObject2 from cellSet c1. Inbetween
the making of the two floating objects we need to remove or rename the log.subsetMesh and
log.topoSet. The final script is shown in code 1.4. Replace all text in the Allrun script with the
text in code 1.4 (copy-paste).
runApplication blockMesh
runApplication topoSet -dict system/topoSetDict
runApplication subsetMesh c0 -patch floatingObject -overwrite
mv log.subsetMesh log.subsetMesh0
mv log.topoSet log.topoSet0
runApplication topoSet -dict system/topoSetDict2
runApplication subsetMesh c1 -patch floatingObject2 -overwrite
cp -r 0.org 0 > /dev/null 2>&1
runApplication setFields
runApplication $application
# ----------------------------------------------------------------- end-of-file
Run the case by using the Allrun script. Type ./Allrun in the terminal window.
8
1.4. TUTORIAL - SIXDOF CHAPTER 1. TUTORIAL SIXDOFRIGIDBODYMOTION
Figure 1.2 shows the results after 4.2 seconds where we can see that both bodies have move and
that the mesh around them has deformed. The bodies in this tutorial have moved as one solid body
which can be easily seen while playing the animation during post processing.
9
1.4. TUTORIAL - SIXDOF CHAPTER 1. TUTORIAL SIXDOFRIGIDBODYMOTION
cd $FOAM_RUN
cp -r TwoFloatingObjects TwoFloatingObjects_c2
cd TwoFloatingObjects_c2
./Allclean
In order to use the uncoupled sixDoFRigidBodyMotion solver we need to edit the constants/dynamicMeshDict
and 0.org/pointDisplacement file. When using the uncoupled solver we only specify the solvers we
want to use in the constants/dynamicMeshDict file and all the physical properties of the bodies are
specified in the 0.org/pointDisplacement instead. We need to add the libfvMotionSolvers.so li-
brary to solve the mesh motion and add the appropriate solver settings. Edit the constants/dynamicMeshDict
file, the text in code 1.5 can be copy-pasted to replace all text in the constants/dynamicMeshDict
file.
dynamicFvMesh dynamicMotionSolverFvMesh;
motionSolverLibs
(
"libsixDoFRigidBodyMotion.so"
"libfvMotionSolvers.so" //Add libfvMotionSolvers.so
);
// ************************************************************************* //
10
1.4. TUTORIAL - SIXDOF CHAPTER 1. TUTORIAL SIXDOFRIGIDBODYMOTION
Next we need to make the appropriate changes in the 0.org/pointDisplacement file for the two rigid
bodies. The properties of the floating objects can be the same as in the original floatingObject
tutorial with the exception of moving the centreOfMass and centreOfRotation by one meter in
the positive x-direction. Copy-paste the text in code 1.6 for floatingObject2.
// Cuboid dimensions
Lx 0.3;
Ly 0.2;
Lz 0.5;
// Cuboid mass
mass #calc "$rho*$Lx*$Ly*$Lz";
code
#{
scalar sqrLx = sqr($Lx);
scalar sqrLy = sqr($Ly);
scalar sqrLz = sqr($Lz);
os <<
$mass
*diagTensor(sqrLy + sqrLz, sqrLx + sqrLz, sqrLx + sqrLy)/12.0;
#};
};
report on;
accelerationRelaxation 0.3;
constraints
{
fixedLine
{
sixDoFRigidBodyMotionConstraint line;
centreOfRotation (-0.5 0.45 0.1);
direction (0 1 0);
}
fixedAxis
{
sixDoFRigidBodyMotionConstraint axis;
axis (0 1 0);
}
}
}
The same settings is used for floatingObject with the exception of centreOfMass and centreOfRotation
which should be the following.
After you have added the correct properties to the seperate floating bodies we need to add informa-
tion about the cellDisplacement in the system/fvSolution file. These settings are used for the
11
1.4. TUTORIAL - SIXDOF CHAPTER 1. TUTORIAL SIXDOFRIGIDBODYMOTION
Copy-paste the settings in code 1.8 which adds the necessary information about the cellDisplacement
to the system/fvSolution file. The case in now ready to run. Use the same Allrun script. Type
into the terminal.
./Allrun
Figure 1.3 shows the two uncoupled floating objects. When playing the animation while post pro-
cessing it’s clear that the two floating objects are not mechanically coupled. From the figure we can
see a small amount of mesh deformation as well as a small difference in angle between the bodies.
12
1.4. TUTORIAL - SIXDOF CHAPTER 1. TUTORIAL SIXDOFRIGIDBODYMOTION
cd $FOAM_RUN
cp -r TwoFloatingObjects_c2 TwoFloatingObjects_c3
cd TwoFloatingObjects_c3
./Allclean
To show that the motion of floatingObject2 is only influenced by floatingObject we remove the
initial wave created in system/setFieldsDict. Remove the second boxToCell in the system/setFieldsDict
file so that the regions only contains the initial water level as shown in code 1.10.
Run the case using the same Allrun script as previously. Type into the terminal.
./Allrun
Figure 1.4: Case 2 - Two floating objects, sixDoF and prescribed motion
Figure 1.4 shows how floatingObject2 (left object in figure 1.4) has been rotated because of the
motion of floatingObject (right object in figure 1.4). This is easily seen when post processing and
playing the animation. This type of implementation can be useful when simulating the motion of a
boat induced by the opening of a dam for instance.
13
1.4. TUTORIAL - SIXDOF CHAPTER 1. TUTORIAL SIXDOFRIGIDBODYMOTION
The simulation seen in figure 1.5 is meshed using snappyHexMesh and the surface of the boat and
hydrofoil was made in a seperate CAD software. Download the case from the course webpage con-
taining the simulation files and geometry. When meshing such a case we need seperate patch names
for both the hydrofoil and the hull since they have very different mesh requirements for the surface.
The coupled implementation of sixDoFRigidBodyMotion solver is useful in such a case since the
hydrofoil and boat are easily connected as one rigid body even though they have seperate patches,
as we saw in tutorial Case 1. When simulating such a case it’s important that the surrounding mesh,
especially in-between the hull and hydrofoil, is deformed properly. In this case the movement of the
boat is relativly large so it’s important that the cells in-between the hull and hydrofoil follow the
movmement of the boat.
14
1.4. TUTORIAL - SIXDOF CHAPTER 1. TUTORIAL SIXDOFRIGIDBODYMOTION
The case is run parallel and is set up to run on 4 CPU-cores. Edit the Allrun script and the
system/decomposeParDict file if you wish to alter the number of cores to run on. Run the down-
loaded case with the included Allrun script. The case is rather computationally heavy so it’s
recommended to start the simulation and then look at how it is setup. The case is largly based on
the DTCHull tutorial located in $FOAM_TUTORIALS/multiphase/interDyMFoam/ras/DTCHull/.
Code 1.11 shows the complete Allrun script for the case. Compared to the previous tutorials
this case uses snappyHexMesh to mesh the geometry. More information on commands and tips on
snappyHexMesh follows in the next section, section 1.4.5. Looking at the Allrun script we can
see that after running snappyHexMesh we run the application extrudeMesh. This is done in order
to extract a 2D mesh from the xy-plane since snappyHexMesh can only mesh in 3D. Other than
snappyHexMesh the case is similar to the previous tutorials with the addition of running in parallel.
The domain is decomposed into smaller domains to be run parallely on 4 processors. Once the
simulation is finished we reconstruct the smaller domains into one domain again which can be post
processed with the application reconstructPar. Figure 1.6 shows how the cells in-between the
hull and hydrofoil have followed the movement of the boat except further away where we can see
some distortion of the cells in the red marked area. For cases with very large deformations an
alternative strategy such as overset mesh can be used. To control which cells should be affected
by the movement of the boat we use the innerDistance and outerDistance command in the
constant/dynamicMeshDict. innerDistance sets the distance at which the cells close to the body
ridigly follow the movement of that body while outerDistance sets how far out from the body we
deform cells.
15
1.4. TUTORIAL - SIXDOF CHAPTER 1. TUTORIAL SIXDOFRIGIDBODYMOTION
Refinements
Refinements in snappyHexMesh can be set as a volume, surface or distance refinements. Volume
refinements can be set with a searchableBox among others, such as searchableCylinder, and the
amount of refinement can be set by levels with the refinement located inside a searchableBox for
example.
refinementBox
{
type searchableBox;
min (-999 -0.5 -1);
max (999 1.7 1);
}
refinementRegions
{
refinementBox
{
mode inside;
levels ((2 2));
}
}
The above code shows an example where a refinement is placed within a box with a minimum and
maximum refinement level of 2. The refinements level refers to how many times smaller the cell
sides should be within the searchableBox. An increase in refinement of one level means that the
sides of the cell will be half as long, or an 8 times reduction in volume for 3D meshes, which can
lead to a rapid increase in cell count if the level is set too high. Volume refinements can also be set
as a distance from a surface. The code below demonstrates how to set the refinement level of the
cells that are located within 0.2 m from the patch named hydrofoil.
refinementRegions
{
hydrofoil
{
mode distance;
levels ((0.2 4));
}
}
This type of refinement can be useful when the user needs a certain level of refinement close to the
surface of a particular patch. nCellsBetweenLevels is the cell growth rate, or the number of layers
of cells with the same level before changing level. nCellsBetweenLevels together with distance
based volume refinements can be effectivly used to control the overall cell count and near surface
cell size.
Surface refinements can be specified as the code below shows. The author found that the cell count
can rapildy increase when increasing the level and that the best surface quality was obtained when
using the same maximum and minimum refinement level.
refinementSurfaces
{
hull
{
// Surface-wise min and max refinement level
level (4 4);
}
}
The author recommends that the user starts with the surface refinements while keeping the volume
refinements coarse for a new case. This allows the user to fast find what surface refinement level is
needed to capture the detail the user needs before increasing the cell count with volume refinements
and growth rates. Try reducing the levels of refinement on the different refinements by one level
in the system/snappyHexMeshDict and remeshing the case. Note how the cell count and meshing
16
1.4. TUTORIAL - SIXDOF CHAPTER 1. TUTORIAL SIXDOFRIGIDBODYMOTION
times reduces. Do the same again but increase the levels by one level from the default case. It
becomes clear that the refinements levels have a big impact on cell count and meshing time which
can make fine tuning of the mesh cumbersome.
extrudeMesh - 3D to 2D mesh
extrudeMesh is a utility that can be used to convert a 3D mesh into a 2D mesh. snappyHexMesh is
not capable of creating a 2D mesh by it’s own. The utility extrudeMesh allows the user to convert
a 3D mesh from snappyHexMesh into a 2D mesh. The wingMotion tutorial uses this utility, located
at $FOAM_TUTORIALS/incompressible/pimpleDyMFoam/wingMotion/.
The above command shows an example when scaling a .stl file from mm to m.
surfaceTransformPoints can also be used to translate and rotate a geometry. This funtion of the
utility can be useful when running an airfoil simulation for many different angles of attack. The user
could use this utility in a script to run many different angles of attack instead of manually rotating
and saving the geometry in CAD software.
17
Chapter 2
Tutorial - sixDoFRigidBodyMotion
output, Euler angles
For previous tutorial cases it can be good to get the rotational movement of the bodies for post
processing. This tutorial shows how to copy and modify the sixDoFRigidBodyMotion solver to
output the Euler angles expressed in degrees for the three axes x, y and z.
Add Code 2.1 to the sixDoFRigidBodyMotionAngle.C starting at line 340 in the sixDoFRigidBodyMotionAngle.C
file. This will output the Euler angles while running which the user can later post process to plot
the angular movement over time.
While still in the sixDoFRigidBodyMotionAngle.C file we can see the theory that was presented in
equation 1.2 at line 271-272.
There are differences from the theory. In code 2.2 we have additional translational (tConstraints_)
and rotational (rConstraints_) constraints, acceleration damping (aDamp_) as well as a scalar 0.5.
The scalar 0.5 is used because each time step is split into two, the first half of the timestep leapfrog
moves the body updating the position while the second half updates the acceleration. Together they
make up the movement and acceleration update of the entire timestep. For more information on
how the rotation quaternion is used in OpenFOAM see the 6-DOF VOF-solver without Damping in
OpenFOAM report by Erik Ekedahl [2].
18
2.1. EULER
CHAPTER
ANGLES
2. TUTORIAL - SIXDOFRIGIDBODYMOTION OUTPUT, EULER ANGLES
Modify the Make/files file to contain the new sixDoFRigidBodyMotionAngle.C file and change
the library location.
Change the first and last line in the Make/files file to match Code 2.3
...
...
...
LIB = $(FOAM_USER_LIBBIN)/libsixDoFRigidBodyMotionAngle
cp -r $FOAM_TUTORIALS/multiphase/interDyMFoam/ras/floatingObject/ $FOAM_RUN
cd $FOAM_RUN
cd floatingObject/constant
Change the dynamicMeshDict file to use the modified sixDoFRigidBodyMotion solver by adding
Angle to the end as Code 2.4 shows.
solver sixDoFRigidBodyMotionAngle;
sixDoFRigidBodyMotionAngleCoeffs
Run the tutorial and look at the output from the interDyMFoam solver. The output should now
contain the Euler angle (in degrees) as Code 2.5.
19
Chapter 3
Discussion
The different sixDoFRigidBodyMotion solver gives the user an easy possibility to implement several
uncoupled or rigidly coupled rigid bodies. Another possibility when using the uncoupled implemen-
tation is to have a prescribed motion on one boundary while having sixDoFRigidBodyMotion on
another patch.
This way of prescribing the boundaries has the limitation of only having one type of motion per
boundary. For instance prescribing a motion and sixDoF simultaneously to one body is not possible
without modification to the source code. This type of implementation could be used to simulate the
transient behaviour of a boat by prescribing a motion to the rudder while having the entire boats
movement determined by the sixDoFRigidBodyMotion solver.
One could take this a step further by incorporating a more advanced regulation such as a proportional-
integral-derivative controller (PID controller). An example of where such a implementation can be
useful is regulating an airfoil angle towards a desired performance in one simulation instead of
running several simulations where the airfoil angle is changed in increments.
20
Chapter 4
References
21
Study questions
• Where do we specify the physical properties of a rigid body when using the coupled sixDoF-
RigidBodyMotion solver?
• What does the innerDistance and outerDistance options do in the constants/dynamicMeshDict
file?
• What is important to think of when setting the innerDistance for a coupled rigid body?
• What utility do we use in order to convert a 3D mesh into a 2D mesh?
• How much smaller or larger will a cell get if the refinement level is increased by 1.
22