In this example we shall demonstrate
In this example we shall illustrate the solution of the steady 2D Navier-Stokes equations in a modified driven cavity problem: The fluid is contained in a quarter-circle domain and is subject to gravity which acts in the vertical direction. We solve the problem in two different formulations, using the stress-divergence and the simplified form of the Navier-Stokes equations, respectively, and by applying the gravitational body force via the gravity vector, , and via the body force function, , respectively.
using the stress-divergence form of the Navier-Stokes equations Solve
and
in the quarter-circle domain , and , subject to the Dirichlet boundary conditions
on the curved and left boundaries; and
on the bottom boundary, . Gravity acts vertically downwards so that . |
When discussing the implementation of the Navier-Stokes equations in an earlier example , we mentioned that oomph-lib
allows the incompressible Navier-Stokes equations to be solved in the simplified, rather than the (default) stress-divergence form. We will demonstrate the use of this feature by solving the following problem:
using the simplified form of the Navier-Stokes equations Solve
and
in the quarter-circle domain , and , subject to the Dirichlet boundary conditions
on the curved and left boundaries; and
on the bottom boundary, . To make this consistent with Problem 1, we define the body force function as . |
Note that in Problem 2, the gravitational body force is represented by the body force rather than the gravity vector.
The two forms of the Navier-Stokes equations differ in the implementation of the viscous terms, which may be represented as
For an incompressible flow, , both forms are mathematically equivalent but the stress-divergence form is required for problems with free surfaces , or for problems in which traction boundary conditions are to be applied.
In order to be able do deal with both cases, oomph-lib's
Navier-Stokes elements actually implement the viscous term as
By default the components of the vector , are set to 1.0, so that the stress-divergence form is used. The components are stored in the static data member
of the NavierStokesEquations<DIM>
class which forms the basis for all Navier-Stokes elements in oomph-lib
. Its entries are initialised to 1.0. The user may over-write these assignments and thus re-define the values of being used for a specific problem. [In principle, it is possible to use stress-divergence form for the first component of the momentum equations, and the simplified form for the second one, say. However, we do not believe that this is a particularly useful/desirable option and have certainly never used such (slightly bizarre) assignments in any of our own computations.]
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 for Problem 1 at a Reynolds number of and a ratio of Reynolds and Froude numbers (a measure of gravity on the viscous scale) of . The velocity vanishes along the entire domain boundary, apart from the bottom boundary where the moving "lid" imposes a unit tangential velocity which drives a large vortex, centred at . The pressure singularities created by the velocity discontinuities at and are well resolved. The pressure plot shows that away from the singularities, the pressure decreases linearly with , reflecting the effect of the gravitational body forces which acts in the negative direction.
The next figure shows the computational results for Problem 2, obtained from a computation with adaptive Crouzeix-Raviart elements.
We use a namespace Global_Physical_Variables
to define the various parameters: The Reynolds number,
the gravity vector , and the ratio of Reynolds and Froude number, , which represents the ratio of gravitational and viscous forces,
In Problem 2, gravity is introduced via the body force function which we define such that Problems 1 and 2 are equivalent. (We use the gravity vector to specify the direction of gravity, while indicating it magnitude by )
Finally we define a body force function, which returns zero values, for use when solving Problem 1.
First we create a DocInfo
object to control the output, and set the maximum number of spatial adaptations to three.
To solve problem 1 we define the direction of gravity, , and set the entries in the NavierStokesEquations<2>::Gamma
vector to , so that the stress-divergence form of the equation is used [In fact, this step is not strictly necessary as it simply re-assigns the default values.]
Next we build problem 1 using Taylor-Hood elements and passing a function pointer to the zero_body_force(...)
function (defined in the namespace Global_Physical_Variables
) as the argument.
Now problem 1 can be solved as in the previous example.
To solve problem 2 we set the entries in the NavierStokesEquations<2>::Gamma
vector to zero (thus choosing the simplified version of the Navier-Stokes equations), define , and pass a function pointer to the body_force(...)
function to the problem constructor.
Problem 2 may then be solved as before.
The problem class is very similar to that used in the previous example , with two exceptions:
We store the function pointer to the body force function in the private data member Body_force_fct_pt
.
As usual the first task is to create the mesh. We now use the RefineableQuarterCircleSectorMesh<ELEMENT>
, which requires the creation of a GeomObject
to describe geometry of the curved wall: We choose an ellipse with unit half axes (i.e. a unit circle).
Next the error estimator is set, the boundary nodes are pinned and the Reynolds number is assigned, as before .
Within this loop we also pass the pointers to , the gravity vector and the body-force function to the elements.
The RefineableQuarterCircleSectorMesh<ELEMENT>
contains only three elements and therefore provides a very coarse discretisation of the domain. We refine the mesh uniformly twice before pinning the redundant pressure degrees of freedom, pinning a single pressure degree of freedom, and assigning the equation numbers, as before.
The post processing function remains the same as in the previous examples .
Problem::actions_before_newton_solve()
. The figure below shows what you should expect.]A pdf version of this document is available.