2.2 Flow Around A Cylinder: The Open Source CFD Toolbox
2.2 Flow Around A Cylinder: The Open Source CFD Toolbox
2.2 Flow Around A Cylinder: The Open Source CFD Toolbox
Tutorial Guide
Contents 2.2 Flow around a cylinder
± 1 Introduction
In this example we shall investigate potential flow around a cylinder using thepotentialFoam solver. This example introduces the
± 2 Incompressible flow following OpenFOAM features:
2.1 Lid-driven cavity flow non-orthogonal meshes;
2.2 Flow around a cylinder generating an analytical solution to a problem in OpenFOAM;
2.3 Magnetohydrodynamic flow of use of a dynamic code to generate the block vertices;
a liquid use of a coded function object to compare results against the analytical solution.
± 3 Compressible flow
± 4 Multiphase flow 2.2.1 Problem specification
± 5 Stress analysis
The problem is defined as follows:
Index Solution domain
The domain is 2 dimensional and consists of a square domain with a cylinder collocated with the centre of the square as
shown in Figure 2.15.
Governing equations
(2.14)
(2.15)
Boundary conditions
Initial conditions
, — required in OpenFOAM input files but not necessary for the solution since the problem is
steady-state.
Solver name
potentialFoam: a potential flow code, i.e. assumes the flow is incompressible, steady, irrotational, inviscid and it ignores
gravity.
Case name
cylinder case located in the $FOAM_TUTORIALS/basic/potentialFoam directory.
potentialFoam is a useful solver to validate OpenFOAM since the assumptions of potential flow are such that an analytical solution
exists for cases whose geometries are relatively simple. In this example of flow around a cylinder an analytical solution exists with
which we can compare our numerical solution. potentialFoam can also be run more like a utility to provide a (reasonably)
conservative initial field for a problem. When running certain cases, this can useful for avoiding instabilities due to the initial
field being unstable. In short, potentialFoam creates a conservative field from a non-conservative initial field supplied by the user.
Remember that all meshes are treated as 3 dimensional in OpenFOAM. If we wish to solve a 2 dimensional problem, we must
describe a 3 dimensional mesh that is only one cell thick in the third direction that is not solved. In Figure 2.16 we show only the
back plane of the geometry, along , in which the vertex numbers are numbered 0-18. The other 19 vertices in the front
plane, , are numbered in the same order as the back plane, as shown in the mesh description file below:
17 convertToMeters 1;
18
19 vertices #codeStream
20 {
21 codeInclude
22 #{
23 #include "pointField.H"
24 #};
25
26 code
27 #{
28 pointField points(19);
29 points[0] = point(0.5, 0, -0.5);
30 points[1] = point(1, 0, -0.5);
31 points[2] = point(2, 0, -0.5);
32 points[3] = point(2, 0.707107, -0.5);
33 points[4] = point(0.707107, 0.707107, -0.5);
34 points[5] = point(0.353553, 0.353553, -0.5);
35 points[6] = point(2, 2, -0.5);
36 points[7] = point(0.707107, 2, -0.5);
37 points[8] = point(0, 2, -0.5);
38 points[9] = point(0, 1, -0.5);
39 points[10] = point(0, 0.5, -0.5);
40 points[11] = point(-0.5, 0, -0.5);
41 points[12] = point(-1, 0, -0.5);
42 points[13] = point(-2, 0, -0.5);
Page 3 of 7
49 // Duplicate z points
50 label sz = points.size();
51 points.setSize(2*sz);
52 for (label i = 0; i < sz; i++)
53 {
54 const point& pt = points[i];
55 points[i+sz] = point(pt.x(), pt.y(), -pt.z());
56 }
57
58 os << points;
59 #};
60 };
61
62
63 blocks
64 (
65 hex (5 4 9 10 24 23 28 29) (10 10 1) simpleGrading (1 1 1)
66 hex (0 1 4 5 19 20 23 24) (10 10 1) simpleGrading (1 1 1)
67 hex (1 2 3 4 20 21 22 23) (20 10 1) simpleGrading (1 1 1)
68 hex (4 3 6 7 23 22 25 26) (20 20 1) simpleGrading (1 1 1)
69 hex (9 4 7 8 28 23 26 27) (10 20 1) simpleGrading (1 1 1)
70 hex (15 16 10 9 34 35 29 28) (10 10 1) simpleGrading (1 1 1)
71 hex (12 11 16 15 31 30 35 34) (10 10 1) simpleGrading (1 1 1)
72 hex (13 12 15 14 32 31 34 33) (20 10 1) simpleGrading (1 1 1)
73 hex (14 15 18 17 33 34 37 36) (20 20 1) simpleGrading (1 1 1)
74 hex (15 9 8 18 34 28 27 37) (10 20 1) simpleGrading (1 1 1)
75 );
76
77 edges
78 (
79 arc 0 5 (0.469846 0.17101 -0.5)
80 arc 5 10 (0.17101 0.469846 -0.5)
81 arc 1 4 (0.939693 0.34202 -0.5)
82 arc 4 9 (0.34202 0.939693 -0.5)
83 arc 19 24 (0.469846 0.17101 0.5)
84 arc 24 29 (0.17101 0.469846 0.5)
85 arc 20 23 (0.939693 0.34202 0.5)
86 arc 23 28 (0.34202 0.939693 0.5)
87 arc 11 16 (-0.469846 0.17101 -0.5)
88 arc 16 10 (-0.17101 0.469846 -0.5)
89 arc 12 15 (-0.939693 0.34202 -0.5)
90 arc 15 9 (-0.34202 0.939693 -0.5)
91 arc 30 35 (-0.469846 0.17101 0.5)
92 arc 35 29 (-0.17101 0.469846 0.5)
93 arc 31 34 (-0.939693 0.34202 0.5)
94 arc 34 28 (-0.34202 0.939693 0.5)
95 );
96
97 boundary
98 (
99 down
100 {
101 type symmetryPlane;
102 faces
103 (
104 (0 1 20 19)
105 (1 2 21 20)
106 (12 11 30 31)
107 (13 12 31 32)
108 );
109 }
110 right
111 {
112 type patch;
113 faces
114 (
115 (2 3 22 21)
116 (3 6 25 22)
Page 4 of 7
117 );
118 }
119 up
120 {
121 type symmetryPlane;
122 faces
123 (
124 (7 8 27 26)
125 (6 7 26 25)
126 (8 18 37 27)
127 (18 17 36 37)
128 );
129 }
130 left
131 {
132 type patch;
133 faces
134 (
135 (14 13 32 33)
136 (17 14 33 36)
137 );
138 }
139 cylinder
140 {
141 type symmetry;
142 faces
143 (
144 (10 5 24 29)
145 (5 0 19 24)
146 (16 10 29 35)
147 (11 16 35 30)
148 );
149 }
150 );
151
152 mergePatchPairs
153 (
154 );
155
156 // ************************************************************************* //
18 application potentialFoam;
19
Page 5 of 7
20 startFrom latestTime;
21
22 startTime 0;
23
24 stopAt nextWrite;
25
26 endTime 1;
27
28 deltaT 1;
29
30 writeControl timeStep;
31
32 writeInterval 1;
33
34 purgeWrite 0;
35
36 writeFormat ascii;
37
38 writePrecision 6;
39
40 writeCompression off;
41
42 timeFormat general;
43
44 timePrecision 6;
45
46 runTimeModifiable true;
47
48 functions
49 {
50 error
51 {
52 // Load the library containing the 'coded' functionObject
53 libs ("libutilityFunctionObjects.so");
54
55 type coded;
56
60 codeEnd
61 #{
62 // Lookup U
63 Info<< "Looking up field U\n" << endl;
64 const volVectorField& U = mesh().lookupObject<volVectorField>("U");
65
77 dimensionedScalar uInfX
78 (
79 "uInfx",
80 dimensionSet(0, 1, -1, 0, 0),
81 ULeft
82 );
83
84 Info << "U at inlet = " << uInfX.value() << " m/s" << endl;
85
86
94 reduce(magCylinder, maxOp<scalar>());
95
96 dimensionedScalar radius
97 (
98 "radius",
99 dimensionSet(0, 1, 0, 0, 0),
100 magCylinder
101 );
102
103 Info << "Cylinder radius = " << radius.value() << " m" << endl;
104
105 volVectorField UA
106 (
107 IOobject
108 (
109 "UA",
110 mesh().time().timeName(),
111 U.mesh(),
112 IOobject::NO_READ,
113 IOobject::AUTO_WRITE
114 ),
115 U
116 );
117
130 UA = uInfX*(dimensionedVector(vector(1,0,0))
131 - pow((radius/magCentres),2)*cs2theta);
132
141 error.write();
142 #};
143 }
144 }
145
146
147 // ************************************************************************* //
potentialFoam executes an iterative loop around the pressure equation which it solves in order that explicit terms relating to non-
orthogonal correction in the Laplacian term may be updated in successive iterations. The number of iterations around the pressure
equation is controlled by the nNonOrthogonalCorrectors keyword in the fvSolution dictionary. In the first instance we can set
nNonOrthogonalCorrectors to 0 so that no loops are performed, i.e. the pressure equation is solved once, and there is no
non-orthogonal correction. The solution is shown in Figure 2.17(a) (at , when the steady-state simulation is complete).
We expect the solution to show smooth streamlines passing across the domain as in the analytical solution in Figure 2.17(c),
yet there is clearly some error in the regions where there is high non-orthogonality in the mesh, e.g. at the join of blocks 0, 1 and 3.
The case can be run a second time with some non-orthogonal correction by setting nNonOrthogonalCorrectors to 3. The
solution shows smooth streamlines with no significant error due to non-orthogonality as shown in Figure 2.17(b).