Professional Documents
Culture Documents
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.
Contents
1 Introduction 2
2 Meshing 2
2.1 Meshing Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2.1.1 Stator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.1.2 Rotor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.1.3 Combining both Meshes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
6 Conclusions 27
6.1 Meshing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
6.2 Physical Modelling of rotation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
7 Appendix 28
i
CONTENTS CONTENTS
Learning outcomes
• Using cfMesh to generate Mesh for this case and learning how to work with cfMesh.
• Physical modelling of rotation using MRF.
• Physical modelling of rotation using mesh motion.
1
2 MESHING
1 Introduction
The purpose of the project is to look at the suitability, pros and cons for alternative techniques
available in OpenFOAM for modelling of rotating impeller and static baffles in a reactor. One more
purpose is also to evaluate the use of cfMesh to generate mesh for this application.
In Chemical engineering, chemical reactors are the vessels designed to contain chemical reactions.
Vessels which are widely used in the process industries are generally called batch reactors. A typical
batch reactor consists of a tank with an agitator and a heating or cooling system. They may also
contain static baffles depending on the application. These vessels may vary in size from less than 1
litre to 15000 litres. Batch reactors are used for a variety of operations such as solids dissolution,
product mixing, chemical reactions, batch distillation and crystallization.
In this tutorial a lab scale reactor is used. This vessels are in sizes of about 500 to 1000 millilitres.
They are used in production systems which are used for preparing small volumes of medical sub-
stances. The difficulty in modelling this kind of reactors is modelling of rotation. In OpenFOAM
modelling of rotation is handled using three techniques Single reference frame (SRF), Multiple refer-
ence frame and Sliding grid technique. In this tutorial MRF and Sliding grid technique are used. In
MRF method a separate rotating region is defined and modelled using rotating frame of reference.
Most OpenFOAM steady state solvers are capable of handling MRF using fvOptions. In Sliding grid
technique, reactor is divided into two regions stationary and a rotating region. The rotating region
is rotated using sliding grid technique and therefore transient problems with strong rotor-stator
interaction can be solved.
Figure 1 shows the geometry of batch reactor. It consists of a reactor vessel of radius 50 mm and
height 90mm. The reactor Vessel contains a stationary baffle rod with a baffle wing attached to it.
Impeller is attached to a rotating shaft . The small rotating shaft is attached to a long shaft which
is stationary. The region around the impeller is the MRF region.
2 Meshing
cfMesh was used to generate mesh. cfMesh is an open source library for automatic mesh generation
built on top of OpenFOAM. It is compatible with all recent versions of OpenFOAM and FOAM-
extend. cfMesh is currently available for following work flows. The mesher operates on triangulated
geometry inputs in one of the formats fms, ftr and stl. It builds meshes using the choice of basic
2
2 MESHING
a) b)
meshing strategies:
• CartesianMesh - Used to generate 3D hexahedral cells with polyhedral cells in the transition
regions between the cells of different sizes. The meshing process can be started by typing
cartesianMesh in the console.
• Cartesian2DMesh - Used to generate 2D meshes. By default cfMesh will generate a bound-
ary layer which can be further refined. Meshing process can be started by typing cartesian2DMesh
in the console.
• Tetrahedral - Used to generate tetrahedral cells. By default it does not generate any bound-
ary layer but such can be generated later using refinement settings. The meshing process can
be started by typing tetMesh in the console.
• Polyhedral - Used to generate meshes with arbitrary polyhedral cells. It can be used for
poor geometries. The meshing process can be started by typing pMesh in console.
All sharp features in the geometry must be defined prior to the meshing process. The edges at the
border between the two patches are treated as sharp features in the meshing process. This sharp
edges are captured only if there is an edge of a triangulation surface at that location.
An STL file describes a raw unstructured triangulated surface by the unit normal vertices of the
triangles using a threedimensional Cartesian coordinate system. They describe only the surface
geometry without any representation of color or texture. The STL file formats specifies both ASCII
and binary representations. Below is an example of STL file in ASCII representation.
solid xx
facet normal 1.954537e-01 8.563388e-01 4.779976e-01
outer loop
vertex -3.547176e+01 -4.186972e+00 1.980803e+01
vertex -3.639162e+01 -3.977019e+00 1.980803e+01
vertex -3.603364e+01 -4.528674e+00 2.064995e+01
endloop
endfacet
endsolid xx
In the above file xx is a patch name. A patch always starts with solid Name and ends with
endsolid Name. Giving name for the patch is not compulsory. Two STL files can be joined
together by just copying the contents of one file to other. In the below example, an STL file which
contains patch YY is added to the above STL file.
solid xx
facet normal 1.954537e-01 8.563388e-01 4.779976e-01
3
2.1 Meshing Procedure 2 MESHING
outer loop
vertex -3.547176e+01 -4.186972e+00 1.980803e+01
vertex -3.639162e+01 -3.977019e+00 1.980803e+01
vertex -3.603364e+01 -4.528674e+00 2.064995e+01
endloop
endfacet
endsolid xx
solid YY
facet normal 4.201081e-01 8.723634e-01 2.499825e-01
outer loop
vertex -3.701545e+01 -4.185124e+00 2.064995e+01
vertex -3.761253e+01 -4.157825e+00 2.155811e+01
vertex -3.662183e+01 -4.634923e+00 2.155811e+01
endloop
endfacet
endsolid YY
We can also split an STL file into different STL files by just copying all triangles of a single patch
to a new text file. Two patches can also be combined into a single patch by just copying triangles
of a patch into other patch.
The CartesianMesh strategy is used to generate the mesh in this particular case. cfMesh generates
the mesh based on the settings given in the meshDict file which is present in the system directory.
cfMesh requires only two mandatory settings to start the meshing process:
• surfaceFile - this files points to the file that contains triangulated geometry and the path of
the file is same as the path of the case directory.
• maxCellSize - this represents the default cell size used for the meshing. It is the maximum cell
size generated in the domain.
cfMesh has number of refinement settings that can be used to generate a good mesh. All the refine-
ment settings are not explained in the report. They are explained in detail in the cfMesh user guide.
cfMesh generates the mesh in a single domain. If there are multiple disconnected domains, cfMesh
keeps the region which contains the most number of cells and removes the cells of the other region(s).
In the case of a rotorstator simulations it is useful, and in some cases necessary, to generate the mesh
in more than one region. Therefore the mesh in this case is generated as a single mesh region for
rotor and a single mesh region for the stator. These regions are later merged to form the entire mesh.
Given geometry is divided into two regions stator and rotor. Below Table shows how different parts
in the geometry are divided into two regions. This can also be seen in Figure 2.
Stator Rotor
baffle rod, baffle wing, stationary Impeller, rotating shaft, MRF
shaft, reactor vessel and MRF interface
interface
cfMesh is not installed in OpenFOAM-2.4 X and FOAM-extend 3.1. It can be easily installed by
following the instructions given in Appendix.
4
2.1 Meshing Procedure 2 MESHING
2.1.1 Stator
The following section explains the meshing procedure for stator. This tutorial is based on asmoOctree
tutorial in cfMesh tutorials. you can copy asmoOctree tutorial to your run directory by using the
command
run
cp-r \$FOAM_TUTORIALS/mesh/cartesianMesh/asmoOctree/ stator
It should be noted that cfMesh tutorials are not copied to OpenFOAM tutorials directory while
installing it. This should be done manually.
cd stator
rm -r geom.stl
rm -r Allclean
rm -r Allrun
copy stator_updated.stl file from the given files to this directory
vi system/meshDict
Below is the meshDict file of stator. you need to paste this in system/meshDict file. Comments in
the meshDict file will give an idea on different things used in the meshDict file.
Below table gives which part corresponds to which patch. As you can see from table reactor vessel
is divided into two patches WALL SURFACE and WALL REACTOR and MRF interface is divided
into three patches TOP,BOTTOM, CYLINDER.
Part Patch
reactor vessel WALL SURFACE, WALL REACTOR
baffle wing WALL BAFFLE WING,
baffle rod WALL BAFFLE ROD
stationary shaft WALL STAT SHAFT
MRF interface TOP, CYLINDER, BOTTOM
renameBoundary is used in the meshDict file to change the patch names and types while generating
meshes. Here TOP, BOTTOM and CYLINDER patches are renamed to tops, bottoms and cylinders.
All other patches are combined into a single patch called stator. localRefinement is used to refine
cells at that particular patch. In the meshDict file maxcellSize is specified in meters because cfMesh
assumes that the geometry is in meters. The mesh generated will be scaled to required dimensions
later.
surfaceFile "stator_updated.stl";
maxCellSize 2; // [m]
localRefinement //allows for local refinement regions at the boundary
{
WALL_SURFACE // patch
{
cellSize 1.2; // requested cell size
}
WALL_STAT_SHAFT
{
cellSize 1.2;
}
WALL_REACTOR
{
cellSize 2;
}
5
2.1 Meshing Procedure 2 MESHING
WALL_BAFFLE_WING
{
cellSize 1;
refinementThickness 1; // thickness of refinement zone
}
WALL_BAFFLE_ROD
{
cellSize 1;
}
TOP
{
cellSize 2;
}
CYLINDER
{
cellSize 2;
//refinementThickness 1;
}
BOTTOM
{
cellSize 2;
//refinementThickness 1;
}
}
TOP
{
newName tops; //new Name
type wall; //new Patch Type
}
BOTTOM
{
newName bottoms;
type wall;
}
6
2.1 Meshing Procedure 2 MESHING
CYLINDER
{
newName cylinders;
type wall;
}
}
}
The meshing process can be initiated by typing cartesianMesh in the console.
cartesianMesh
improveMeshQuality
checkMesh
improveMeshQuality is used to improve the mesh quality and checkMesh is used to check the quality
of mesh.
2.1.2 Rotor
The meshing procedure for rotor is similar to stator. asmoOctree tutorial should be copied to run
directory.
run
cp-r $FOAM_TUTORIALS/mesh/cartesianMesh/asmoOctree/ stator
cd stator
rm -r geom.stl
rm -r Allclean
rm -r Allrun
copy rotor_updated.stl file from the given files to this directory
vi system/meshDict
Below table shows which part corresponds to which patch. renameBoundary is used in meshDict
file to rename the patches. New patch Names can also be seen in below table
surfaceFile "rotor_updated.stl";
maxCellSize 1;
localRefinement
{
WALL_IMPELLER
{
cellSize 0.8;
}
WALL_ROT_SHAFT
{
cellSize 0.5;
}
TOP
7
2.1 Meshing Procedure 2 MESHING
{
cellSize 0.8;
}
BOTTOM
{
cellSize 0.8;
}
CYLINDER
{
cellSize 0.8;
}
}
boundaryLayers
{
patchBoundaryLayers
{
WALL_IMPELLER
{
nLayers 3;
thicknessRatio 1.2;
}
}
}
renameBoundary
{
newPatchNames
{
WALL_IMPELLER
{
newName impeller;
type wall;
}
WALL_ROT_SHAFT
{
newName rshaft;
type wall;
}
CYLINDER
{
newName CYLINDERR;
type wall;
}
BOTTOM
{
newName BOTTOMR;
type wall;
}
TOP
{
newName TOPR;
type wall;
8
2.1 Meshing Procedure 2 MESHING
}
}
}
a) b)
Figure 3: Mesh generated using cfMesh in two separate regions a) stator and b) rotor
run
cp -r rotor Project
cp -r stator Project
cd Project
mergeMeshes stator rotor
rm -r rotor
cd stator
rm -r constant/polyMesh
mv 1/polyMesh constant/
rm -r 1
In the above commands stator is the master case and rotor is the case that has the mesh to be
merged into the stator mesh. The merged mesh ends up in the master case, in a time directory
corresponding to startTime+deltaT. There is also a flag -overwrite that will force mergeMeshes to
directly rewrite to the constant/polyMesh directory in master case.
run
cp -r rotor Project
cp -r stator Project
cd Project
mergeMeshes -overwrite stator rotor
9
3 SETTING UP CASE USING MRF
The original geometry was generated in millimeters, but cfMesh and OpenFOAM assume that the
geometry is in meters. Therefore the mesh is transformed to meters using
transformPoints -scale '(0.001 0.001 0.001)'
Now we have a domain with two separate regions which are not coupled to each other. This can be
seen using the checkMesh command.
checkMesh
Figure 4 is a clip with normal in the Z-direction, at the center of the rotor. Both stator and rotor
regions can be seen in the figure.
∂(ur ) p
+ ∇ · (ur ur ) + 2Ω × ur + (Ω × (Ω + r)) = −∇( ) + ∇ · (υ∇ur ), (1)
∂t ρ
where p, ρ and υ denote pressure, density and kinematic viscosity respectively. The relative velocity
ur is defined by
ur = u − Ω ∗ r, (2)
and Ω represents the angular velocity.
∂(ρu)
+ ∇ · (ρuu) = −∇p + ∇ · (µ∇u) (3)
∂t
where µ represents dynamic viscosity.
In this case mesh is generated in two regions and merged together using mergeMeshes utility. The
connection between two regions is handled using a mesh interface. OpenFOAM supports different
mesh interfaces like General Grid interface (GGI), mixing plane and Arbitrary Mesh Interface (AMI).
GGI and mixing plane are used only in FOAM-extend. In this case AMI (Arbitrary Mesh Interface) is
used. AMI operates by projecting one of the patch faces onto the other. From these weighting factors
will be calculated, to determine how an AMI boundary cell should couple to the AMI boundary cells
on the other side of the interface. This weighting factors should be close to 1 always. AMI interface
can be used even if the patches are not perfectly conformal, but it is better to keep both patches as
conformal as possible.
10
3.1 Pre-processing 3 SETTING UP CASE USING MRF
3.1 Pre-processing
The MRF technique is implemented in different ways in OpenFOAM and FOAM-extend. Rotation
is defined in system/fvOptions in OpenFOAM and in constant/MRFZones in Foam-extend. Below
table shows how the MRF technique is implemented in OpenFOAM and FOAM-extend
OpenFOAM FOAM-extend
simpleFoam + fvOptions MRFsimpleFoam + MRFZones
This tutorial is based on the mixerVessel2D tutorial in OpenFOAM-2.4.x. This tutorial can be
copied to your run folder by using the command
cp -r $FOAM_TUTORIALS/incompressible/simpleFoam/mixerVessel2D $FOAM_RUN
run
cp -r Project ProjectMRF
cd ProjectMRF
cd stator
vi constant/polyMesh/boundary
Interface between patches of rotor and stator region should be coupled using AMI interface, this can
be done by editing boundary file in constant/polyMesh/boundary
9
(
tops
{
type cyclicAMI;
inGroups 1(cyclicAMI);
nFaces 1224;
startFace 1174428;
matchTolerance 0.0001;
transform noOrdering;
neighbourPatch TOPR; //neighbor patch on rotor side
}
bottoms
{
type cyclicAMI;
inGroups 1(cyclicAMI);
nFaces 968;
startFace 1175652;
matchTolerance 0.0001;
transform noOrdering;
neighbourPatch BOTTOMR; //neighbor patch on rotor side
}
cylinders
{
type cyclicAMI;
inGroups 1(cyclicAMI);
nFaces 1376;
startFace 1176620;
matchTolerance 0.0001;
transform noOrdering;
neighbourPatch CYLINDERR; //neighbor patch on rotor side
}
stator
11
3.1 Pre-processing 3 SETTING UP CASE USING MRF
{
type wall;
inGroups 1(wall);
nFaces 27664;
startFace 1177996;
}
impeller
{
type wall;
inGroups 1(wall);
nFaces 25320;
startFace 1205660;
}
rshaft
{
type wall;
inGroups 1(wall);
nFaces 704;
startFace 1230980;
}
CYLINDERR
{
type cyclicAMI;
inGroups 1(cyclicAMI);
nFaces 18856;
startFace 1231684;
matchTolerance 0.0001;
transform noOrdering;
neighbourPatch cylinders; //neighbor patch on stator side
}
BOTTOMR
{
type cyclicAMI;
inGroups 1(cyclicAMI);
nFaces 14448;
startFace 1250540;
matchTolerance 0.0001;
transform noOrdering;
neighbourPatch bottoms; //neighbor patch on stator side
}
TOPR
{
type cyclicAMI;
inGroups 1(cyclicAMI);
nFaces 14432;
startFace 1264988;
matchTolerance 0.0001;
transform noOrdering;
neighbourPatch tops; //neighbor patch on stator side
}
)
In the above boundary file tops, bottoms and cylinders are the AMI interfaces on the stator side
and TOPR, BOTTOMR, and CYLINDERR are the AMI interfaces on the rotor side. Each patch
12
3.1 Pre-processing 3 SETTING UP CASE USING MRF
should be given a corresponding neighbour patch. Corresponding changes are also to be done in the
0 directory.
dimensions [0 1 -1 0 0 0 0];
boundaryField
{
rshaft
{
type fixedValue;
value uniform (0 0 0);
}
stator
{
type fixedValue;
value uniform (0 0 0);
}
impeller
{
type fixedValue;
value uniform (0 0 0);
}
TOPR
{
type cyclicAMI;
value $internalField;
}
BOTTOMR
{
type cyclicAMI;
value $internalField;
}
CYLINDERR
{
type cyclicAMI;
value $internalField;
}
tops
{
type cyclicAMI;
value $internalField;
}
bottoms
{
type cyclicAMI;
13
3.1 Pre-processing 3 SETTING UP CASE USING MRF
value $internalField;
}
cylinders
{
type cyclicAMI;
value $internalField;
}
}
All the files in 0 directory are provided. They can be copied directly from there. This can also be
done by copying the O/files from mixerVessel2D tutorial and doing the corresponding changes.
Next step is to create a cellZone for defining the rotation of the impeller. cfMesh does not automat-
ically create cell sets and cell zones while generating meshes. This can be done by using the setSet
and topoSet utilities in OpenFOAM and Foam-extend. There are a number of options available in
both setSet and topoSet to do mesh manipulations. In this case both setSet and topoSet are used
to get an idea how both of them work. Since we already have a cellSet of the rotor region which is
written when checkMesh is done, we can use it directly to create the rotor cellZone using
setSet
cellZoneSet rotor new setToCellZone region1
quit
In the above command rotor is the name of the cellZone and region1 is the cell set which contains
all the cells of the rotor region.
The next step is to create a faceSet containing all the faces of the AMI interfaces.This is done using
the topoSet utility and a topoSetDict file. This file is located in system/topoSetDict, and should in
this contain
actions
(
{
name AMI; // Get both sides of AMI
type faceSet;
action new; // Get all faces in cellSet
source patchToFace;
sourceInfo
{
name bottoms;
}
}
{
name AMI;
type faceSet;
action add; //Add faces to faceset AMI
source patchToFace;
sourceInfo
{
name tops;
}
}
{
14
3.1 Pre-processing 3 SETTING UP CASE USING MRF
name AMI;
type faceSet;
action add;
source patchToFace;
sourceInfo
{
name cylinders;
}
}
{
name AMI;
type faceSet;
action add;
source patchToFace;
sourceInfo
{
name CYLINDERR;
}
}
{
name AMI;
type faceSet;
action add;
source patchToFace;
sourceInfo
{
name BOTTOMR;
}
}
{
name AMI;
type faceSet;
action add;
source patchToFace;
sourceInfo
{
name TOPR;
}
}
);
The above topoSetDict file is provided along with the case files. In the above topoSetDict file ini-
tially faceSet with name AMI is created which contains all the faces of patch bottoms. This is done
by using the action command new. After that all the faces from other patches are added to faceSet
AMI using the action command add.
topoSet
The settings for the rotation component in OpenFOAM-2.4.x is defined using the system/fvOptions
file. Patches which are adjacent to rotating patches and which are non-rotating should be included
in nonRotatingpatches () . As you can see in the below fvOptions file tops, bottoms, and cylinders
patches are non-rotating stator AMI interface patches. Angular velocity of 40 rad/sec along Z-axis
15
3.2 Results 3 SETTING UP CASE USING MRF
MRF1
{
type MRFSource;
active true;
selectionMode cellZone;
cellZone rotor;
MRFSourceCoeffs
{
nonRotatingPatches (tops bottoms cylinders);
active true;
origin (0 0 0);
axis (0 0 1);
omega 40; // in rad/sec
}
}
fvSchemes, fvSolution and controlDict can be copied from the given case files to system directory.
This can also be done by copying this files from mixerVessel2D tutorial, but necessary changes should
be done to fvSolution file to implement turbulence model. turbulence properties, RAS properties
and transport properties files should be added to constant directory to implement turbulence model.
This files can be copied from given case files.
Now the set-up for MRF is done and the simulation is started by typing simpleFoam in console.
simpleFoam
3.2 Results
U Magnitude
1.21
1
0.75
0.5
0.25
16
4 SETTING UP CASE USING SLIDING GRID
Figure 5 is a velocity contour at Z=0.0032 m plane. From the figure we can see high velocities near
the tip of the blade which is expected. Velocity magnitude at the tip of the blade is in agreement
with analytical solution which is 1.2 m/s.
V = r ∗ Ω = 0.03 ∗ 40 = 1.2m/s
Figure 6 shows the velocity vectors entering from the top of the impeller and a recirculation region
at the side of the impeller. We can also observe high velocity at the tip of the impeller.
4.1 Pre-processing
The setup used for AMI is very much similar to that of MRF. This is because we are using the same
mesh interface (AMI) between stator and rotor. We can use the same meshes as MRF. The only
change is how the mesh motion is defined. Here mesh motion is defined using a dynamicMeshDict
file which is present in constant directory. Here mesh motion is obtained by using solidBodyMo-
tionFvMesh class which is a sub class of dynamicFvMesh. To start with the case copy the MRF case
run
cp -r ProjectMRF ProjectAMI
cd constant
Below is the dynamicMeshdict file. This file is provided along with the case files. In the dynam-
icMeshDict file cellZone specifies which region to rotate. solidBodyMotionFunction specifies the
17
4.1 Pre-processing 4 SETTING UP CASE USING SLIDING GRID
type of motion. Here angular velocity of 5 rad/sec is taken. Angular velocity should be increased
gradually over time to attain the an angular velocity of 40 rad/sec. The reason behind this is mean
courant number. In order to keep the mean courant number low we need to decrease either time
step or angular velocity for a given mesh.
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "constant";
object dynamicMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dynamicFvMesh solidBodyMotionFvMesh;
motionSolverLibs ( "libfvMotionSolvers.so" );
solidBodyMotionFvMeshCoeffs
{
cellZone rotor;
solidBodyMotionFunction rotatingMotion;
rotatingMotionCoeffs
{
origin (0 0 0);
axis (0 0 1);
omega 5; // rad/s
}
}
// ************************************************************************* //
We need to remove constat/fvOptions file from the system directory since we are not defining rotation
using this file. This is not compulsory because we are not using the same solver and pimpleDyM-
Foam won’t use MRF settings from that file.
cd ..
rm -r system/fvOptions
Time step to be used in the simulation can be given in controlDict file. we can use adjustTimeStep
to decrease the time step during the simulation if the mean courant number is increasing more than
1. In this case time step of 1e-4 is used.
copy the below controlDict file to system/controlDict file
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object controlDict;
18
4.2 Results 5 SCALAR TRANSPORT EQUATION
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
application pimpleDyMFoam;
startFrom latestTime;
startTime 0;
stopAt endTime;
endTime 5;
deltaT 1e-4;
writeControl adjustableRunTime;
writeInterval 0.01;
purgeWrite 10;
writeFormat ascii;
writePrecision 6;
writeCompression off;
timeFormat general;
timePrecision 6;
runTimeModifiable true;
//adjustTimeStep yes;
maxCo 2;
Now the set-up for sliding grid is done and the simulation is started by typing pimpleDyMFoam in
console.
pimpleDyMFoam
4.2 Results
Figure 7 shows the velocity contours at various time steps. Effect of impeller position on the flow
field can be clearly seen from the figure. Here you can see high velocities near the tip of the impeller.
Compared to MRF case we don’t have high velocities in between impeller blades.
19
5.1 Implementation in simpleFoam 5 SCALAR TRANSPORT EQUATION
U Magnitude U Magnitude
1.31 1.31
1.2 1.2
0.8 0.8
0.4 0.4
0 0
a) at t=4.925s b) at t=4.935s
U Magnitude U Magnitude
1.31 1.31
1.2 1.2
0.8 0.8
0.4 0.4
0 0
foam
cp -r --parents applications/solvers/incompressible/simpleFoam $WM_PROJECT_USER_DIR
cd $WM_PROJECT_USER_DIR/applications/solvers/incompressible
mv simpleFoam mysimpleFoam
cd mysimpleFoam
wclean
mv simpleFoam.C mysimpleFoam.C
rm -r SRFSimpleFoam porousSimpleFoam
Allwmake
In the above steps the simpleFoam directory is copied to the user directory and renamed as mysim-
pleFoam. simpleFoam/simpleFoam.C is renamed as mysimpleFoam.C. Now we need to add the
transport equation in mysimpleFoam.C file before runTime.write().
20
5.1 Implementation in simpleFoam 5 SCALAR TRANSPORT EQUATION
where Sc and Sct are Schmidt’s number and turbulent Schmidt’s number.
Next we should add volumeScalarField C in the createFields.H file. We can copy the same as p and
change p to C, since both are scalar fields. we should also define Sc and Sct, this can be done by
defining it in createFields.H file by adding below code
IOdictionary transportProperties
(
IOobject
(
"transportProperties",
runTime.constant(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
)
);
dimensionedScalar Sc
(
transportProperties.lookup("Sc")
)
dimensionedScalar Sct
(
transportProperties.lookup("Sct")
)
This code will look for the value of Sc and Sct in a transportPropoerties file in the constant directory.
We should also change the name of file in Make/files to compile the modified solver, which can be
done by using the command
string="mysimpleFoam.C\nEXE = \$(FOAM_USER_APPBIN)/mysimpleFoam"
printf "%b\n" "$string" > Make/files
wmake
21
5.2 Running MRF case with modified solver 5 SCALAR TRANSPORT EQUATION
run
cp -r ProjectMRF ProjectMRFT
cd ProjectMRFT
cd stator
internalField uniform 0;
boundaryField
{
rshaft
{
type zeroGradient;
}
stator
{
type zeroGradient;
}
impeller
{
type zeroGradient;
}
TOPR
{
type cyclicAMI;
value $internalField;
}
BOTTOMR
22
5.2 Running MRF case with modified solver 5 SCALAR TRANSPORT EQUATION
{
type cyclicAMI;
value $internalField;
}
CYLINDERR
{
type cyclicAMI;
value $internalField;
}
tops
{
type cyclicAMI;
value $internalField;
}
bottoms
{
type cyclicAMI;
value $internalField;
}
cylinders
{
type cyclicAMI;
value $internalField;
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
C
{
solver smoothSolver;
smoother GaussSeidel;
nSweeps 2;
tolerance 1e-08;
relTol 0.1;
}
We need to initialize C and this can be done by using the setFields utility. We can copy the
setFieldsDict file from damBreak tutorial using the following command
cp $FOAM_TUTORIALS/multiphase/interFoam/laminar/damBreak/system/setFieldsDict system
23
5.2 Running MRF case with modified solver 5 SCALAR TRANSPORT EQUATION
The following changes are made to the setFieldsDict file. I used a cylinderToCell option here to pick
up a region to set the field values.
defaultFieldValues
(
volScalarFieldValue C 0
);
regions
(
cylinderToCell
{
p1 (0 0 0.036); // centre of first circle
p2 (0 0 0.043); // centre of second circe
radius 0.035; // radius of cylinder
fieldValues
(
volScalarFieldValue C 1
);
}
);
setFields
I have introduced probes at different point locations in the reactor vessel to look at the concentration
at those locations over iterations. This is done by using probes utility in OpenFOAM. This is
implemented by adding the following code to the controlDict file.
functions
{
concentraionProbes
{
type probes;
functionObjectLibs ("libsampling.so");
outputControl timeStep;
outputInterval 1;
probeLocations
(
( 0.010 0.010 0.043 ) // Probe(0) probe locations coordinates
( 0.010 -0.010 0.043 ) // Probe (1)
( 0.010 0.010 -0.010 ) // Probe (2)
);
fields // field to plot
(
C
);
}
Now the set-up for case is done and simulation is started by typing mysimpleFoam in console.
mysimpleFoam
24
5.3 Implementation in pimpleDyMFoam 5 SCALAR TRANSPORT EQUATION
Results
Project AMI case is solved initially till t=4.995 sec to attain convergence. Then the scalar transport
equation is introduced and solved for more 0.65 sec. Concentration is plotted at three probe locations
and plotted over time. Location of the probes are given below
Figure 8 shows the plot of concentration over time. It can be seen from figure that at Probe 2 the
concentration is zero till t=5.1 sec. This is as expected because Probe 2 is at the top of the reactor.
Concentration at Probe 0 and 1 is decreasing and attaining a uniform value as time passes. It can
also be seen that concentration at Probe 2 is decreasing from t=5.28 sec and reaching a uniform
value. In order to achieve a uniform concentration thought the reactor the simulation should be
continued for more time. This is not done because of time constraints.
Figure 9 shows the concentration contours in a plane normal to Y. At t=4.995s the concentration is 1
in the middle of the reactor. From the figure it can also be seen how the water is moving downwards
in the reactor. This is as expected because the impeller is located close to the bottom of the reactor
vessel. Effect of baffle rod and wing can also be seen from the figures. The concentration at probe
2 is almost zero till 5.345s and increases over time to reach a uniform concentration.
25
5.3 Implementation in pimpleDyMFoam 5 SCALAR TRANSPORT EQUATION
C C
1 0.936
0.8
0.75
0.6
0.5
0.4
0.25
0.2
0 -0.00557 0
a) at t=4.995s b) at t=5.045s
C C
0.687 0.295
0.6
0.2
0.4
0.2 0.1
0 0
C C
0.245 0.155
0.2
0.12
0.08
0.1
0.04
0 0
e) at t=5.245s f) at t=5.345s
C C
0.101 0.1 0.0827 0.08
0.075 0.06
0.05 0.04
0.025 0.02
0 0
g) at t=5.445s h) at t=5.545s
C
0.0749
0.06
0.04
0.02
i) at t=5.645s
26
6 CONCLUSIONS
6 Conclusions
6.1 Meshing
cfMesh is a robust and easy to use meshing tool. It can generate hexa, tetra and polyhedral meshes.
It can handle bad geometries very well. One of the main advantage is its ability to run in parallel
which saves lot of time when generating large meshes. The available refinement settings are easy to
use. It is very good with handling sharp edges if the given input geometry is good. It is very easy
to generate an initial mesh, however it takes some time to generate an ideal mesh.
The main disadvantage with cfMesh is, it can’t generate multi region meshes if there are multiple
disconnected regions. Even though it is good at handling geometries with poor quality, final mesh
quality still depends largely on the quality of input geometry.
Below figure shows mesh generated in the rotor region. As you can see from below figure (a), when
the input geometry is given as a single patch, edges of the rotor region are not captured properly.
This problem is solved by dividing the geometry into individual patches. In figure (b) rotor region
is divided into 3 different patches top, bottom and cylinder.
Figure 10: Comparison between using a single patch and individual patches
MRF
MRF is a steady state solution with a fixed impeller position. Hence the name Frozen rotor tech-
nique. The main advantage with MRF is, it is not computationally expensive. All steady state
OpenFOAM solvers support MRF and it is easy to implement using fvOptions. One more advan-
tage with MRF is, it is not necessary to generate mesh in two regions. The rotor region can be picked
easily using topoSet and setSet utilities in OpenFOAM. There are number of options available in
both of these utilities to manipulate meshes. It is possible to get an unsteady solution using MRF,
but this is not accurate because the stator and rotor interaction cannot be resolved. This is because
impeller or rotor is fixed at a single position. It can be used when there is weak interaction between
the stator and rotor and when unsteady solution is not required.
27
REFERENCES 7 APPENDIX
method in OpenFOAM needs more tedious work flow. The rotating and stationary regions should be
generated as separate meshes and should be merged later. In OpenFOAM you can use mergeMeshes
utility to merge meshes. This method employs PIMPLE solver to obtain an unsteady solution. This
is computationally very expensive compared to MRF, but the rotor-stator interactions can be fully
resolved. In OpenFOAM computational time can be decreased by running it in parallel. One more
disadvantage with sliding grid is we need to implement a ramp-up function or increase the angular
velocity of the rotor gradually. This is because of the Courant-Friedrichs-Lewy (CFL) condition.
This problem can be solved by properly choosing the time step and cell size during mesh generation.
References
[1] Magnus Winter. Benchmark and validation of Open Source CFD codes, with focus on compressible
and rotating capabilities, for integration on the SimScale platform. ”Chalmers University of
Technology”
[2] Weidong Huang; Kun Li. CFD Simulation of Flows in Stirred Tank Reactors. ”Nuclear Reactor
Thermal Hydraulics and Other Applications”, book edited by Donna Post Guillen, ISBN 978-
953-51-0987-7
[3] Håkan Nilsson. Lecture Slides, Rotating Machinery. ”Chalmers University of Technology”
[4] Userguide cfMesh-V 1.1.1
7 Appendix
Installing cfMesh
Go to http://sourceforge.net/projects/cfmesh/ and download the cfMesh-v1.1.1.tgz file.
• make sure you have the gcc compiler set up properly. We compile using gcc 4.8.2 or newer.
• Make sure you have lnInclude directories generated in OpenFoam source directories for triSur-
face, meshTools, foam/openFOAM, pstream/mpi, OSSPecific/Posix and edgeMEsh libraries.
If you dont have them, generate them like this:
to generate lnInclude:
– go to src/trisurface, wmake libso, wait untill it starts to build (or fails)
– go to src/meshTools, wmake libso, wait untill it starts to build (or fails)
– go to src/foam or src/openFoam, wmake libso, wait untill it starts to build (or fails)
– go to src/pstream/mpi, wmake libso, wait untill it starts to build (or fails)
– go to src/edgeMesh, wmake libso, wait untill it starts to build (or fails)
– go to src/OSspecific/MsWindows or POSIX, wmake libo, wait untill it starts to build (or
fails)
• You can now use ./Allwmake script in cfMesh source folder to compile cfMesh
• This will build cfMesh libraries and binaries in FOAM USER APPBIN and FOAM USER LIBBIN.
28
7 APPENDIX
cd postProcessing/concentrationProbes/4.995
gnuplot
set xlabel "time"; set ylabel "C"; plot "C" using 1:2 title "Probe 0", "C" using 1:3
title "Probe 1", "C" using 1:4 title "Probe 2"
exit
Study questions
• How do you give refinement settings for a edge in cfMesh?
• Does cfMesh support regular expressions?
• How do you create a cellSet using a stl surface?
• How can you plot a graph from multiple files using gnu plot?
29