Chapter 3 - Solutions of the Newtonian viscous-flow equations Incompressible Newtonian viscous flows are governed by the Navier-Stokes equations ∂u 1 + (u · ∇)u = − ∇p + ν∇2 u + f , ∂t ρ ∇ · u = 0,
(1) (2)
where u, p, ρ, ν and f are the velocity vector, pressure, density, kinematic viscosity and body forces respectively. The equations as written are independent of coordinate system, but they look exactly the same using Cartesian coordinates. Of equally great importance, at least in chapter 3, are the Navier-Stokes equations in cylindrical coordinates. The cylindrical coordinates, r, θ, z, are given in terms of the Cartesian coordinates x, y, z as x = r cos θ, y = r sin θ, z = z. The Cartesian position vector is thus x = r cos θi + r sin θj + zk. The unit vectors in cylindrical coordinates are ir = iθ = iz =
dx dr | dx dr | dx dθ | dx dθ | dx dz | dx dz |
= cos θi + sin θj, = − sin θi + cos θj, = k.
The velocity vectors in Cartesian and cylindrical coordinates read respectively u(x, y, z, t) = ux i + uy j + uz k u(r, θ, z, t) = ur ir + uθ iθ + uz iz The gradient ∇ and the divergence of the velocity vector ∇ · u in cylindrical coordinates are given respectively by ∂ 1 ∂ ∂ ∇ = ir + iθ + iz (3) ∂r r ∂θ ∂z 1 ∂rvr 1 ∂vθ ∂vz ∇·u= + + (4) r ∂r r ∂θ ∂z Suggested assignment 1 Show that the following expressions are true ∂ 1 ∂ ∂ + vθ + vz ∂r r ∂θ ∂z 1 ∂ ∂ 1 ∂2 ∂2 ∇2 = r + 2 2+ 2 r ∂r ∂r r ∂θ ∂z
u · ∇ = vr
1
(5) (6)
y x
2h
Figure 1: Laminar plane channel flow. Suggested solution: ∂ 1 ∂ ∂ u · ∇ = (vr ir + vθ iθ + vz iz ) · ir + iθ + iz ∂r r ∂θ ∂z vθ ∂ ∂ ∂ + iθ · iθ + iz · iz vz u · ∇ = ir · ir vr ∂r r ∂θ ∂z 1 ∂ ∂ ∂ + vθ + vz u · ∇ = vr ∂r r ∂θ ∂z The cylindrical unit vectors are orthogonal, so the only nonzero terms are those with ik · ik for k = r, θ, z. To find the Laplacian use the formula for divergence of a vector and insert for Eq. (3) ∇2 = ∇ · ∇ ∂ ∂ ∂∂ 1 ∂ 1r ∂θ 1 ∂r ∂r + + ∂z r ∂r r ∂θ ∂z 2 1 ∂ ∂ ∂2 ∂ 1 ∇2 = r + 2 2+ 2 r ∂r ∂r r ∂θ ∂z
∇2 =
Suggested assignment 2 Start from Eq. (1) and derive the momentum equations for Cylindrical coordinates. The results are given in App B of White.
Laminar parallel shear flows The Navier-Stokes equations are nonlinear because of the convective term, (u · ∇)u, and in general not analytically solvable for most problems in fluid mechanics. The equations can be solved analytically when the convective term is zero and for a few other simplified flows. In chapter 3 of White we start by considering the types of flow where convection is zero. The convection term is never negligible for turbulent flows, where the flow rapidly changes direction in a seemingly chaotic fashion. We will get back to turbulent flows in Chapter 6. For now we assume the flow is laminar. For a laminar flow the convection term will be zero for a parallel shear flow where the geometry is infinite in at least one direction and the velocity vector is parallel to the walls of the geometry. For example, a pipe flow or a plane channel flow as shown in Fig. 1, where there is only one nonzero component of the velocity vector, and the velocity vector is parallel to the surrounding walls. The gradient of this velocity component is normal to the wall
2
and as such u · ∇u = 0 and the Navier-Stokes equations reduce to the linear equations ∂u 1 = − ∇p + ν∇2 u + f , ∂t ρ ∇ · u = 0.
(7) (8)
Since the equations are linear it should not be surprising to find that there are many analytical solutions available for laminar parallel shear flows. If the only nonzero velocity component is in the x-direction, then u = (u, 0, 0) and the Navier-Stokes equations reduce to ∂u 1 ∂p =− + ν∇2 u + fx , ∂t ρ ∂x ∂u = 0. ∂x
(9) (10)
which is also valid for the axial component of cylindrical coordinates (see Ch. 3-2.2). There are two types of parallel shear flows: Couette and Poiseuille. Couette flows are driven by moving walls. Friction, i.e., drag or viscous forces are then responsible for "dragging" the fluid with a direction aligned with the wall. For Poiseuille flows the driving force is a pressure gradient that can be generated using a pump. Couette flows We will first look at a steady plane Couette flow, like in Chapter 3-2.1, where the height of the plane channel is 2h. There is no applied pressure and no gravitational forces in the x-direction, so the Navier-Stokes equations reduce further to ∇2 u = 0, ∂u = 0, ∂x
(11) (12)
with boundary conditions u(−h) = 0 and u(h) = U (see Fig. 3-1 in [7]). The exact solution of these equations is U y u(y) = 1+ . (13) 2 h We will now solve the Couette flow numerically using FEniCS, which is a software used for solving differential equations with the finite element method (http://fenicsproject.org). An excellent tutorial for quickly getting started with FEniCS can be found here [1]. FEniCS solves PDEs by expressing the original problem (the PDEs with boundary and initial conditions) as a variational problem. The core of the recipe for turning a PDE into a variational problem is to multiply the PDE by a function v, integrate the resulting equation over the computational domain (typically called Ω), and perform integration by parts of terms with second-order derivatives. The function v which multiplies the PDE is in the mathematical finite element literature called a test function. The unknown function u to be approximated is referred to as a trial function. The terms test and trial function are used in FEniCS programs too. In this course we will learn how to use the FEniCS software, but the focus will be on the physics of flow. We will use FEniCS to generate numerical solutions that we can easily play with to enhance our understanding of what the mathematical equations represent, but we will not go through the inner details of the finite element method. For those interested in a deeper understanding, the finite element method is taught in, e.g., INF5620 and INF5650. In the current case of a Couette flow we will solve Eq. (11). We assume here for completeness that the equation has an additional constant source f ∇2 u = f. 3
(14)
We now multiply the Poisson equation by the test function v and integrate over the domain Ω = [−h, h], Z Z 2 (∇ u)v dx = f v dx . (15) Ω
Ω
Note that dx is used to represent a volume integral. For Cartesian coordinates dx is equal to dxdydz, whereas for cylindrical coordinates it equals rdrdθdz. Next we apply integration by parts to the integrand on the left hand side with a second-order derivative, Z Z Z ∂u (∇2 u)v dx = − ∇u · ∇v dx + v ds, (16) Ω Ω ∂Ω ∂n ∂u where ∂n is the derivative of u in the outward normal direction at the boundary (here at y = ±h). The test function v is required to vanish on the parts of the boundary where u is known, which in the present problem implies that v = 0 for y = ±h. The second term on the right-hand side of Eq. (16) therefore vanishes for the current problem and we are left with Z Z − ∇u · ∇v dx = f v dx , (17) Ω
Ω
which is also referred to as the weak form of the original boundary value problem (∇2 u = f with boundary conditions). The finite element method discretizes and solves this weak form of the problem on a domain divided into non-overlapping cells. In 2D we typically apply triangles, whereas in 3D tetrahedrons are applied. For 1D problems like the Couette flow we simply divide the computational domain Ω into non-overlapping intervals. The final step required for building a finite element solution is to choose an appropriate function space for our solution. A function space can for example be piecewise linear functions or piecewise polynomials of a higher degree. Different function spaces can be chosen for the trial and test functions, but in general they only differ on the boundaries. The test and trial spaces Vˆ and V are in the present problem defined as Vˆ = {v ∈ H 1 (Ω) : v = 0 on y = ±h}, 1
V = {v ∈ H (Ω) : v = 0 on y = −h and v = U on y = h} ,
(18) (19)
Briefly, H 1 (Ω) is known as the Sobolev space containing functions v such that v 2 and ||∇v||2 have finite integrals over Ω. You will learn more about the Sobolev space in a basic finite element course. For now it will be sufficient to know that you need to choose a function space and for fluid flow it is usually appropriate to choose a space consisting of piecewise linear or quadratic polynomials. Note that the proper mathematical statement of our variational problem now goes as follows: Find u ∈ V such that Z Z − ∇u · ∇v dx = f v dx ∀v ∈ Vˆ . (20) Ω
Ω
Implementation The entire implementation that solves the variational problem (20) is given in Listing 1. If this bit of code is stored in a textfile called "Couette.py", the program can be run by typing "python Couette.py" on the command line of a bash shell in the same folder as the file is stored. Alternatively one can enter an environment like Python or IPython (recommended: install with "sudo apt-get install ipython") and execute the script there with "run Couette". [....] ipython In [1] run Couette
/* start ipython in a regular bash shell */ /* execute script in ipython shell */
A more thorough tutorial for the Poisson equation is given in [2]. Here we will repeat only the most necessary steps. The first thing we need to do is to import all basic FEniCS functionality into the python environment from dolfin import *
4
""" Couette flow """ from dolfin import * h = 1. N = 10 mesh = IntervalMesh (N , -h , h ) V = FunctionSpace ( mesh , ’ CG ’ , 1 ) u = TrialFunction ( V ) v = TestFunction ( V ) def bottom (x , on_boundary ) : return near ( x [ 0 ] , -h ) and on_boundary def top (x , on_boundary ) : return near ( x [ 0 ] , h ) and on_boundary U = 1. bcs = [ DirichletBC (V , 0 , bottom ) , DirichletBC (V , U , top ) ] u_ = Function ( V ) solve ( - inner ( grad ( u ) , grad ( v ) ) * dx == Constant ( 0 ) * v * dx , u_ , bcs = bcs ) u_exact = project ( Expression ( " U / 2 *( 1 + x [ 0 ]/ h ) " , U =U , h = h ) , V ) plot ( u_ , title = " Couette flow " ) plot ( u_ - u_exact , title = " Error couette flow " )
Code Listing 1: Couette.py
This is typically the first line of most FEniCS scripts as it imports all necessary functionality like Interval,FunctionSpace,Function,DirichletBC,UnitSquare and much, much more. A computational mesh is then generated by dividing the computational domain (Ω = [−h, h]) into N equally sized intervals, each of size 2h/N h = 1. N = 10 mesh = Interval (N , -h , h )
We now choose a piecewise linear solution by defining a function space over the mesh V = FunctionSpace ( mesh , " CG " , 1 ) u = TrialFunction ( V ) v = TestFunction ( V )
Second order polynomials or higher may be chosen by using a higher number here, but for the current problem this will not enhance the accuracy since the analytical solution is linear. The trial and test functions u and v are then declared, just as described leading up to Eq. (20). The current problem assigns a value for u on both boundaries, which is mathematically termed Dirichlet boundary conditions. To implement these Dirichlet conditions we first need to specify where the boundaries are using two python functions def bottom (x , on_boundary ) : return near ( x [ 0 ] , -h ) and on_boundary def top (x , on_boundary ) : return near ( x [ 0 ] , h ) and on_boundary
Here x is an array representing position. It is an array of length equal to the number of spatial dimensions of the mesh. In our case it is an array of length 1. The boundary conditions are created using the FEniCS function DirichletBC. U = 1.
5
Figure 2: Numerical solution of the Couette flow.
bcs = [ DirichletBC (V , 0 , bottom ) , DirichletBC (V , U , top ) ]
Note that by using brackets [ ] the two boundary conditions are placed in a python list named bcs. The variational problem is solved by creating a Function to hold the solution and then calling the function solve. u_ = Function ( V ) solve ( - inner ( grad ( u ) , grad ( v ) ) * dx == Constant ( 0 ) * v * dx , u_ , bcs = bcs )
The u− Function has N + 1 unknowns, which are the solutions at the N + 1 nodes of the mesh. However, it is important to remember that the finite element solution is not restricted to the nodes of the mesh. The finite element solution is the piecewise continuous linear profiles, well defined over the entire elements. You can look at the discrete solution at the nodes on the command line as a numpy array using w = u_ . vector () . array () print w
or plot the piecewise linear solution using plot ( u_ , title = " Couette " , interactive = True )
The numerical result is shown in Fig. 2. The exact solution is given in Eq. (13). We can put the exact solution in a FEniCS Function by projecting an Expression onto the same function space as the numerical solution: u_exact = project ( Expression ( " U / 2 *( 1 + x [ 0 ]/ h ) " , U =U , h = h ) , V )
The Functionu_exact will now contain N + 1 values, just like u− , and if we have computed correctly these values should be more or less the same as in u− . A plot of the numerical solution minus the exact solution shows that the computed solution is exact down to machine precision ≈ 10−16 . This is to be expected since the solution is linear and we are assuming a piecewise linear finite element solution.
6
Couette flow between axially moving concentric cylinders The next example in Chapter 3-2.2 is the flow between axially moving concentric cylinders. The equation is the same as for the regular Couette flow in 3-2.1, but the coordinate system is cylindrical. There is no applied pressure gradient and the flow is described by the Poisson equation with no source.
1 ∂ r ∂r
∇2 u = 0, ∂u r = 0. ∂r
(21) (22)
The two cylinders have diameters r0 and r1 , where r0 < r1 . The Dirichlet boundary conditions are u(r = r0 ) = u0 and u(r = r1 ) = u1 . The solution to Eq. (22) can be found by integrating twice u(r) = C1 ln(r) + C2 ,
(23)
where the two integration constants are found using the boundary conditions leading to U1 − U0 ln(r1 /r0 ) ln(r1 ) ln(r0 ) C2 = U0 − U1 ln(r1 /r0 ) ln(r1 /r0 )
C1 =
which inserted into Eq. (23) gives u(r) = U0
ln(r1 /r) ln(r/r0 ) + U1 . ln(r1 /r0 ) ln(r1 /r0 )
(24)
Equation (24) is exactly the sum of Eqs. (3-18) and (3-19), which is a result of the governing equation being linear. The variational formulation of the problem reads Z Z − ∇u · ∇v dx = f v dx , (25) Ω
Ω
but in Cylindrical coordinates the volume integral needs to be transformed (dx = rdr2πL, assuming the cylinder has length L) and the variational problem becomes Z Z − ∇u · ∇v rdr = f vr dr . (26) Ω
Ω
Note that the gradient requires no special treatment since the gradient component in the r-direction is unchanged in cylindrical coordinates (see Eq. (3)). A FEniCS implementation for axially moving concentric cylinders is shown in Listing 2.
Suggested assignments Written assignments Problems 3-1, 3-2 and 3-3 in White [7]. Computer exercise Validate the analytical results (3-22) and (3-23) in Chapter 3-2.3 of White [7], for flow between rotating concentric cylinders. Can you reproduce Eq. (3-23)? Suggested solution is given in Listing 3.
7
""" Couette flow between two axially moving cylinders """ from dolfin import * import pylab parameters [ ’ r e o r d e r _ d o f s _ s e r i a l ’] = False r0 = 0 . 2 r1 = 1 . u0 = Constant ( 1 ) u1 = Constant ( 1 ) mesh = IntervalMesh ( 1000 , r0 , r1 ) V = FunctionSpace ( mesh , " CG " , 1 ) u = TrialFunction ( V ) v = TestFunction ( V ) def inner _boundar y (x , on_boundary ) : return near ( x [ 0 ] , r0 ) and on_boundary def outer _boundar y (x , on_boundary ) : return near ( x [ 0 ] , r1 ) and on_boundary bc0 = DirichletBC (V , u0 , inner _boundar y ) bc1 = DirichletBC (V , u1 , outer _boundar y ) r = Expression ( " x [ 0 ] " ) F = inner ( grad ( v ) , grad ( u ) ) * r * dx == Constant ( 0 ) * v * r * dx u_ = Function ( V ) # Compute all three s u b p r o b l e m s (3 - 2 ) and plot in the same figure pylab . figure ( figsize =( 8 , 4 ) ) for u00 , u11 in zip ([ 1 , 1 , 1 ] ,[1 , -1 , 2 ]) : u0 . assign ( u00 ) u1 . assign ( u11 ) solve (F , u_ , bcs =[ bc0 , bc1 ]) pylab . plot ( u_ . vector () . array () , mesh . coordinates () ) pylab . legend ([ " ( a ) " , " ( b ) " , " ( c ) " ] , loc = " lower left " ) pylab . xlabel ( " Velocity " ) pylab . ylabel ( " r " ) pylab . savefig ( " problem3 - 2 . pdf " ) u_exact = ( u1 - u0 ) * ln ( r ) / ln ( r1 / r0 ) + u0 - ( u1 - u0 ) * ln ( r0 ) / ln ( r1 / r0 ) u_exact = project ( u_exact , V )
Code Listing 2: AxiallyMovingCyl.py
8
""" Flow between rotating concentric cylinders """ from dolfin import * r0 = 0 . 2 ; r1 = 1 mesh = IntervalMesh ( 100 , r0 , r1 ) V = FunctionSpace ( mesh , ’ CG ’ , 1 ) u = TrialFunction ( V ) v = TestFunction ( V ) x = Expression ( " x [ 0 ] " ) w0 = Constant ( 1 .) ; w1 = Constant ( 0 . 1 ) T0 = Constant ( 8 ) ; T1 = Constant ( 10 ) mu = Constant ( 0 . 25 ) ; k = Constant ( 0 . 001 ) u_ = Function ( V ) T_ = Function ( V ) F = inner ( grad ( v ) , grad ( u ) ) * x * dx + u * v / x * dx FT = inner ( grad ( v ) , grad ( u ) ) * x * dx - mu / k * v * x *( u_ . dx ( 0 ) - u_ / x ) ** 2 * dx def inner_bnd (x , on_bnd ) : return on_bnd and x [ 0 ] < r0 + DOLFIN_EPS def outer_bnd (x , on_bnd ) : return on_bnd and x [ 0 ] > 1 - DOLFIN_EPS bci = DirichletBC (V , r0 * w0 ( 0 ) , " std :: abs ( x [ 0 ] - 0 . 2 ) < 1 .e - 12 " ) bco = DirichletBC (V , r1 * w1 , outer_bnd ) bcTi = DirichletBC (V , T0 , inner_bnd ) bcTo = DirichletBC (V , T1 , outer_bnd ) solve ( lhs ( F ) == rhs ( F ) , u_ , bcs =[ bci , bco ]) solve ( lhs ( FT ) == rhs ( FT ) , T_ , bcs =[ bcTi , bcTo ]) # Compute exact s o l u t i o n given in ( 3 . 22 ) ue = project ( r0 * w0 *( r1 /x - x / r1 ) / ( r1 / r0 - r0 / r1 ) + r1 * w1 *( x / r0 - r0 / x ) / ( r1 / r0 - r0 / r1 ) , V ) # Compute exact s o l u t i o n given in ( 3 . 23 ) Tn = project (( T_ - T0 ) / ( T1 - T0 ) , V ) PrEc = mu * r0 ** 2 * w0 ** 2 / k / ( T1 - T0 ) Te = PrEc * r1 ** 4 / ( r1 ** 2 - r0 ** 2 ) ** 2 *(( 1 - r0 ** 2 / x ** 2 ) (1 - r0 ** 2 / r1 ** 2 ) * ln ( x / r0 ) / ln ( r1 / r0 ) ) + ln ( x / r0 ) / ln ( r1 / r0 ) Te = project ( Te , V ) print " \ nError velocity = " , errornorm ( u_ , ue , degree_rise = 0 ) print " Error temperature = " , errornorm ( Tn , Te , degree_rise = 0 ) print " ??? Should be close to zero .\ n " plot ( u_ , plot ( ue , plot ( Tn , plot ( Te ,
title = " Computed angular velocity " ) title = " Exact angular velocity ( 3 . 22 ) " ) title = " Computed temperature " ) title = " Exact temperature ( 3 . 23 ) " )
# Since I cannot r e p r o d u c e the t e m p e r a t u r e I have r e c o m p u t e d # ( 3 . 23 ) a n a l y t i c a l l y . I plot that result here C1 = w0 - r1 ** 2 *( w1 - w0 ) / ( r0 ** 2 - r1 ** 2 ) C2 = r1 ** 2 *( w1 - w0 ) / (1 - r1 ** 2 / r0 ** 2 ) C3 = ( T1 - T0 + C2 ** 2 * mu / k *( 1 / r1 ** 2 - 1 / r0 ** 2 ) ) / ln ( r1 / r0 ) C4 = T0 + C2 ** 2 * mu / k / r0 ** 2 - C3 * ln ( r0 ) Tee = project (( - C2 ** 2 * mu / k / x ** 2 + C3 * ln ( x ) + C4 - T0 ) / ( T1 - T0 ) , V ) plot ( C1 * x + C2 /x , mesh = mesh , title = " Recomputed velocity " ) plot ( Tee , mesh = mesh , title = " Recomputed temperature " ) print " \ nError recomputed temperature = " , errornorm ( Tn , Tee ) print " Which is a strong indication that ( 3 . 23 ) is wrong !! "
Code Listing 3: RotatingCylinders.py
9
Poiseuille flows Poiseuille flows are driven by pumps that forces the fluid to flow by modifying the pressure. Fluids flow naturally from regions of high pressure to regions of low pressure. Typical examples are cylindrical pipe flow and other duct flows. Figure 1 illustrates a fully developed plane channel flow. Fully developed Poiseuille flows exists only far from the entrances and exits of the ducts, where the flow is aligned parallel to the duct walls. If we assume the flow is in the x-direction, as shown in Fig. 3-6 of [7], then the velocity vector is u(y, z, t) = (u(y, z, t), 0, 0) and Navier-Stokes equations can be simplified to ∂u 1 dp = ν∇2 u − , ∂t ρ dx ∂u = 0, ∂x
(27) (28)
The equations are still linear because the flow is aligned in one direction and convection is thus zero. The only difference from Couette flow is that there is a non-zero source term in the pressure gradient. The transient term on the left hand side is zero for stationary flows. The total volume flow, Q, through any duct is found by integrating the velocity over the entire cross section, C, of the duct Z Q=
udA.
(29)
C
Using Eq. (38) it is also possible to define an average velocity, u, through the duct u=
Q . A
(30)
The average velocity is subsequently used to define the Reynolds number and certain friction factors - engineering tools used to classify duct flow. The circular pipe For a steady cylindrical pipe flow with radius r0 the solution to Eq. (36) is found simply by integrating twice and applying boundary conditions: ν d du 1 dp r = , (31) r dr dr ρ dx d du r dp r = , (32) dr dr µ dx du r2 dp r = + C1 , (33) dr 2µ dx du r dp C1 = + , (34) dr 2µ dx r r2 dp u(r) = + C1 ln(r) + C2 , (35) 4µ dx where C1 and C2 are integration constants. The constant C1 must be zero for the flow at the center of the pipe to remain finite. The condition at the wall u(r0 ) = 0 gives C2 = −
r02 ∂p , 4µ ∂x
(36)
which leads to the final expression for the pipe flow u(r) = −
1 ∂p 2 r0 − r2 4µ ∂x 10
(37)
Combined Couette and Poiseuille flow It is possible to combine an applied pressure gradient with moving walls. Such flows are termed combined Couette-Poiseuille flows and they are governed by the Poiseuille Eq. (36). The solution to a combined Couette-Poiseuille flow can be found as the sum of a Couette solution uc using zero pressure gradient and a homogeneous Poiseuille solution up using zero velocity on walls. For a plane channel with u(h) = U and u(−h) = 0 the solution is thus found by solving the two problems ∇2 uc = 0, uc (h) = U, uc (−h) = 0, 1 dp ∇2 up = , up (±h) = 0. µ dx
(38) (39)
The combined solution u = uc + up is the solution to the original problem. This can be seen by summing Eq. (47) and Eq. (48) and also evidently u(h) = uc (h) + up (h) = U and similarily for y = −h. The superposition is possible simply because the governing equation is linear. The principle is used also for transient flows in both Chapters (3-4) and (3-5). Noncircular ducts For steady and fully developed duct flows the governing equation is simply the Poisson equation ∇2 u =
1 dp . µ dx
(40)
The equation is linear and very easy to solve numerically for any shape of the duct. There is also a great number of analytical solutions available for noncircular duct flows, solutions that can be used to verify the quality of the numerical software. The duct solutions are often used for specifying inlet profiles to much more complicating geometries, where the flow enters the geometry through a duct. In Listing 4 we show a FEniCS code used to solve Eq. (49) for a rectangular duct spanned as −a 6 y 6 a and −b 6 z 6 b . Of interest here is the computation of the very complicated analytical expression for the velocity given as 16a2 u(z, y) = µπ 3
dp − dx
∞ X
(−1)
i−1 2
i=1,3,5,...
cosh(iπz)/2a cos(iπy)/2a 1− . × cosh(iπb)/2a i3
(41)
The FEniCS implementation of this exact solution overloads the Expression class and you should recognize Eq. (50) in the overloaded eval method. Here x is an array of the coordinates and x[0] and x[1] represent y and z respectively. Unfortunately, the Python Expression u_exact is quite slow to interpolate due to the non-vectorized for-loop. For this reason, a C++ version of the same Expression is implemented instead, which speeds up the program with a factor of 45. Analysing the error. In Listing 4 we compute the errornorm that compares the computed finite element solution with the exact solution. This error will depend on the mesh size and the order of the polynomial approximation. The error should disappear in the limit of a highly resolved mesh or for very high order polynomials. Given the polynomial order, the rate at which the error disappears can be computed by performing experiments with meshes of different resolution. We assume that the error for a mesh of element size hi can be written as Ei = Chri , where C is a constant. We now want to find the order r of which the error disappears with mesh refinement. The order r can be found by computing Ei for two different hi ’s, i.e., Ei = hri and Ei−1 = hri−1 , and then isolate r: ln(Ei /Ei−1 ) r= . (42) ln(hi /hi−1 ) Running Listing 4 the rectangle problem is solved for a range of meshes and the output is 11
from dolfin import * from numpy import cosh , cos set_l og_activ e ( False ) dpdx = Constant ( - 0 . 01 ) mu = Constant ( 0 . 01 ) a = 2 b = 1 factor = 16 .* a * a / mu ( 0 ) / pi ** 3 *( - dpdx ( 0 ) ) class u_exact ( Expression ) : def eval ( self , value , x ) : u = 0 for i in range (1 , 500 , 2 ) : u += (( - 1 ) **(( i - 1 ) / 2 ) *( 1 - cosh ( i * pi * x [ 1 ] / 2 . / a ) / cosh ( i * pi * b / 2 / a ) ) * cos ( i * pi * x [ 0 ] / 2 . / a ) / i ** 3 ) value [ 0 ] = u * factor # Much faster C ++ version ue_code = ’’’ class U : public Expression { public : double a , b , mu , dpdx ; void eval ( Array < double > & values , const Array < double > & x ) const { double u = 0 .; double factor = 16 .* a * a / mu / pow ( DOLFIN_PI , 3 ) *( - dpdx ) ; for ( std :: size_t i = 1 ; i < 600 ; i = i + 2 ) u += pow ( -1 , (i - 1 ) / 2 % 2 ) *( 1 . - cosh ( i * DOLFIN_PI * x [ 1 ]/ 2 ./ a ) / cosh ( i * DOLFIN_PI * b / 2 ./ a ) ) * cos ( i * DOLFIN_PI * x [ 0 ]/ 2 ./ a ) / pow (i , 3 ) ; values [ 0 ] = u * factor ; } } ; ’’’ u_c = Expression ( ue_code ) u_c . a = float ( a ) ; u_c . b = float ( b ) u_c . mu = float ( mu ( 0 ) ) ; u_c . dpdx = float ( dpdx ( 0 ) ) def main (N , degree = 1 ) : mesh = RectangleMesh ( -a , -b , a , b , N , N ) V = FunctionSpace ( mesh , ’ CG ’ , degree ) u = TrialFunction ( V ) v = TestFunction ( V ) F = inner ( grad ( u ) , grad ( v ) ) * dx + 1 / mu * dpdx * v * dx bc = DirichletBC (V , Constant ( 0 ) , Do mainBoun dary () ) u_ = Function ( V ) solve ( lhs ( F ) == rhs ( F ) , u_ , bcs = bc ) # u_e = i n t e r p o l a t e ( u_exact () , V ) u_e = interpolate ( u_c , V ) bc . apply ( u_e . vector () ) u_error = errornorm ( u_e , u_ , degree_rise = 0 ) return u_error , mesh . hmin () E = []; h = []; degree = 1 for n in [5 , 10 , 20 , 40 , 80 ]: ei , hi = main (n , degree = degree ) E . append ( ei ) h . append ( hi ) from math import log as ln for i in range (1 , len ( E ) ) : r = ln ( E [ i ] / E [i - 1 ]) / ln ( h [ i ] / h [i - 1 ]) print " h = % 2 . 2E E = % 2 . 2E r = % . 2f " % ( h [ i ] , E [ i ] , r )
Code Listing 4: RectangleDuct.py 12
h=4.47E-01 h=2.24E-01 h=1.12E-01 h=5.59E-02
E=6.40E-03 E=1.69E-03 E=4.29E-04 E=1.08E-04
r=1.76 r=1.92 r=1.98 r=1.99
showing the second order accuracy that is to be expected from using piecewise linear elements. Changing the degree in the FunctionSpace to 2 the order should be three and the output quite correctly reads: h=4.47E-01 h=2.24E-01 h=1.12E-01 h=5.59E-02
E=2.14E-04 E=2.63E-05 E=3.27E-06 E=4.04E-07
r=3.13 r=3.03 r=3.01 r=3.02
Suggested assignments Written assignments Problems 3-4 and 3-5 in White [7]. Computer exercise In White [7] Chap. 3-3.3 there are 6 analytical solutions provided for 6 different types of ducts. In this weeks computer assignment you are asked to verify the analytical solutions (3-47), (3-49) and (3-52). Experiment with higher order "CG" elements (the solution is then higher order continuous piecewise polynomials) and compute the errornorm. Does the error vanish for higher order polynomials for all ducts or does it remain constant?
Unsteady duct flows Unsteady plane shear flows are experienced by fluids where the driving forces are suddenly or continuously changed. A fluid initially at rest will for example respond to a sudden increase in the pressure gradient (we suddenly start the pump) and the volume flow through the duct will then increase monotonically until steady state is reached. The applied pressure gradient may also vary in time. Another scenario is that a wall is suddenly or continuously set in motion, dragging with it the fluid initially at rest. Common for these flows is that the transient term in Eq. (36) cannot be neglected. Starting flow in a cylindrical pipe When a fluid initially at rest suddenly is exposed to a constant pressure gradient, the fluid will start to move as a response to the applied forces and the flow will increase for some time until the steady state Poiseuille flow profile (46) is reached. For convenience we modify this equation slightly here and write it for the steady velocity us as us = um 1 − r˜2 , (43) where um = −
r02 ∂p 4µ ∂x
(44)
and r˜ = r/r0 . We use the superposition principle and split the equation into two contributions u(r, t) = v(r, t) + us (r),
(45)
where u(r, t) is the complete solution and v(r, t) is the solution to the homogeneous Eq. (36) in cylinder coordinates: 2 ∂v ∂ v 1 ∂v =ν , (46) + ∂t ∂r2 r ∂r
13
subject to boundary condition v(r0 , t) = 0 and initial condition v(r, 0) = −us (r). The equation can be non-dimensionalized by multiplying with r02 /ν and using t˜ = tν/r02 and r˜ = r/r0 ∂v ∂ 2 v 1 ∂v = 2 + . ∂ r˜ r˜ ∂ r˜ ∂ t˜
(47)
Equation (60) can be solved using a separation of variables v(˜ r, t˜) = V (˜ r)T (t˜). Inserted into Eq. (60) we obtain 2 dT d V 1 dV + , (48) V =T d˜ r2 r˜ d˜ r dt˜ 00 1 0 V T˙ = T V + V , (49) r˜ 00 0 V + 1r˜ V T˙ = , (50) T V where the dot and apostrophe represent ordinary derivatives with respect to t˜ and r˜ respectively. Since the left hand side depends only on t˜ and the right hand side only on r˜, both sides must be equal to a constant. It turns out that the constant must be negative to satisfy the appropriate boundary conditions. We call the new constant −λ2 and obtain the two separate ordinary differential equations T˙ + λ2 T = 0,
(51)
r˜2 V + r˜V + λ2 r˜2 V = 0.
(52)
00
0
The first equation has solution 2˜
T (t) = e−λ t .
(53)
The second equation can be rewritten using x = r˜λ and chain rule differentiation leading to 00
0
x2 V + xV + x2 V = 0,
(54)
with the apostrophe here being a derivative with respect to x. Equation (67) is Bessel’s differential equation of zero order. The solution to Bessel’s equation is the Bessel function of the first kind of order zero J0 (x). (55) A solution to V becomes V (˜ r) = AJ0 (λ˜ r),
(56)
where A is a constant. We now need to make sure that the boundary and initial conditions are satisfied. The boundary condition requires V (1) = J0 (λ) = 0. Figure 4 shows how the Bessel function behaves. Apparently it looks somewhat like a damped cosine function with multiple roots that we call λk . The first four roots are located at x = 2.4048, 5.5201, 8.6537, 11.7915 corresponding to λ1 , λ2 , λ3 , λ4 . One general solution is thus V (˜ r) = Ak J0 (λk r˜) with a total solution
(57) 2
˜ v(˜ r, t˜) = Ak J0 (λk r˜)e−λk t .
(58)
Since the equations are linear we can use superposition and obtain a total solution simply by summing over multiple possible solutions v(˜ r, t˜) =
∞ X
2˜
Ak J0 (λk r˜)e−λk t .
k=1
14
(59)
Figure 3: Plot of the Bessel function of first kind of zero order. We now have a solution consisting of many constants that satisfy the boundary condition. It remains to close these constants using the initial condition v(˜ r, 0) = −um (1 − r˜2 ). We have ∞ X Ak J0 (λk r˜) = −um (1 − r˜2 ) (60) k=1
and we want to find Ak . To this end we use orthogonality Z 1 xJn (λk x)Jn (λm x)dx = 0 for k 6= m
(61)
0
and orthonormality 1
Z
xJn (λk x)Jn (λk x)dx = 0
2 Jn+1 (λk ) . 2
(62)
If Eq. (73) is multiplied by r˜J0 (λm r˜) and integrated from zero to unity we get Z
1
r˜J0 (λm r˜) 0
∞ X
1
Z
um (1 − r˜2 )˜ rJ0 (λm r˜)d˜ r.
Ak J0 (λk r˜)d˜ r=−
(63)
0
k=1
We now use (74) to eliminate all terms on the left hand side where k 6= m and insert for (75). The result is a closed expression for Ak Z 1 2 Ak = − 2 r˜J0 (λk r˜)um (1 − r˜2 )d˜ r. (64) J1 (λk ) 0 The integral on the right hand side can be evaluated exactly (details left out for now) leading to Ak = −
4um J2 (λk ) 8um =− 3 λ2k J12 (λk ) λk J1 (λk )
(65)
The final solution to starting flow in a cylinder, Eq. (59), becomes u(˜ r, t˜) = um (1 − r˜2 ) −
∞ X 8um J0 (λk r˜) k=1
in agreement with Eq. (3-96) in White [7]. 15
λ3k J1 (λk )
2˜
e−λk t
(66)
Pipe flow due to an oscillating pressure gradient Consider now the same problem as in the previous section, but with a pressure gradient that is oscillating in time ∂p = −ρKeiωt , (67) ∂x √ where i = −1 and eiωt = cos ωt + i sin ωt. (68) The governing equation for the cylinder is thus ∂u = Keiωt + ν ∂t
∂ 2 u 1 ∂u + ∂r2 r ∂r
.
(69)
We now want solve Eq. (82) with no-slip boundary conditions on the cylinder walls. We will neglect the initial condition and look only for a long-term steady oscillatory solution on the form u(r, t) = eiωt V (r).
(70)
That is, we look for a solution where all the transient behaviour is governed by an oscillating pressure gradient proportional to eiωt . Inserting for Eq. (83) in Eq. (82) and using the same nomenclature as in the previous section we obtain 1 0 iωt iωt iωt 00 V iω e = K e + ν e V + V r 1 V iω = K + ν V 00 + V 0 r 2 iω Kr r2 V 00 + rV 0 − r2 V = − . ν ν p Using x = r iω/ν and chain rule differentiation the equation can be rewritten as x2 V 00 + xV 0 − x2 V = −
Kx2 , iω
(71)
where the apostrophe now represents differentiation with respect to x. This equation looks very much like a modified Bessel equation [3] of zero order. The only difference is the right hand side, which should be zero. To get rid of the right hand side we use another change of variables V = Vˆ +
K iω
(72)
and insert this in Eq. (84) such that x2 Vˆ 00 + xVˆ 0 − x2 Vˆ = 0.
(73)
The solution to the modified Bessel equation of zero order is the modified Bessel function of the first kind (the second kind cannot be used since this function is infinite for x = 0) of zero order, I0 , so Vˆ (x) = AI0 (x), (74) or in terms of the ordinary Bessel function: Vˆ (x) = AJ0 (−ix), where A is a constant. With this result we can now express the total solution as p K iωt u(r, t) = e AI0 (r iω/ν) + . iω 16
(75)
(76)
The boundary condition requires u(r0 , t) = 0, which determines A: A=−
K p
iωI0 (r0
iω/ν)
.
(77)
Inserted into Eq. (89) we are left with ! √ I0 (r iω) p 1− , I0 (r0 iω/ν)
(78)
! p −iω/ν) p 1− , J0 (r0 −iω/ν)
(79)
Keiωt u(r, t) = iω or Keiωt u(r, t) = iω
J0 (r
in accordance with Eq. 3-98 in White [7]. The Bessel function can be found in the toolbox scipy.special. The solution is computed in Listing 5 and the result is shown in Fig. 5 for a relatively large normalized ω ˜ = ωr02 /ν = 10. A smaller value of ω ˜ will result in velocity profiles closer to the steady Poiseuille profile umax (1 − r˜2 ). from numpy import * from pylab import * from scipy . special import jv r0 = 1 w = 0.1 K = 1.0 nu = 0 . 01 r = linspace (0 , r0 , 50 ) ws = w * r0 ** 2 / nu def u ( t ) : return K / 1j / w * exp ( 1j * w * t ) *( 1 - jv (0 , r * sqrt ( - 1j * w / nu ) ) / jv (0 , r0 * sqrt ( - 1j * w / nu ) ) ) figure ( figsize =( 6 , 4 ) ) ll = [] for i in range ( 6 ) : print 1 / w * i * 2 * pi / 6 plot ( u ( i / ( 6 * w ) * 2 * pi ) , r ) ll += [ r "t = 0 · τ " . format ( i ) ] legend ( ll ) axis ([ - 15 , 25 , 0 , 1 ]) xlabel ( " Velocity " ) ylabel ( " Radial position " ) show ()
Code Listing 5: plotCylOscillatingGradient.py
Unsteady flows with moving boundaries In the previous section the driving force for the oscillating flow was the pressure gradient. Transient behaviour can also be obtained for Couette type flows, where the velocity of the walls are either (1) Suddenly accelerated to a constant velocity uwall = U0 . (2) Oscillated as a function of time, i.e., uwall = f (t). The governing equation for these types of flow is the homogeneous heat equation ∂u = ν∇2 u. ∂t 17
(80)
Figure 4: Velocity profiles in a pipe with an oscillating pressure gradient. The parameter τ = 2π/w/6, such that an entire period is obtained for t = 6τ . We consider only parallel shear flows in Cartesian coordinates, where the velocity vector is u = (u(y, t), 0, 0) and the equation is reduced to ∂2u ∂u = ν 2. ∂t ∂y
(81)
There are many different solutions available for this 1D heat equation, depending on the boundary and initial conditions of the problem. Most solutions make use of the Fourier series, the Fourier integral or Fourier transforms, see, e.g., Kreyszig [6]. As a first example of flow that is suddenly accelerated to a constant velocity, consider a infinite plane normal to the y-axis located at y = 0 and initially at rest at t = 0. The plane is then suddenly accelerated to a constant velocity U0 in the x-direction and remains at this velocity for all t > 0. Above the plane, for y > 0, the fluid is initially at rest. Friction and the no-slip boundary condition will make the flow above the plane increase in speed. Far away from the plane the velocity will be zero, i.e., u(∞, t) = 0. This means that the velocity will never reach a steady state, and the boundary layer over the plane will continue to grow for all time. We can find the solution as before using a separation of variables, but first we normalize the velocity u − U0 v(y, t) = , (82) U0 such that the boundary condition at y = 0 becomes homogeneous, i.e., v(0, t) = 0 for t > 0. The PDE for v is still Eq. (94). Start by separating variables v(y, t) = T (t)V (y). (83) Inserted into Eq. (94) we get T˙ V 00 = = K, (84) νT V where K is a constant. To obtain physically realistic solutions, the constant needs to be negative. This can be understood looking first at the transient part: T˙ = KνT,
18
(85)
with solution T (t) = eKνt .
(86)
If K is positive, then the velocity will grow without bounds and without energy being added to the system. For the second equation we have V 00 − KV = 0.
(87)
√ √ V (y) = A sinh( Ky) + B cosh( Ky).
(88)
If K is positive, then the solution is
√ The boundary condition V (0) = 0 requires B = 0. The remaining term A sinh( Ky) grows without bounds as y −→ ∞, which is not in agreement with v(∞, t) = −1 and we have to assume that K is a negative constant that we can write as K = −λ2 . The solutions to the separated ordinary differential equations become 2
T (t) = e−λ
νt
,
(89)
V (y) = A sin(λy) + B cos(λy).
(90)
The constants need to be found using boundary and initial conditions. The boundary condition V (0) = 0 leads to B = 0 and as such one solution reads 2
v(y, t) = A sin(λy)e−λ
νt
.
(91)
To satisfy the initial condition we need to use more than one solution and through the superposition principle we can simply add solutions. A periodic Fourier series for v reads v(y, t) =
∞ X
2
Ak sin(λk y)e−λk νt ,
(92)
k=1
where Ak are constants, λk = kπ/L and L is the length of the periodic domain. However, our domain is not periodic and it is unbounded for y −→ ∞. It turns out that for infinite domains and non-periodic solution, it is advantageous to work with Fourier integrals instead. A Fourier integral for our problem reads Z ∞ 2 v(y, t) = A(λ) sin(λy)e−λ νt dλ. (93) 0
and the "constant" A(λ) is a continuous function of λ. Since v only contains sinuses it is an odd function. As such, even though we are only interested in the domain y > 0 we can define an initial condition for v(y, 0) over the entire −∞ < y < ∞ as an odd function Z ∞ v(y, 0) = 1 − 2H(y) = A(λ) sin(λy)dλ, for − ∞ < y < ∞, (94) 0
where H(y) is the Heaviside function. This way v(y, 0) = 1 for y < 0, v(y, 0) = −1 for y > 0 and by symmetry v(0, 0) = 0. Through orthogonality and the initial condition we can find A(λ) as (see Kreyszig [6]) Z 2 ∞ A(λ) = − sin(λy 0 )dy 0 . (95) π 0 Inserted into the total solution we get Z Z 2 2 ∞ ∞ v(y, t) = − sin(λy 0 )dy 0 sin(λy)e−λ νt dλ, π 0 0
19
(96)
Figure 5: Plot of the initial condition for function v(y, 0) = 1 − 2H(y). which can be rewritten by changing the order of integration as Z Z 2 2 ∞ ∞ v(y, t) = − sin(λy 0 ) sin(λy)e−λ νt dλdy 0 . π 0 0
(97)
The inner integral can be transformed using sin(λy) sin(λy 0 ) = 0.5(cos λ(y − y 0 ) − cos λ(y + y 0 )) Z Z 2 ∞ ∞ −λ2 νt 1 e (cos λ(y − y 0 ) − cos λ(y + y 0 )) dλdy 0 . (98) v(y, t) = − π 0 2 0 The inner integrals can then be computed exactly since r Z ∞ 2 π − e−λ νt cos λ(y − y 0 )dλ = e 4νt 0 and Z
∞
2
e−λ
νt
cos λ(y + y 0 )dλ =
r
0
π − e 4νt
y−y 0 √ 2 νt
2
y+y 0 √ 2 νt
2
,
(99)
.
(100)
dy 0 .
(101)
The solution now reads r v(y, t) = −
1 4πνt
∞
Z
− e
y−y 0 √ 2 νt
2
−
−e
y+y 0 √ 2 νt
2
0
Using integration by substitution, the integrals can be reorganized into error functions Z z 2 2 √ erf(z) = e−u du, π 0
(102)
if we simply use a change of variables y − y0 √ , 2 νt y + y0 u0 = √ , 2 νt u=
du 1 =− √ dy 0 2 νt du 1 = √ dy 0 2 νt
(103) (104)
The integrals become Z
∞
e
−
y−y 0 √ 2 νt
2
√ Z dy 0 = −2 νt
∞
2
e−u du,
(105)
y √ 2 νt
0
√ y √ = − νtπ 1 − erf 2 νt 20
(106)
Figure 6: Velocity profiles for flow over a plane that is suddenly accelerated from zero to U0 . and Z
∞
e
−
y+y 0 √ 2 νt
2
∞
√ Z dy 0 = 2 νt
2
e−u du,
(107)
y √ 2 νt
0
=
√
y √ νtπ 1 − erf . 2 νt
Putting it all together we finally obtain r
1 √ v(y, t) = − − νtπ (−2)erf 4πνt y √ . = −erf 2 νt
y √ 2 νt
(108)
,
(109) (110)
The original unnormalized velocity becomes y √ u(y, t) = U0 1 − erf , 2 νt
(111)
in agreement with Eq. 3-107 in White [7]. Profiles for the velocity above the plane is shown in Fig. 7.
Suggested assignments Written assignments conditions
Consider the homogeneous heat equation with inhomogeneous boundary ∂u ∂2u − ν 2 = 0, for ∂t ∂y u(y, 0) = φ(y),
0≤y≤L
u(0, t) = g, u(L, t) = h where g and h are constants. Find the general solution u(y, t). Hint: use a function U (y) = 1/L[(L − y)g + yh] and find the solution of v(y, t) = u(y, t) − U (y). The equation for v(y, t) is the same as for u(y, t), but now with homogeneous boundary conditions. Optional (difficult), find the general solution if g and h are functions of time. Two hints to the optional assignment are 21
Figure 7: Velocity profiles for flow over a plane that is suddenly accelerated from zero to U0 . Plot of the entire solution including the unphysical domain. Computer assignment Choose suitable g and h and compare the analytical solution from the written assignment with a numerical implementation. Transient problems Transient problems are usually solved in FEniCS using a finite difference approximation of the time derivative. The time dimension can be discretized using constant discrete time intervals of length 4t, and we look for solutions at the discrete times t = [0, 4t, 24t, ..., T − 4t, T ] = k4t, for k = 0, 1, 2, ..., N − 1, N , 4t = T /N . The solutions at the N + 1 different timesteps are similarly written as uk . Using finite differences for the time derivative, a variational form of the heat equation reads Z k Z 1 u − uk−1 vdx = −ν ∇uk− 2 · ∇vdx, (112) 4t Ω Ω where the right hand side is computed at the midpoint between timesteps k and k − 1 using 1 notation uk− 2 = (uk + uk−1 )/2. Note that when the solution is computed, we start at the initial condition at k = 0, where the initial condition u0 is known and u1 is unknown. When u1 is subsequently computed and known, we are ready to move on to the next solution u2 and so on. In other words, uk is always the unknown we are trying to compute and uk−1 , uk−2 , ... are all considered to be known. In FEniCS the unknown uk is represented in Forms as a TrialFunction, whereas all knowns are represented as Functions. A variational form for the heat equation in FEniCS may look like: u = TrialFunction ( V ) v = TestFunction ( V ) u_ = Function ( V ) # Known s o l u t i o n at k u_1 = Function ( V ) # Known s o l u t i o n at k - 1 dt = Constant ( 0 . 1 ) nu = 0 . 01 U = 0 . 5 *( u + u_1 ) F = inner ( u - u_1 , v ) * dx + dt * nu * inner ( grad ( U ) , grad ( v ) ) * dx
The solution of the form must be placed inside a loop, advancing the solution forward in time, something like: t = 0 while t < T : t += dt solve ( lhs ( F ) == rhs ( F ) , u_ , bcs )
22
# Advance s o l u t i o n to next t i m e s t e p : u_1 . vector () [:] = u_ . vector () [:]
The python functions lhs and rhs are used to extract bilinear (terms containing both trialand testfunctions) and linear (terms containing only testfunction and no trialfunction) forms respectively. The last line of code copies all the values from u_ to u_1. Note that uk is the unknown we look for at timestep k. In the variational form uk is represented as an unknown TrialFunction. However, when the variational form has been solved, the known solution can be found in the Function u_ and we are then finished with timestep k. When we now move on to the next timestep, the solution we just found becomes the solution at the previous timestep, i.e., at k − 1. This is why we copy all values from u_ to u_1 as our final task in the time loop. Suggested solution to computer assignment is given in Listing 6. Fluid oscillation above an infinite plate An infinite plate oscillates with a velocity u(0, t) = U0 cos(ωt), which is the boundary condition to the fluid flow set in motion above the plate. We look for a "steady state" solution u = (u(y), 0, 0), meaning that we look for a solution independent of initial conditions. This problem is also referred to as Stokes second problem. Since the plate oscillates with frequency cos(ωt) a justified guessed solution is u(y, t) = f (y)eiωt . Inserted into the unsteady 1D heat equation we obtain − νf 00 = 0, f iω eiωt eiωt 00 iω f − f =0 ν A general solution to this problem is f (y) = Ae−
√ iω ν
y
+ Be
√ iω ν
y
,
where only the first leads to physically realistic real solutions for y −→ ∞, such that B = 0. The boundary condition at y = 0 leads to u(0, t) = f (0)eiωt = Aeiωt , where the real part then requires A = U0 and as such √ iω u(y, t) = U0 e− ν y+iωt Unsteady flow between two infinite plates Consider two infinite plates separated by a distance h containing fluid initially at rest at t = 0. At t = 0 the velocity of the lower plate at y = 0 is suddenly accelerated to a velocity of U0 and the fluid above the plate starts to move due to friction and the no-slip boundary condition. The flow will approximate the steady linear Couette solution U0 (1 − y/h) as t −→ ∞. Find the velocity between the plates as a function of time and space. The velocity, u = (u(y), 0, 0), is parallel to the walls and described by the 1D heat equation ∂u ∂2u − ν 2 = 0, ∂t ∂y u(y, 0) = 0, u(0, t) = U0 , u(h, t) = 0 23
for
0≤y≤h
0
from dolfin import * import numpy U0 = 1 . L = 1. nu = 0 . 01 w = 0.1 mesh = IntervalMesh ( 40 , 0 , L ) V = FunctionSpace ( mesh , ’ CG ’ , 1 ) u = TrialFunction ( V ) v = TestFunction ( V ) T = 100 . N = 200 dt = T / N t = 0. g = Constant ( U0 * numpy . cos ( w * t ) ) h = 0 bc0 = DirichletBC (V , g , " std :: abs ( x [ 0 ]) < 1e - 12 " ) bcL = DirichletBC (V , h , " std :: abs ( x [ 0 ] - { } ) < 1e - 12 " . format ( L ) ) u_ = interpolate ( Expression ( " U0 *( 1 - x [ 0 ]/ L ) " , U0 = U0 , L = L ) , V ) u_1 = Function ( V ) u_1 . vector () [:] = u_ . vector () [:] class u_exact ( Expression ) : def eval ( self , value , x ) : value [ 0 ] = U0 *( 1 - x [ 0 ] / L ) * cos ( w * t ) f = 0 for i in range (1 , 20 ) : Ln = i * pi / L df = sin ( Ln * x [ 0 ]) / Ln *(( - w * cos ( w * t ) + Ln ** 2 * nu * sin ( w * t ) + w * exp ( - Ln ** 2 * nu * t ) ) / ( w ** 2 + Ln ** 4 * nu ** 2 ) ) f += df value [ 0 ] += f * 2 * U0 * w / L F = inner (u - u_1 , v ) * dx + dt * nu * inner ( v . dx ( 0 ) , 0 . 5 *( u . dx ( 0 ) + u_1 . dx ( 0 ) ) ) * dx equation = lhs ( F ) == rhs ( F ) ue = Function ( V ) uex = u_exact () for t in numpy . linspace ( dt , T , N ) : g . assign ( U0 * numpy . cos ( w * t ) ) solve ( equation , u_ , bcs =[ bc0 , bcL ]) u_1 . vector () [:] = u_ . vector () [:] plot ( u_ , title = " Velocity " ) ue . vector () [:] = interpolate ( uex , V ) . vector () [:] plot ( ue , title = " Exact U " ) print " Errornorm = " , errornorm ( u_ , ue , degree_rise = 0 ) interactive ()
Code Listing 6: HeatInhomogenBC.py
24
Through a shift of variables and using the steady Couette solution v(y, t) = u(y, t) − U0 (1 − y/h), the problem can be redefined with homogeneous boundary conditions ∂v ∂2v − ν 2 = 0, for 0 ≤ y ≤ h ∂t ∂y v(y, 0) = −U0 (1 − y/h), 0 < y < h v(0, t) = 0, v(h, t) = 0 We can solve this problem easily using separation of variables v(y, t) = T (t)V (y). Inserted into the heat equation we obtain as before V 00 T˙ = = −λ2 νT V and two ordinary differential equations for T and V 2
T (t) = e−λ
νt
,
V (y) = A sin(λy) + B cos(λy). The boundary conditions give us B = 0 and λ = λn = nπ/h for n = 1, 2, . . .. Using superposition we get the total solution for v(y, t): v(y, t) =
∞ X
2
An sin(λn y)e−λn νt ,
n=1
where the coefficients are found using the initial condition and orthogonality. That is, multiply v(y, 0) by sin(λm ), integrate from 0 to h and isolate An : Z 2U0 h An = − sin(λn y)(1 − y/h)dy h 0 2U0 An = − nπ The total solution is then u(y, t) = U0 (1 − y/h) −
∞ 2U0 X sin(λn y) −λ2n νt e . π n=1 n
Similarity solutions Similarity solutions are obtained when the number of independent variables describing a problem is reduced by at least one. We will first illustrate this by revisiting Stokes first problem - A fluid initially at rest in an infinite domain (y −→ ∞) is suddenly set in motion by an infinite flat plate located at y = 0. We have already found the solution to this problem using Fourier integrals. The solution is given in Eq. (124) and repeated here y √ u(y, t) = U0 1 − erf . 2 νt We will now look at this problem again and try to find a solution using a similarity approach. First define a similarity variable y η= √ , 2 νt and observe that the solution can be written in terms of merely one variable u(η) = U0 (1 − erf(η)) . 25
Usually we don’t know the solution and have to guess a similarity variable. Having defined η, the heat equation can be rewritten using chain rule differentiation ! 2 du ∂ 2 η du ∂η d2 u ∂η + −ν = 0. dη ∂t dη 2 ∂y dη ∂y 2 The partial derivatives of η are ∂η η =− , ∂t 2t ∂η 1 = √ , ∂y 2 νt ∂2η = 0. ∂y 2 Inserting this into the above leads to and ordinary differential equation for u(η), which is exactly what we were hoping to achieve du d2 u 2η + 2 = 0. dη dη This ordinary differential equation must be solved using boundary conditions u(0) = U0 and u(∞) = 0. Define first h(η) = du/dη and rewrite the ODE as 2ηh +
dh = 0. dη
Separate variables and integrate to obtain 2 du = Ae−η . dη
Integrate one more time to obtain u(η) = Aerf(η) + B Inserting for the boundary conditions we finally get the original solution derived with much more effort in Eq. (124).
Suggested assignments Written assignments Problem 3-15, 3-16, 3-17 from White [7]. Plane stagnation flow Another well known and much used similarity solution is the streamfunction ψ(x, t), that is most often used for two-dimensional flows, where it is defined through u=
∂ψ , ∂y
v=−
∂ψ . ∂x
(113)
In 2D the only non-zero component of the vorticity vector, ωz , is computed as ωz =
∂v ∂u − , ∂x ∂y
(114)
If this definition is combined with Eq. (137) we obtain a Poisson equation for the streamfunction ∇2 ψ = −ωz . 26
(115)
The streamfunction is much used for inviscid irrotational flows, where the vorticity component ωz = 0. However, the definition of the streamfunction is equally valid for viscous flows. An illustration of plane stagnation flow is given in Fig. (3-24) of [7]. For inviscid flows the solution is trivially obtained as ψ = Bxy,
u = Bx,
v = −By,
(116)
where B is a positive constant. Make sure to check that the solution satisfies both Eq. (139) (with zero right hand side) and the continuity equation ∂u ∂v + = 0. ∂x ∂y
(117)
For viscous flows it is somewhat more complicated, since the right hand side of Eq. (139) is nonzero. To find the solution for viscous flows we also need to consider the momentum equations in two dimensions 2 ∂u ∂u 1 ∂p ∂ u ∂2u +v u + , =− +ν ∂x ∂y ρ ∂x ∂x2 ∂y 2 2 ∂2v ∂v ∂v 1 ∂p ∂ v + . (118) u +v =− +ν ∂x ∂y ρ ∂y ∂x2 ∂y 2 These equations are nonlinear due to the two underlined terms and coupled through the continuity equation. Note that there are three equations for the three unknowns u, v, p, so the equations are closed. We will now look for a similarity solution through a modification of the streamfunction of the form ∂ψν df ∂ψν ψν = Bxf (y), u = = Bx , v = − = −Bf. (119) ∂y dy ∂x Using an apostrophe for the derivative of f with respect to y one has immediately 0 ∂u = Bf , ∂x ∂v = 0, ∂x
00 ∂u = Bxf , ∂y 0 ∂v = −Bf , ∂y
∂2u = 0, ∂x2 ∂2v = 0, ∂x2
000 ∂2u = Bxf , ∂y 2 00 ∂2v = −Bf . ∂y 2
We immediately see that the continuity equation is satisfied. Inserting for the streamfunction in Eq. (142) we obtain 0
1 ∂p , ρ ∂x 0 00 1 ∂p B 2 f f + νBf = − ρ ∂y 00
B 2 x(f )2 − B 2 xf f − νBxf
000
=−
The last equation here states that ∂p/∂y is only a function of y and thus ∂2p = 0. ∂x∂y The momentum equation in the x-direction can be simplified by dividing through by −νBx f
000
+
0 B 00 1 ∂p f f − (f )2 = ν νBxρ ∂x
The left hand side is only a function of y and the right hand side only of x. Treating the right hand 0 00 000 side as a constant we can compute its value using the boundary conditions f = 1, f = f = 0
27
for y −→ ∞ (the first follows from freestream condition uviscous = uinviscid ). Inserted for the boundary conditions we obtain finally f
000
+
0 B B 00 f f − (f )2 = − . ν ν
(120)
Note that Eq. (144) is an exact equation for stagnation flow, since no terms have been eliminated in its derivation. The equation is nonlinear, which calls for iterative numerical p solution techniques. The equation can be nondimensionalized using lengthand velocityscales ν/B and √ νB respectively, and the dimensionless variables r √ B , ψ = xF (η) Bν. (121) η=y ν We can now easily obtain r
ν , B r r r 0 0 0 dF dη ν B ν f = =F =F , dη dy B ν B r 0 00 00 B dF dη =F , f = dη dy ν
f (y) = F
00
f
000
=
000 B dF dη =F . dη dy ν
Inserted into Eq. (144) we obtain the dimensionless equation F
000
00
0
+ F F + 1 − (F )2 = 0, 0
(122) 0
that can be solved using boundary conditions F (0) = F (0) = 0 and F (∞) = 1. Axisymmetric stagnation flow The plane stagnation flow discussed in the previous section is stagnant for a line in the z-plane located at x = 0. Axisymmetric stagnation flow is similar in form, but only stagnant in a single point located at x = y = z = 0. This axisymmetric flow is what you obtain by pointing a garden hose directly towards a plane wall (neglecting gravity). The equations are similar to the plane flow, but may be simplified using cylindrical coordinates. A streamfunction in cylindrical coordinates can be defined through 1 ∂ψ 1 ∂ψ , uz = (123) ur = − r ∂z r ∂r For axisymmetric flows with uθ = 0 the continuity equation reads 1 ∂rur ∂uz + = 0. r ∂r ∂z Inserting for Eq. (147) it is easily verified that continuity is satisfied. The streamfunction for axisymmetric inviscid flow towards a stagnation point is given as ψ = −Br2 z which leads to velocity components ur = Br,
uz = −2Bz
28
For viscous flows one may obtain a dimensionless similarity solution using r √ B 2 ψ = −r F (η) Bν, η = z . ν Inserting into the momentum equation for ur the mathematics are very much like in the previous section leading to 000 00 0 F + 2F F + 1 − (F )2 = 0. (124) This differs from plane stagnation flow only by the factor 2.
Numerical solution of nonlinear equations Equation (146) and Eq. (148) are nonlinear and no analytical solutions are known. Very few techniques are actually available for solving nonlinear equations analytically and as such we usually have to rely on numerical methods to obtain solutions for real fluid flows. Reynolds Averaged Navier-Stokes equations, that will be discussed thoroughly in chapter 6 of White [7], are basically Navier-Stokes equations with a nonlinear viscosity coefficient. In this section we will consider two of the most important techniques for iteratively solving nonlinear equations: Picard and Newton iterations. The general procedure for obtaining solutions to nonlinear equations is to guess an initial solution and then successively recompute new and hopefully better approximations to the solution. This is illustrated nicely with Newton’s method (also called Newton-Raphson’s method). Consider a nonlinear function f (x) of one variable x (e.g., f (x) = x2 − 1 or f (x) = x sin(x) − 1), where one is interested in finding the roots x such that f (x) = 0. Newton’s method boils down to making an initial guess x0 that does not satisfy our equation (i.e., f (x0 ) 6= 0) and from this initial guess we successively compute better approximations to the final root: Guess x0 ,
n=0
while not f (xn ) ≈ 0 do xn+1 = xn −
f (xn ) f 0 (xn )
n=n+1 That is, compute x1 from x0 and check if the solution is close enough to the root. If not, compute x2 using x1 as initial condition. Repeat until f (xn ) ≈ 0. When PDEs are solved numerically we obtain through discretization a system of many equations for many variables. Newton’s method extends easily to systems of equations as well. Consider 2 equations with two unknowns written compactly as F (x) ( x2 + 2xy = 0, F (x) = (125) x + 4y 2 = 0, where x = (x, y)T . The vector F has two components (the two equations) and there are two unknowns. We can compute the derivative of F with respect to x ∂Fi 2x + 2y 2x = . (126) Jij = 1 8y ∂xj The derivative is often called the Jacobian. Newton’s method for these two equations (or any system of equations) is simply J(xk )(xk+1 − xk ) = −F (xk ),
(127)
or with index notation for equation i k Jij (xk+1 − xkj ) = −Fik , j
29
(128)
where the k index signals that both J and F are computed using the solution at iteration step k. There is no summation on repeated k’s. A discrete finite element solution of the function u can be written as u(x) =
N X
ui vi (x),
(129)
i=0
where vi are the testfunctions. The solution has N + 1 unknowns ui , or "degrees of freedom", that for a linear Lagrange element are the values at the vertices of the mesh. When a PDE containing both trial- and testfunctions is assembled in FEniCS a set of N + 1 linear equations arise for these unknowns. We will now see how nonlinear equations can be handled by FEniCS. Nonlinear Poisson equation Consider the nonlinear Poisson equation − ∇ · (q(u)∇u) = f (u),
(130)
where q and f may be nonlinear functions of u. Using testfunction v as in Eq. (18) and neglecting the boundary term the variational form reads Z Z q(u)∇u · ∇vdx = f (u)vdx. (131) Ω
Ω
This is a nonlinear variational form and we need to solve it iteratively. Newton’s method Consider first Newton’s method for solving the nonlinear Poisson equation. We use the notation uk for the known solution at iteration step k and u the unknown trialfunction as before in Eq. (19). For Newton’s method we write the variational form solely in terms of known functions Z Z F (uk ; v) = q(uk )∇uk · ∇vdx − f (uk )vdx. (132) Ω
Ω
k
F (u ; v) is a linear form in that it does not contain the unknown u, only the testfunction v. It is a nonlinear form in terms of the known Function uk though. The Jacobian of F (uk ; v) is computed is FEniCS as u_ = Function ( V ) v = TrialFunction ( V ) F = inner ( q ( u_ ) * grad ( u_ ) , grad ( v ) ) * dx - inner ( f ( u_ ) , v ) * dx J = derivative (F , u_ , u )
where q(u_) and f(u_) are some python functions returning the coefficient of the equation and the source respectively. The function q might for example be coded like def q ( u ) : return 1 + u
which of course must appear in the script before creating the form F. A complete implementation that solves the nonlinear Poisson equation on the unit interval x=[0, 1] is shown in Listing 7. Note that everything below the line with solve(F == 0, u_, [bc0, bc1]) actually can be replaced simply by using this very compact call. The part from J = derivative(F,u_, u) and out is included here simply to illustrate how Newton’s method works in practise. Picard iterations For Picard iterations we have to linearize the variational form in Eq. (155) ourself. Let us first linearize such that the coefficient is known: Z Z k F (u; v) = q(u )∇u · ∇vdx − f (uk , u)vdx (133) Ω
Ω
30
from dolfin import * mesh = U n i t I n t e r v a l Me s h ( 10 ) V = FunctionSpace ( mesh , ’ CG ’ , 1 ) u = TrialFunction ( V ) v = TestFunction ( V ) bc0 = DirichletBC (V , Constant ( 0 ) , " std :: abs ( x [ 0 ]) < 1e - 10 " ) bc1 = DirichletBC (V , Constant ( 1 ) , " std :: abs ( x [ 0 ] - 1 ) < 1e - 10 " ) def q ( u ) : return 1 + u ** 4 u_ = interpolate ( Expression ( " x [ 0 ] " ) , V ) F = inner ( grad ( v ) , q ( u_ ) * grad ( u_ ) ) * dx # # solve ( F == 0 , u_ , [ bc0 , bc1 ]) J = derivative (F , u_ , u ) du = Function ( V ) error = 1 ; k = 0 while k < 100 and error > 1e - 12 : A = assemble ( J ) b = assemble ( - F ) [ bc . apply (A , b , u_ . vector () ) for bc in [ bc0 , bc1 ]] solve (A , du . vector () , b ) u_ . vector () . axpy ( 1 . , du . vector () ) error = norm ( du . vector () ) print " Error = " , error k += 1
Code Listing 7: nonlinearNewton.py
The first term on the rhs of F (u; v) is bilinear in that it contains both trial- and testfunctions u and v. The equation is also linear in u, which is necessary for FEniCS to accept it. Note that the function f could be linear in u as well. For example, if f (u) = u2 , then we can linearize it like f (u) = u · uk . Picard iterations are implemented as Newton up to the point where the form is created. The remaining part of the Picard code reads: F = inner ( grad ( v ) , q ( u_ ) * grad ( u ) ) * dx k = 0 u_1 = Function ( V ) while k < 100 and error > 1e - 12 : solve ( F == Constant ( 0 ) * v * dx , u_ , [ bc0 , bc1 ]) error = errornorm ( u_ , u_1 ) u_1 . assign ( u_ ) print " Error = " , k , error k += 1
The Function u_1 holds the previous solution and u_1.assign(u_) copies all values from the newly computed u_ to u_1. On my laptop computer Newton’s method requires 4 iterations to converge, whereas Picard requires 12. This is quite typical. Newton’s method is known to be very efficient when it actually finds the solution, but it often diverges if the initial guess is not close enough to the final solution. Picard is known to approach the solution more slowly, but in return it is usually more robust in that it finds the solution from a broader range of initial conditions.
Stokes flow Flows at very low Reynolds numbers are often called Stokes flow. If the Navier-Stokes equations are nondimensionalized using the characteristic velocity U and length scale L, the equations can
31
be simplified as Re
∂u ˜ ˜ ˜p + ∇ ˜ 2u + (˜ u · ∇)˜ u = −∇˜ ˜, ∂ t˜ ˜ ·u ∇ ˜ = 0,
(134) (135)
˜ = x/L, p˜ = p/(µU/L) and Re = ρU L/µ. The spatial derivative where u ˜ = u/U , t˜ = tU/L, x ˜ which explains the tilde on the nabla operator. The assumption for is taken with respect to x, Stokes flow is that the Reynolds number is very small Re << 1, such that the acceleration term on the left hand side of Navier-Stokes can be neglected. Stokes flow is therefore governed, on dimensional form, by µ∇2 u = ∇p,
(136)
∇ · u = 0.
(137)
Conveniently there is a FEniCS demo available for solving the Stokes equations in a threedimensional cubic domain. In this demo the velocity and pressure are solved using a coupled system of equations. That is, both Eq. (160) and Eq. (161) are solved simultaneously as opposed to in a segregated, sequential manner. Since Eq. (160) is a vector equation, this means that we are actually solving 4 equations (if the domain is 3D) simultaneously. Both u and p are treated as unknowns (TriaFunctions) using a MixedFunctionSpace: V = V e c t o r F u n c t i o n S p a c e ( mesh , ’ CG ’ , 2 ) Q = FunctionSpace ( mesh , ’ CG ’ , 1 ) VQ = V * Q # The Mixed space , a l t e r n a t i v e writing : # VQ = M i x e d F u n c t i o n S p a c e ([ V , Q ]) u , p = Tria lFunctio ns ( VQ ) v , q = TestFunctions ( VQ )
Notice that the velocity functionspace has higher degree than the pressure functionspace. This distinction is necessary in order to solve the Stokes flow using a mixed formulation. A mixed Lagrange functionspace where V and Q are of the same order is unstable. Make sure to try this out and observe the pressure. The variational formulation for the Stokes equations is found by multiplying Eq. (160) with TestFunction v and Eq. (161) with TestFunction q and then integrating over the domain Z Z µ v · ∇2 u dx = v · ∇p dx, Ω Ω Z q ∇ · u dx = 0. Ω
Both the Laplacian and pressure gradient are integrated by parts Z Z Z Z µ v · (∇u · n) ds − µ ∇v : ∇u dx = v · pn ds − p ∇ · v dx, Γ Ω Γ Ω Z q ∇ · u dx = 0, Ω
where n is the normal vector out of the domain and the colon represents an inner product (contraction) of two second order tensors. The boundary integral can be written as Z v · (pI − µ∇u) · n ds Γ
and you should recognize (pI − µ∇u) · n as part of the total stress τ = −pI + µ(∇u + ∇uT ) acting on the surface with normal vector n. In finite element communities the boundary condition (pI − µ∇u) · n = 0 is called pseudo-traction or a do-nothing boundary condition. It is often used on outlets where we are simply interested in letting the fluid escape with as little interference of 32
boundary conditions as possible. It is called do-noting because you don’t have to do anything to enforce it, just simply omit the boundary terms and solve the two equations Z Z µ ∇v : ∇u dx − p ∇ · v dx = 0, Ω ZΩ q ∇ · u dx = 0. Ω
In FEniCS we may solve these two equations (one vector and one scalar equation) coupled with the Form F = mu * inner ( grad ( v ) , grad ( u ) ) * dx - inner ( div ( v ) , p ) * dx - inner (q , div ( u ) ) * dx
Note that terms involving TestFunction v end up in the vector equation, whereas terms containing TestFunction q end up in the scalar equation. All terms defined in F are bilinear, in that they all contain one TestFunction and one TrialFunction. The sign of the velocity divergence has been set to negative, because this leads to a symmetric coefficient matrix, which is favourable for iterative solvers. To solve the equations we need to create a Function in the mixed functionspace to hold the solution, for example like this: up_ = Function ( VQ ) solve ( lhs ( F ) == rhs ( F ) , up_ , bcs ) u_ , p_ = up_ . split () plot ( u_ )
The boundary conditions will of course depend on the problem being solved. Note that you cannot set Dirichlet boundary conditions for both velocity and pressure simultaneously, since that would be an over specification. A no-slip boundary condition on a solid wall located at y = 0 for a two-dimensional problem can be set like bc = DirichletBC ( VQ . sub ( 0 ) , Constant (( 0 , 0 ) ) , " std :: abs ( x [ 1 ]) <1e - 12 " )
Likewise, a Dirichlet boundary condition on pressure can be set using VQ.sub(1). In the mandatory assignments we will compute Stokes flow and make use of the stream function ψ(x, t) defined in Eq. (137). The Poisson equation for the streamfunction Eq. (139), can be transformed to a variational form by multiplying with a TestFunction ψv and then integrating over the domain using integration by parts Z Z 2 ψv ∇ ψdx = − ψv ωz dx, Z Z Ω ZΩ − ∇(ψv ) · ∇(ψ)dx + ψv ∇ψ · nds = − ψv ωz dx. (138) Ω
Γ
Ω
Here n is the normal vector pointing outwards from the external boundary. The normal can be used directly in FEniCS forms through, e.g., n=FacetNormal(mesh). By taking the curl of Eq. (160) and using that the curl of a gradient is always zero, an equation for the vorticity vector ω is obtained ∇2 ω = 0. Likewise, by taking the divergence (not gradient as it says in White [7]) of Eq. (160) we obtain an equation for the pressure ∇2 p = 0, which follows since ∇ · ∇2 u = ∇2 (∇ · u) = 0. For Stokes flow both the pressure and the vorticity are governed by homogeneous Laplace equations. For 2D flows we also know the equation for the streamfunction ∇2 ψ = −ωz . Inserting this into the Laplace equation for ωz we obtain ∇4 ψ = 0,
33
(139)
which is a biharmonic equation for the streamfunction. Obviously, if ψ is a solution to ∇4 ψ = 0, then −ψ is a solution as well. In other words, the direction of flow along a streamline is arbitrary and only fixed due to boundary conditions. Reversing the direction of the flow (like we do in the mandatory assignment) will not change the streamlines, but the values will get the opposite sign. Stokes paradox states that it is not possible to obtain steady solutions to ∇4 ψ = 0 for 2D flows with both free stream and no-slip boundary conditions. Stokes paradox is, like d’Alembert’s paradox, really only a paradox because the equations do not represent real physical flow, just approximations in the limit. It follows from Stokes paradox that inertia can never be neglected for 2D flows with both free stream and no-slip boundary conditions. Creeping flow past a sphere Stokes flow past a sphere of radius a is a 3D flow and thus solutions to ∇4 ψ = 0 may be found even though there is no-slip on the sphere wall and free stream far away. In spherical polar coordinates the stream function, ψ, is defined through ur =
1 ∂ψ , r2 sin θ ∂θ
uθ = −
1 ∂ψ . r sin θ ∂r
(140)
The streamfunction equation becomes for spherical coordinates
1 ∂2 cot θ ∂ ∂2 + − 2 2 2 ∂r r ∂θ r ∂θ
2 ψ = 0,
(141)
with boundary conditions ∂ψ ∂ψ = = 0, for r = a, ∂r ∂θ 1 ψ = U r2 sin2 θ + const, for r ←→ ∞. 2 Using separation of variables White reports that the solution to this problem reads 1 a 3r 2r2 ψ = U a2 sin2 θ − + 2 , 4 r a a and thus we obtain the velocity components from Eq. (164) a3 3a ur = U cos θ 1 + 3 − , 2r 2r a3 3a uθ = U sin θ −1 + 3 + 4r 4r A few important notes • The velocity is independent of ρ and µ, which is actually true for all creeping flows. • There is perfect symmetry of the streamlines past the sphere. No wake and no separation. • The velocity is everywhere smaller than the free stream. This is contrary to inviscid flows where the velocity is maximum at the top and bottom of the sphere. For Stokes flow the velocity will here be zero due to no-slip. • The effect of the sphere can be observed at enormous distances away from the sphere. At r = 10a the velocity is still 10% lower than the free stream. 34
The pressure can be computed from the momentum equations in radial and θ-direction ∂p 2 ∂uθ 2ur 2uθ cot θ 2 , = µ ∇ ur − 2 − 2 − ∂r r r ∂θ r2 ∂p uθ 2 ∂ur = µr ∇2 uθ + 2 − 2 2 ∂θ r ∂θ r sin θ Insert for ur and uθ and integrate both equations, using boundary conditions, to obtain p(r, θ) = p∞ −
3µaU cos θ, 2r2
(142)
where p∞ is the pressure in the free stream. From Eq. (166) it is evident that the pressure is highest at the front (left hand side) of the sphere where θ = π, and lowest at the rear where θ = 0. The pressure difference sets up a force acting on the sphere in the streamwise direction. The total force acting on the sphere is a vector that can be computed as Z F = τ · n dA, Γ
where as before the total stress is composed of pressure and friction through the stress tensor τ = −pI + µ(∇u + ∇uT ). The normal to the surface of the sphere is everywhere aligned with the r-direction such that we can write Z Fp + Fτ = −pI + µ(∇u + ∇uT ) · n dA, ZΓπ = (τrr + τrθ )2πa2 sin θdθ, 0
where τrr and τrθ are the pressure and friction stresses respectively. This follows since the pressure force is always acting normal to the plane and shear acts in the tangent plane. Remember that τij is a force acting in the j-direction on a plane having i as the normal direction. The pressure has already been computed. The remaining shear stress can be computed in spherical coordinates as 1 ∂ur ∂uθ uθ + − τrθ = µ , r ∂θ ∂r r µU sin θ 3a3 =− . r 2r3 The total force acting in the streamwise direction is computed by inserting for τrr and τrθ leading to two simple integral as Fx = |Fp | cos θ + |Fτ | sin θ 2 4 = 3µU πa + , 3 3 = 6µπU a. In other words, the drag force consists of 2/3 friction and 1/3 pressure.
Mandatory assignments due 11/3 2014 kl. 12.00 Mandatory assignment (i) Verify the analytical solutions (3-47), (3-49) and (3-52) in White [7]. Experiment with higher order "CG" elements (the solution is then higher order continuous piecewise polynomials) and compute the errornorm. Report tables of the error vs mesh size (mesh.hmin()) and comment on the order of accuracy. See Listing (4) for how to compute the errors. 35
Mandatory assignment (ii) Solve Eq. (146) and Eq. (148) using both Picard and Newton iterations. Hint: Define a new variable H = F 0 and solve a coupled system of equations for H and F . Start for example like this: from dolfin import * L = 4 mesh = IntervalMesh ( 50 , 0 , L ) V = FunctionSpace ( mesh , ’ CG ’ , 1 ) VV = V * V # Mixed space for H and F fh = TrialFunction ( VV ) # T r i a l F u n c t i o n for the Mixed space f , h = split ( fh ) # split into c o m p o n e n t s in the space vf , vh = TestFunctions ( VV )
Mandatory assignment (iii) Assume low Reynolds number and use FEniCS to compute a numerical solution of Stokes flow for a driven cavity. The domain of the cavity is [0, 1] × [0, 1] and the dynamic viscosity µ = 100. The domain consists of 4 solid walls, where the top lid (y = 1 and 0 < x < 1) is moving at speed u = (1, 0). The remaining 3 walls are not moving. Compute the streamfunction and find the center of the vortex, i.e., the point where the streamfunction goes through a minimum. For the driven cavity the value of the streamfunction can be set to zero on the entire exterior domain. Note that the boundary condition on ψ follows from the very definition of the streamfunction Eq. (137), where it should be understood that the variable ψ will only need to be known up to an arbitrary constant. If ψ is a solution, then ψ + C gives exactly the same velocity field since the partial derivative of a constant (here C) is zero. As such we can put an "anchor" on the solution by specifying that ψ = 0 at the corner where x = 0, y = 0. It then follows that ψ will be zero on the entire domain. Along the left hand border, where x = 0 and 0 ≤ y ≤ 1, we have the boundary condition on velocity stating that u = ∂ψ/∂y = 0. Since the gradient of ψ is 0 along the border it follows that ψ = 0 along this border. Similarly, for the top lid v = −∂ψ/∂x = 0, and thus ψ must be equal to 0 for the entire top lid. The same procedure applies to the last two borders and consequently ψ = 0 for the entire border. Note that the value does not have to be zero, any constant value may be chosen. Mandatory assignment (iv) Assume low Reynolds number and use FEniCS to compute a numerical solution of Stokes flow creeping past a step (see Fig. 3-37 in [7]). A mesh for the geometry is shown in Fig. 9. The height of the step is 0.1L. The height and width of the rectangular geometry is 0.5L and L respectively. Use Re = U L/µ = 0.01 (setting density to unity) as in Fig. 3-37 in [7]. Set the velocity of the top (at y = 0.5L) to constant u = (1, 0). Use pseudo-traction for the inlet located at x = 0 and the outlet located at x = L. No-slip for the bottom wall. Create a suitable mesh using for example Gmsh, Triangle. If you have the latest version of FEniCS installed it is also possible to create this mesh directly by subtracting rectangles (see demo) or by creating a SubMesh of a RectangleMesh. However, a tool like Gmsh is more flexible and it is easy to generate meshes that have higher density near corners, as shown in Fig. 9. Once, e.g., a Gmsh mesh MyGmshMesh.msh has been created it can be converted to a dolfin mesh MyDolfinMesh.xml using the dolfin-convert tool. The command "dolfin-convert -h" presents a list of formats that can be converted to dolfin mesh through the dolfin-convert tool. [....] dolfin - convert MyGmshMesh . msh MyDolfinMesh . xml
(a) Compute the streamfunction and find the center location of the standing vortex. Report the result (e.g., in a table) as a function of mesh density. Hint: solve problem by enforcing boundary conditions weakly. Use definition in Eq. (137) and n=FacetNormal(mesh) to implement the weak boundary form (second term on left of Eq. (162)). (b) Make a contour plot, similar to Fig. 3-27 in [7], of the streamfunction. Hint: Dump result to VTK-format and plot contours using paraview. To create a VTK-file for the streamfunction 36
Figure 8: Mesh for a backwards facing step. solution Function psi: f = File ( " psi . pvd " ) f < < psi
(c) Compute the velocity flux in and out of the domain. Is mass being conserved? Hint: to compute the flow through left and right domains we need to integrate the solution over these domains only Z u=
udA. Γ
Surface integrals like this can be computed in FEniCS by making use of SubDomains and a FacetFunction: def left (x , on_boundary ) : return x [ 0 ] < 1e - 12 and on_boundary Left = AutoSubDomain ( left ) mf = FacetFunction ( " size_t " , mesh ) mf . set_all ( 0 ) Left . mark ( mf , 1 )
Briefly, this code creates a FacetFunction that has an integer value on all facets (in 2D that means all the edges) in the mesh ("size_t" may have to be replaced by "uint" depending on your version of dolfin). The SubDomain Left is created by feeding an inside function (left) to the AutoSubDomain function. Left.mark(mf,1) sets the value of all facets on the left boundary to 1. Using these tools we can now integrate over the left boundary exclusively. For example, to compute the area of the inlet do A = assemble ( Constant ( 1 ) * ds ( 1 ) , e x t e r i o r _ f a c e t _ d o m a i n s = mf , mesh = mesh )
(d) Reverse the direction of the flow using u = (−1, 0) for the top boundary. Does this change the location of the vortex? Explain the result. (e) Compute the normal stress on the bottom wall. Is there any difference depending on the
37
direction of the flow? Is this realistic for real flows of moderate Reynolds numbers? The normal stress on the wall is computed as Z (τ · n) · n ds,
(143)
Γ
where the stress tensor τ = −pI + µ(∇u + ∇uT ).
Suggested assignments Written assignments
Problems 4-1 and 4-3 in White [7].
Chapter 4 - Laminar boundary layers Important topics of Chapter 4. • Displacement thickness • Momentum thickness • Flat plate integral analysis • Boundary layer equations • Flow separation • Blasius solution • Falkner-Skan solution
Suggested assignments Written assignments • Derive the boundary layer equations (Eq. (4-32) in [7]) starting from the Navier-Stokes equations. • Derive the Blasius equation. • Derive the Falkner-Skan equation. Computer assignments Implement a nonlinear solver for the Blasius equation. Do the same for the Falkner-Skan equation and vary the parameter β as shown in Fig. 4-11 in White [7]. What happens at β = −0.19884? At −0.19884 ≤ β ≤ 0 there are according to White at least two possible solutions. One solution is shown in Fig. 4-11a in White. Another solution shows negative 00 values for f (0), thus indicating backflow close to the wall. Using different initial guesses for the solution it should be possible to obtain both solutions.
Suggested assignments Computer assignment Compute the flow past a rotating cylinder. Use a rectangular domain Ω = [0, 6] × [−1, 1] and place the cylinder at (x, y) = (1, 0) with a radius of 0.25. Assume at first steady creeping flow, walls at y = ±1 and set the velocity on the left hand side (x = 0) to 1 − y 2 . Set the cylinder to rotate against the clock at a constant speed of 1. Compute lift and drag forces on the cylinder. Reverse the direction of the rotation and recompute lift and drag. Now include convection and solve the Steady (nonlinear) Navier-Stokes equations for the same problem. Set the rotation to oscillate with an angular speed of sin πt and compute the unsteady creeping flow past the cylinder. Do the same for unsteady Navier-Stokes and attempt to find the von Kármán street for a steady cylinder. 38
Chapter 6 - Incompressible turbulent mean flow Turbulent flows are governed by the Navier-Stokes equations. However, • there are no simplifications possible by dimensional analysis or through similarity solutions, • no exact definition is known for turbulence, • turbulent flows are not very well understood. Turbulent flows are usually "defined" by listing their most characteristic properties. Here is what we know • Turbulence is a flow property and not a fluid property. • Turbulence is always three-dimensional in space and transient. There is no such thing as two-dimensional turbulence. • Turbulence is irregular, with seemingly random and chaotic motion. However, there is order to the chaos. The flow satisfies the Navier-Stokes equations, so it is apparently deterministic. Still, N-S are extremely sensitive to initial and boundary conditions (the butterfly-effect). The slightest perturbations in initial or boundary conditions leads to a completely different solution. Thus, turbulence is stochastic even though the Navier-Stokes equations are deterministic. • Turbulent flows consist to a great deal of vortices and vorticity. Vortex stretching and tilting are 3-dimensional phenomena that characterize turbulent flows and these processes can not happen in 2D. If a vortex tube is stretched it must increase its angular velocity to conserve angular momentum. This can only happen in 3D. In 2D vorticity is (unphysically) a conserved quantity. • The vortices come in a range of scales. The size of the largest vortices (the largest scales) is determined by the geometry of the flow, whereas the size of the smallest vortices (the smallest scales) is determined by viscosity. • The energy cascade. Energy is introduced into the flow on the largest scales and dissipated on the smallest. Dissipation ε of kinetic energy is defined as ε = µs : s, where strain s = 0.5 ∇u + ∇uT The strain increases dramatically towards the center of a vortex tube leading to higher dissipation rates in this region. • Turbulence occur at high Reynolds numbers. The normalized momentum equation reads ∂u 1 2 + (u · ∇)u = −∇p + ∇ u + f. ∂t Re Diffusion is stabilizing as it tends to smear out all gradients. Briefly, perturbations (disturbances) to the flow are amplified by convection and dampened by viscosity. If the Reynolds number is large, then diffusion is small and convection dominates, leading to unstable turbulent flows. If the Reynolds number is small then viscosity dominates and perturbations are killed before they can trigger turbulence. Engineers need to be able to predict the behaviour of turbulent flows. However, in a turbulent flow the velocity u(x, t) and pressure p(x, t) should really be considered as random variables. In other words, at any point in space and time we will not be able to predict the exact value of velocity or pressure. We can, however, predict the statistical properties of these random variables. This is usually accomplished using ensamble averages or Reynolds averaging. 39
Figure 9: Measurements of turbulent velocity. Consider first a turbulent flow that is statistically steady, i.e., the statistical properties of the flow are independent of time. This happens, e.g., for a plane channel flow or a straight pipe flow where the applied pressure gradient (the driving force) is held constant. As previously stated, in a turbulent flow the velocity vector u(x, t) can be considered a random variable. If you stand in the same spot inside the statistically steady turbulent flow and measure one velocity component, then the signal might very well look something like shown in Fig. 10, where 1000 samples have been taken. The arithmetic mean of the velocity over these samples can computed as hui (x) =
N 1 X u(x, ti ) N i=1
where u(x, ti ) is the velocity at time ti and N = 1000 for the series shown in Fig. 10. If the sampling is done in discrete intervals of time 4t, then ti = i4t. Furthermore, if the samples are taken at sufficiently long time intervals such that u(x, ti ) is uncorrelated with u(x, ti + 4t) then we talk about an ensamble average as N 1 X u(x, ti ). u(x) = lim N →∞ N i=1
40
By multiplying through by 4t in both numerator and denominator the ensamble average can also be rewritten as N
1 X u(x, ti )4t, N →∞ N 4t i=1 Z 1 T ≈ u(x, t)dt, T 0
u(x) = lim
where T = N 4t is the total sampling time, which typically needs to be larger than the largest timescales of the flow. It can be seen that for a statistically steady flow the ensamble average corresponds to the time average. For a more general turbulent flow where the statistics can change in time more care needs to be taken in defining the ensamble average because the random variable u(x, t) will in general be statistically different from the random variable u(x, t + 4t) (e.g., u(x, t) 6= u(x, t + 4t)). To resolve this, consider flipping a coin. If ξ is the random variable where head gives ξ = 1 and tail ξ = 0, then the arithmetic average obviously become N 1 X (i) hξi = ξ N i=1
where ξ (i) is the result of flip i and as N → ∞ we should get hξi = 0.5. Now, if the coins are identical then the arithmetic average is obviously the same if one person flips a coin N times or N persons flip one coin one time. This principle is used in defining an ensamble average for turbulent flows. If, instead of sampling the random variable u(x, t) at N different time intervals, we run N identical experiments and sample u(x, t) at the same time and place in all experiments, then the definition of the ensamble average will be N 1 X (i) u (x, t). N →∞ N i=1
u(x, t) = lim
For a statistically steady flow this will be identical to the time average and the left hand side will not be dependent on time. By using the ensamble average the instantaneous velocity and pressure may be decomposed into a mean and fluctuating component u(x, t) = u(x, t) + u0 (x, t), p(x, t) = p(x, t) + p0 (x, t).
(144) 0
Note that both the instantaneous velocity u(x, t) and the fluctuating velocity u (x, t) should be considered as random variables, whereas the mean velocity u(x, t) is deterministic. Consider any random variable decomposed as φ = φ + φ0 . By definition we have φ0 = 0. This follows since we can take the average of both sides of Eq. (169) leading to φ = φ + φ0 , = φ + φ0 , = φ + φ0 , that can only be true if φ0 = 0. (Note that the average of an average is still the average.) Some other useful averaging rules are φ0 φ = φ0 φ = 0, φφ = φ φ, 2
φφ = (φ + φ0 )(φ + φ0 ) = φ + φ0 φ0 , ∂φ ∂φ = . ∂s ∂s 41
The last rule follows since the two operations differentiation and averaging commute, i.e., the derivative of an average is the same as the average of a derivative. Having defined the average velocity and pressure we are now in a need of equations that can be used to predict them. Equations for any statistical measure can be derived directly by manipulating the Navier-Stokes equations. The equations for u and p are found simply by averaging NS and introducing Eq. (169). Averaging the continuity equation leads to ∇·u=∇·u=0 simply because averaging and differentiation commutes. The average of the momentum equation can be written 1 ∂u + (u · ∇)u = − ∇p + ν∇2 u + f ∂t ρ The density and viscosity are assumed constant. The first term on the left and all terms on the right are averaged by using commutation ∂u ∂u = , ∂t ∂t 1 1 ∇p = ∇p, ρ ρ ν∇2 u = ν∇2 u. This leaves the nonlinear convection term. Using index notation we can take two fast steps using continuity and commutation uj
∂ui uj ∂ui ∂uj = − ui ∂xj ∂xj ∂xj ∂ui uj = . ∂xj
Inserting now for Eq. (169) we have ui uj = (ui + u0i )(uj + u0j ) = ui uj + u0i u0j and thus uj
∂ui uj + u0i u0j ∂ui = ∂xj ∂xj = uj
∂u0i u0j ∂ui + ∂xj ∂xj
Putting it all together we obtain the Reynolds averaged Navier-Stokes equations ∂u0i u0j ∂u 1 + (u · ∇)u = − ∇p + ν∇2 u − + f, ∂t ρ ∂xj ∇·u=0
(145) (146)
Mandatory assignments due 6/5 2014 Mandatory assignment (i) Implement a nonlinear solver for the Falkner-Skan Eq. (168). (a) Vary the parameter β and reproduce Fig. 4-11 (a) and (b) in White [7]. (b) What happens at β = −0.19884?. At −0.19884 ≤ β ≤ 0 there are according to White at least two possible solutions. One solution is shown in Fig. 4-11a in White. Another solution 00 shows negative values for f (0), thus indicating backflow close to the wall. Using different initial guesses for the solution it should be possible to obtain both solutions. Show these in a plot for β = −0.1. 42
Mandatory assignment (ii) Perform benchmarks 2.2 a) and 2.2 b) of Schaefer and Turek, 1996 and report your results comparing with Table 3 and 4 of the benchmark. Mandatory assignmentp(iii) Consider a fully developed turbulent plane channel flow. The wall friction velocity v ∗ = ν∂u/∂y wall = 0.05 and the turbulent Reynolds number Reτ = v ∗ /ν = 1000. (a) Use the Mixing length model and implement a solver for a plane turbulent channel flow. ∂ 2 u 1 ∂p ∂u0 v 0 − − , ∂y 2 ρ ∂x ∂y ∂u u0 v 0 = −νT , ∂y ∂u νt = l2 | |, ∂y + y l = κy 1 − exp − , A yv ∗ y+ = . ν 0=ν
The constants κ = 0.41 and A = 26. Hint 1: the pressure gradient is constant and can be computed from v ∗ by integrating the momentum equation across the channel. Hint 2: use a mesh skewed towards the walls. You should resolve the solution up to at least y + = 1 (or y ≈ ν/v ∗ for the first inner node of the computational mesh). To compute a skewed mesh you could for example do something like this from numpy import arctan mesh = IntervalMesh ( 100 , 0 , 1 ) x = mesh . coordinates () x [: , 0 ] = arctan ( pi *( x [: , 0 ]) ) / arctan ( pi )
which gives y + = 2.31 for first internal node and thus is not dense enough! Modify the mesh and check the location of the first inner node to ensure that it’s less than ν/v ∗ . How many nodes do you need to ensure y + < 1 if you use a regularly spaced mesh that is not skewed towards the wall? (b) Verify that the solution approximates the theoretical results y + = u+ for y + < 5, 1 u+ = ln y + + B for y + > 30, κ where the "constant" B = 5.5. Can you improve the agreement with the computational results by modifying the constants? What is the value of the turbulent viscosity νT at the center of the channel? Do you believe this value is reasonable? Mandatory assignment (iv) Derive from first principles • the Reynolds Averaged Navier Stokes equations (Eq. 6-13 in [7]) • the turbulence kinetic energy equation (Eq. 6.17 in [7]) • the Reynolds stress equation (Eq. 6-18 in [7]) See, e.g., this book for more details about derivation. 43
Turbulence modelling Turbulence modelling is all about finding suitable closures, or models, for the Reynolds stress tensor. The Reynolds stress tensor is symmetrical u0i u0j = u0j u0i
(147)
and thus contains 6 unknown quantities. The Reynolds stress is not really a stress, but it is so called because of the way it appears in the mean momentum equation Eq. (170). The mean momentum equation can alternatively be rewritten as ∂u ρ (148) + (u · ∇)u = ∇ · τ + ρf , ∂t where τ ij = −pδij + 2µS ij − ρu0i u0j , is a new term that has dimensions of stress and 1 ∂ui ∂uj S ij = + . 2 ∂xj ∂xi
(149)
(150)
Mathematically then it appears that the total mean stress tensor has been added a third term −ρu0i u0j after the regular pressure and viscous stresses. The term is called a Reynolds "stress", but it is in fact just the contribution of the fluctuating velocities to the mean nonlinear convection. (Note that ρ is required for the term to have dimensions of stress.) By stress we usually mean the internal forces that fluid particles exert on each other. The highest level of RANS modelling is usually considered the second moment closures that solve transport equations for u0i u0j directly. Second moment closures are outside the scope of this course. The by far most commonly used turbulence model is the eddy viscosity (first moment) closure 2 u0i u0j = −2νT S ij + kδij , 3
(151)
where νT is a ’turbulent viscosity’. Turbulence models are usually classified by the number of additional PDE’s that are used to model the turbulent viscosity. The turbulent viscosity is a parameter of the flow and not the fluid. As mentioned before, one of the most important properties of a turbulent flow is its ability to efficiently mix momentum and scalars, like temperature. Mathematically, the enhanced mixing is manifested through the Reynolds stress and it is through Eq. (183) sought modelled as a diffusion process using νT as a positive (≥ 0) mixing rate constant. Inserted into the momentum equation the eddy viscosity gives rise to the term ∂u0i u0j ∂ ∂ui ∂uj 2 ∂k =− νt + + , ∂xj ∂xj ∂xj ∂xi 3 ∂xi and it can be seen that the first term on the right hand side will lead to enhanced mixing (or diffusion) of ui as long as νT is positive. Having established an algebraic model for the Reynolds stress (183), we have reduced the number of unknowns from 6 to 2 (νT and k). We will now discuss the most common strategies for closing the remaining terms. The turbulent viscosity is by dimensional reasoning the product of a velocityscale u ˜ and a lengthscale l νT = u ˜ · l, where different interpretations are possible for defining such scales. Remembering that one of the ’defining’ properties of turbulence is that it contains a range of scales, such a classification into one single velocity- and lengthscale may seem questionable from the very start. Nevertheless, most 44
turbulence models boil down to finding good approximations for these scales, and the modelled scales are then usually interpreted as the largest scales of turbulence. Many different models exist (including multiscale models, which is beside the scope for this course) and sometimes a timescale tk is used instead of u ˜, but then the two are related through u ˜ = l/tk . Turbulence models are usually classified by the number of additional PDEs that are required to establish the proper scales and we will now go through some of the most basic models. Zero-equation models Zero-equation turbulence models are models that use zero additional PDEs to model the turbulent viscosity. The Mixing length model was the first such turbulence model. For a simple plane shear flow where u is the tangential velocity and y is the wall normal direction the model reads du u ˜ = l , dy du νT = l2 . (152) dy For a plane shear flow the model is excellent as one may choose l ≈ y2 ,
for
y + < 5,
l ≈ κy,
for
30 < y + < 100,
l ≈ 1,
for
y + > 100
(153)
where κ = 0.41 is von Kárman’s constant and y is the distance to the wall. Further s ∂u v∗ = ν , ∂y wall
yv ∗ , y = ν +
are, respectively, the turbulent wall friction velocity and the distance to the wall in normalized ’wall’ units. A Reynolds number based on v ∗ , Reτ = L · v ∗ /ν is often used to characterize flow in turbulent plane shear flows. Several models exist that merge the three domains in Eq. (185) into one single continuous function. Van Driest provided a model that merged the first two inner layers using + y l = κy 1 − exp − , (154) A where A is a constant set to 26 for flat plate flow. This model should be merged with l = constant far enough from the wall. Far enough is often chosen when l from Eq. (186) becomes larger than a factor of the mixing layer thickness δ. An often used estimate is when κy = 0.09δ or y = 0.22δ. The Mixing length model is not a good model for other flows than plane boundary layer flows. For example, in the center of a plane channel the mean velocity gradient is zero due to symmetry (du/dy = 0). The Mixing length model Eq. (184) thus predicts that the turbulent viscosity should be zero in the center of the channel. This is contrary to the experimental observation and intuition, because the turbulent intensity is actually very large in the center. This flaws of the mixing length model first led to the suggested improvement that the velocityscale should be proportional to the turbulence intensity and not the mean velocity gradient √ u ˜ = const · k. (155) The problem now is that this model introduces a new unknown k that requires modelling (whereas the old model used known quantities l and u). Thus one additional PDE is required for closure of the turbulent viscosity. 45
One-equation models Most one-equation turbulence models solves a transport equation for k, the turbulent kinetic energy. The equation for k has already been derived in previous assignments and it is evident that it contains even more unclosed terms. If we start by rewriting the k-equation as ∂k ∂k ∂Tj + uj =− + P − ε˜ ∂t ∂xj ∂xj then the terms on the right hand side are ∂k 1 0 0 1 p ui δij + u0i u0i u0j − ν , ρ 2 ∂xj ∂ui , P = −u0i u0j ∂xj
Tj =
ε˜ = ν
∂u0i ∂u0i . ∂xj ∂xj
(156) (157) (158)
Here Tj represents turbulent transport, P is production of turbulent kinetic energy and ε˜ is ’pseudo’-dissipation of turbulent kinetic energy. The production P is closed since it only contains known quantities like the Reynolds stress and mean velocity gradients. The first two terms of Tj and ε˜ are unknown and require closure. ε˜ is called ’pseudo’-dissipation since the actual dissipation of k is really 2νs0ij s0ij . The two terms are related through the identity 2νs0ij s0ij = ν
∂u0i ∂u0i ∂u0 ∂u0j +ν i , ∂xj ∂xj ∂xj ∂xi
ε = ε˜ + ν
∂u0i ∂u0j . ∂xj ∂xi
Since the last term on the rhs is small relative to the first, dissipation and ’pseudo’-dissipation are similar for most flows. The turbulent transport term is usually modelled as gradient diffusion νt ∂k Tj = − ν + , σk ∂xj where σk is a constant in the near vicinity of one. Like the name suggests the model enhances diffusion of k and serves to smooth out the k field faster than possible simply through regular diffusion. This corresponds well with our knowledge of turbulence as an efficient mixing process. The ’pseudo’-dissipation rate scales like ε˜ ≈
u ˜3 . l
Thus we can find a suitable model for ε˜ simply by inserting for Eq. (187) √ (const · k)3 ε˜ = , l k 3/2 ε˜ = const · , l
and thus l = const ·
46
k 3/2 . ε˜
By inserting for the velocity- and lengthscales we get the following model for the turbulent viscosity √ νT = const · kl, νT = const ·
k2 . ε˜
A weakness of the model is that it requires the lengthscale l to be provided from knowledge of the problem under consideration. For this reason one-equation turbulence models are often referred to as being incomplete. One-equation models are popular for systems where the mixing length can be easily specified, like a plane boundary layer or an aeroplane wing. Two-equation models Two-equation turbulence models introduce an additional PDE for the missing lengthscale. Since two-equation models do not require any parameter (like l) from previous knowledge of the system, the two-equation models are often referred to as being complete. The most popular two-equation turbulence models are variations of the k − ε˜ model and the k − ω model. k − ε˜ models solve one PDE for k and an additional for ε˜. Likewise, k − ω models solve PDEs for k and ω, where ω ≈ ε˜/k. If k and ε˜ are known then l=
k 3/2 , ε˜
tk =
k , ε˜
u ˜=
√ l = k tk
where tk is a turbulent timescale. The turbulent viscosity is as before determined by νT = const · u ˜ · l = const ·
k2 . ε˜
A transport equation for ε˜ can be derived exactly from the Navier-Stokes equations. The resulting equation contains many new unknowns and here we will not go into detail. Instead we will here simply report the entire and closed k − ε˜ model with its most common model ’constants’ ∂ui ∂ui ∂ ∂ui ∂uj 1 ∂p + 23 k + uj = (ν + νT ) + − , ∂t ∂xj ∂xj ∂xj ∂xi ρ ∂xi ∂k ∂k ∂ ∂k νT + uj = ν+ + P − ε˜, ∂t ∂xj ∂xj σk ∂xj ∂ ε˜ ∂ ε˜ ∂ νT ∂ ε˜ ε˜2 P ε˜ + uj − Cε˜2 , (159) = ν+ + Cε˜1 ∂t ∂xj ∂xj σε ∂xj k k ∂ui = 0, ∂xi k2 νT = Cµ , ε˜ Cµ = 0.09, Cε˜1 = 1.44, Cε˜2 = 1.92, σε˜ = 1.3, σk = 1. Unfortunately the model ’constants’ are known to vary from flow to flow and thus often in need of tuning for optimal performance. Nevertheless, two-equation models are complete and the k − ε˜ model is very much in use in industry for a wide range of flows. There is a great number of different RANS turbulence models. Some are listed on the page for NASA’s Turbulence Modelling Resources [4] and the wiki [5] for turbulence modeling. Boundary conditions The average statistics in a turbulent flow have sharp gradients in the near vicinity of a wall. To properly resolve all statistics the location of the first inner computational node needs to be at approximately y + = 1. This restriction is quite demanding in terms of grid resolution, especially at high Reynolds number. The standard k − ε˜ model, Eq. (191), is not very accurate close to walls and many modifications exist to handle this problem. Two main approaches are 47
(1) Do not resolve the flow further than approximately y + = 30 and use wall functions to prescribe boundary conditions inside the wall instead of at the wall. (2) Resolve the flow completely (all the way up to y + = 1) and introduce damping functions. The wall functions are based on the log-law u+ =
1 ln y + + B, κ
(160)
which is known to be in close agreement with experiments of regular boundary layers for a range of Reynolds numbers. If the first inner node (the first node on the inside of the wall) is located at y p , then the velocity can be computed as 1 y p u∗ up = ln + B, ∗ u κ ν
(161)
References [1] http://fenicsproject.org/documentation/tutorial. [2] http://fenicsproject.org/documentation/tutorial/fundamentals.html#the-poisson-equation. [3] http://mathworld.wolfram.com/ModifiedBesselDifferentialEquation.html. [4] http://turbmodels.larc.nasa.gov/ Langley Research Center Turbulence Modeling Resource. [5] http://www.cfd-online.com/wiki/Turbulence_Modeling. [6] Erwin Kreyszig. Advanced Engineering mathematics. Wiley, 8 edition, 1999. [7] Frank M. White. Viscous Fluid Flow. McGraw-Hill, third edition, 2006.
48