In this detailed tutorial, we will explain how to setup dynamic mesh with mesh deformation in OpenFOAM. For this tutorial, we will focus on SixDoFRigidBody motion. If you want to know the general overview of dynamic meshing in OpenFOAM, you can check our previous post here. For prescribed/forced motion simulations, you can check here.
Test case
We will be using the square body for our tutorial due to its very simple shape and easy mesh generation using blockMesh. We will be running the simulation of flow induced oscillations of a square cylinder in a flow field.
The case files can be downloaded here. OpenFOAM-v2012 and Ubuntu 20.04LTS are used to run the tutorial but newer ESI versions will work, too.
Flow solver and numerical schemes
For the flow solver, we chose pimpleFoam for its simplicity. pimpleFoam is a single phase transient incompressible solver with turbulence modeling using RANS. pimpleFoam is simple enough to setup and run the simulation easily while extremely useful to learn because most of your industrial problems are likely to be those involving incompressible flows. Second order finite volume discretizations are used for accurate simulation practice although this tutorial is not designed for verification and validation purposes.
Requirements for a dynamic mesh simulation in OpenFOAM
In order to use dynamic mesh, we need the following:
- A dynamicMeshDict file
- A motion boundary conditions file (pointDisplacement)
- A movingWallVelocity boundary condition for moving body
- An additional matrix solver for solving the mesh motion equation
The dynamicMeshDict file
As I mentioned above, if you want to run simulations involving dynamic meshes, one essential setting file is the dynamicMeshDict file. This file is located inside the $ROOT/constant/ directory. Here, $ROOT is your OpenFOAM case directory. This dynamicMeshDict file contains the definition of the type of dynamic mesh as well as the details of the mesh motion. For sixDofRigidBodyMotion solver, it also contains the dynamic properties of the body.
The following figure is the dynamicMeshDict file for our square cylinder sixDoFRigidBodyMotion simulation. Line 17 shows that we will be using dynamicMotionSolverFvMesh which is the typical dynamic mesh library most commonly used for several types of mesh motion. We can choose other mesh types as well. For example, we can use dynamicOversetFvMesh for overset meshes.
Dynamic properties for sixDofRigidBodyMotion
For the motionSolver, we choose the sixDoFRigidBodyMotion solver. In Line 29, we can set the patch name “square” for which sixDoFRigidBodyMotion is applied. “innerDistance” and “outerDistance” define the mesh morphing/deformation region. Mesh nodes within innerDistance will move as a rigid body while those between innerDistance and outerDistance will deform. Unlike the previous forced oscillation simulations, sixDoFRigidBodyMotion uses a separate mesh motion algorithm with its own diffusivity calculations. As long as we set innerDistance and outerDistance, we do not need to care about diffusivity and mesh motion algorithms. SixDoFRigidBodyMotion solver takes care of these for us.
After that, we need to define dynamic properties. If you are not sure about mass, centreOfMass, orientation, etc. of your body, you can use surfaceInertia utility on your STL file. For the details, you can check here. Then, you can set the kinematics for your body. For instance, you can set angularMomentum and velocity which are initial conditions for the kinematics of the body.
After that, we have acceleration relaxation and damping coefficients. Their main function is to provide stability by avoiding sudden changes in acceleration. Their ranges are between 0.0 and 1.0. But be careful! Too low values (near 0.0) may lead to unphysical results while 1.0 may diverge your simulation. A good range is 0.9~1.0 for both.
Then we can set the time marching scheme for solving the sixDoFRigidBody ODEs. There are 3 choices: CrankNicolson, Newmark-beta and sympletic methods. The first twos are second order implicit solvers while the last one is a second order explicit solver. I used CrankNicolson here but with its default coefficients, it is basically a Newmark solver.
The motion boundary condition file
The pointDisplacement file is located inside the $ROOT/0/ directory. It contains the boundary conditions for the motion of your patches. Basically, you need to assign necessary type of motion for your patch here. For prescribed motions, I defined motion types such as oscillatingDisplacement boundary condition for my patch “square”. For sixDoFRigidBodyMotion, we only need to define “calculated” condition because the sixDoF motion is handled in dynamicMeshDict as we explained above.
For your non-moving parts, you need to keep these fixed by setting as fixedValue and giving a value of uniform (0 0 0). For special patches such as empty or symmetryPlane, you just need to use the patch type as boundary condition.
Constraints
As the final part of the setup, we need to set the constraints and restraints for the motion. Constraints are used to define the motion direction (both linear and angular) and orientation. The available constraints are:
- Axis
- Line
- Plane
- Point
- Orientation
The dictionary format is as shown above. First, you need to assign some name for your constraint. For my example, I used yLine and yAxis. Then you need to define sixDoFRigidBodyMotionConstraint type you need to assign from the above six types. You can find the details of these constraints in OpenFOAM wiki page.
A combination of these can be used to constrain the motion in our desired direction. For example, among the 6 DoF, we want to only set linear motion in y direction, we need to assign a line constraint in y direction (yLine) as shown in Line 59. You may notice that we only give a y-direction vector in the setting and it allows linear motion only in y direction. However, the rotation is not constrained yet. If you run without yAxis entry, the square will rotate in z direction. To avoid this, I attached yAxis constraint which allows rotation only in y direction. Since there is no moment to rotate the body in y direction, the body will not rotate in any direction.
Restraints
Restraints are basically springs and dampers you can define for your dynamics system. There are too many restraint types in OpenFOAM and these vary with OpenFOAM versions. In ESI version, we have
- linearSpring
- linearDamper
- linearSpringDamper
- linearAxialAngularSpring
- sphericalAngularSpring
- sphericalAngularDamper
- tabulatedSphericalAngularSpring
- softWall
However, most of your problems, a linearSpring and a linearAxialAngularSpring should be enough. Also, linear spring includes damping, so you would not need a separate linear damper unless you want to set damping ratios instead of damping coefficients.
The movingWallVelocity boundary condition
All dynamic mesh simulations involve motion of bodies or patches. You need to transfer this motion to the fluid domain as a movingWallVelocity boundary condition. Otherwise, your moving body will have no significant effect on the flow field and you will have physically very wrong results.
This is done by setting movingWallVelocity condition to your moving body inside the $ROOT/0/U file as follows.
Running the simulation
Now we can run the simulation by running the solver. In our problem, we are going to use pimpleFoam which is a single phase incompressible solver. As you can see in the following figure, the 6-DoF rigid body motion is working and we are getting linear and angular velocities as well as displacements.
You can also use other solvers such as interFoam for free-surface problems involving 6DoF motions
Summary
We provided the detailed requirements to setup a dynamic mesh simulation in OpenFOAM using mesh deformation and sixDoFRigidBody motion. This kind of simulation can be used to model several aerodynamics phenomena and various offshore and marine hydrodynamics applications.
Case files
You can find case files here.
Related links
Introduction to Dynamic Mesh in OpenFOAM
Dynamic mesh with OpenFOAM, Part 2: Prescribed motion