This is our first Navier-Stokes example problem. We discuss the non-dimensionalisation of the equations and their implementation in oomph-lib
, and demonstrate the solution of the 2D driven cavity problem.
In dimensional form the 2D [3D] Navier-Stokes equations (in cartesian coordinates
and the continuity equation
where we have used index notation and the summation convention.
Here, the velocity components are denoted by
We non-dimensionalise the equations, using problem-specific reference quantities for the velocity,
where we note that the pressure and the variable body force have been non-dimensionalised on the viscous scale.
The non-dimensional form of the Navier-Stokes equations is then given by
and
where the dimensionless parameters
are the Reynolds number, Strouhal number and Froude number respectively.
The above equations are typically augmented by Dirichlet boundary conditions for (some of) the velocity components. On boundaries where no velocity boundary conditions are applied, the flow satisfies the "traction free" natural boundary condition
If the velocity is prescribed along the entire domain boundary, the fluid pressure
oomph-lib
provides two LBB-stable isoparametric Navier-Stokes elements that are based on the QElement<DIM,3>
family of geometric finite elements. They are nine-node quadrilateral (for DIM=2
), and 27-node brick (for DIM=3
) elements in which the mapping between local and global (Eulerian) coordinates is given by
Here Node
in the element, and the QElement<DIM,3>
class.
In both elements the velocity components
where Node
in the element. Nodal values of the velocity components are accessible via the access function
which returns the i-th
velocity component stored at the element's j-th
Node
.
The two elements differ in the way in which the pressure is represented:
In oomph-lib's
QCrouzeixRaviartElements
the pressure is represented by,
where the
The pressure degrees of freedom are local to the element and are stored in the element's internal Data
. They are accessible via the member function
which returns the value of the j-th
pressure degree of freedom in this element.
Each Node
in a 2D [3D] Crouzeix-Raviart element stores 2 [3] nodal values, representing the two [three] velocity components at that Node
.
In oomph-lib's
QTaylorHoodElements
the pressure is represented by a globally-continuous, piecewise bi-[tri-]linear interpolation between the pressure values
where the
The first 2 [3] values of each Node
in a 2D [3D] Taylor-Hood element store the two [three] velocity components at that Node
. The corner [vertex] nodes store an additional value which represents the pressure at that Node
. The access function
returns the nodal pressure value at the element's j-th
corner [vertex] Node
.
In sufficiently fine meshes, Taylor-Hood elements generate a much smaller number of pressure degrees of freedom than the corresponding Crouzeix-Raviart elements. However, Taylor-Hood elements do not conserve mass locally.
The Reynolds number, Strouhal number, inverse-Froude number, density ratio and viscosity ratio are assumed to be constant within each element. Their values are accessed via pointers which are accessible via the member functions re_pt()
for re_st_pt()
for re_invfr_pt()
for density_ratio_pt()
for viscosity_ratio_pt()
for
By default the pointers point to default values (implemented as static member data in the NavierStokesEquations
class), therefore they only need to be over-written if the default values are not appropriate. The default values are:
We use the same approach for the specification of the body force vector g_pt
(), the variable body force body_force_fct_pt()
, and the volumetric source function source_fct_pt(time,x)
. By default the (function) pointers are set such that
We will illustrate the solution of the steady 2D Navier-Stokes equations using the well-known example of the driven cavity.
![]()
![]() |
The figure below shows "carpet plots" of the velocity and pressure fields as well as a contour plot of the pressure distribution with superimposed streamlines. The velocity vanishes along the entire domain boundary, apart from the bottom boundary
The next figure shows the corresponding results obtained from a computation with QTaylorHoodElements
. The pressure plot illustrates how the interpolation between the corner nodes creates a globally continuous representation of the pressure.
Note that in both simulations, the flow field is clearly under-resolved near the ends of the "lid". In another example we will demonstrate the use of spatial adaptivity to obtain much better solutions for this problem.
The Reynolds number is the only non-dimensional parameter needed in this problem. As usual, we define it in a namespace:
We start by creating a DocInfo
object to store the output directory and the label for the output files.
We build the problem using QCrouzeixRaviartElements
, solve using the Problem::newton_solve()
function, and document the result before incrementing the label for the output files.
Finally, we repeat the process with QTaylorHoodElements
.
The Problem
class for our steady Navier-Stokes problem is very similar to those used for the steady scalar problems (Poisson and advection-diffusion) that we considered in previous examples. We provide a helper function fix_pressure(...)
which pins a pressure value in a specified element and assigns a specific value.
No actions are performed after the solution is found, since the solution is documented in main
. However, before solving, the boundary conditions must be set.
Finally, we provide an access function to the specific mesh and define the post-processing function doc_solution(...)
.
Since this is a steady problem, the constructor is quite simple. We begin by building the mesh and pin the velocities on the boundaries.
Next we pass a pointer to the Reynolds number (stored in Global_Physical_Variables::Re
) to all elements.
Since Dirichlet conditions are applied to both velocity components on all boundaries, the pressure is only determined up to an arbitrary constant. We use the fix_pressure(...)
function to pin the first pressure value in the first element and set its value to zero.
Finally, the equation numbering scheme is set up, using the function assign_eqn_numbers()
.
As expected, this member function documents the computed solution.
As discussed in the introduction, by default oomph-lib's
Navier-Stokes elements use the stress-divergence form of the momentum equations,
as this form is required in problems with free surfaces or problems in which traction boundary conditions are applied.
If the flow is divergence free (
assuming that the viscosity ratio
This simpler form of the equations can be used to solve problems that do not incorporate traction boundaries or free surfaces. We illustrate the use of these equations in another example.
A pdf version of this document is available.