Example problem: 2D driven cavity flow in a quarter-circle domain with spatial adaptation.
In this example we shall demonstrate
how easy it is to adapt the code for the solution of the driven cavity problem in a square domain, discussed in a previous example , to a different domain shape,
how to apply body forces (e.g. gravity) in a Navier-Stokes problem,
how to switch between the stress-divergence and the simplified forms of the incompressible Navier-Stokes equations.
The example problem
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.
Problem 1:
The 2D driven cavity problem in a quarter circle domain with gravity,
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:
Problem 2:
The 2D driven cavity problem in a quarter circle domain with gravity,
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.
Switching between the stress-divergence and the simplified forms of the Navier-Stokes equations
The two forms of the Navier-Stokes equations differ in the implementation of the viscous terms, which may be represented as
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.]
Solution to problem 1
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.
Plot of the velocity and pressure fields for problem 1 with Re=100 and Re/Fr=100, computed with adaptive Taylor-Hood elements.
Solution to problem 2
The next figure shows the computational results for Problem 2, obtained from a computation with adaptive Crouzeix-Raviart elements.
Plot of the velocity and pressure fields for problem 2 with Re=100 and Re/Fr=100, computed with adaptive Crouzeix-Raviart elements.
the gravity vector , and the ratio of Reynolds and Froude number, , which represents the ratio of gravitational and viscous forces,
/// Reynolds/Froude number
double Re_invFr=100;
/// Gravity vector
Vector<double> Gravity(2);
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 )
/// Functional body force
void body_force(constdouble& time, const Vector<double>& x,
Vector<double>& result)
{
result[0]=0.0;
result[1]=-Re_invFr;
}
Finally we define a body force function, which returns zero values, for use when solving Problem 1.
/// Zero functional body force
void zero_body_force(constdouble& time, const Vector<double>& x,
Vector<double>& result)
{
result[0]=0.0;
result[1]=0.0;
}
} // end_of_namespace
The driver code
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.
// Build problem with Gravity vector in stress divergence form,
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.
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).
{
// Build geometric object that parametrises the curved boundary
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.
Try making the curved boundary the driving wall [Hint: this requires a change in the wall velocities prescribed in Problem::actions_before_newton_solve(). The figure below shows what you should expect.]
Plot of the velocity and pressure distribution for a circular driven cavity in which the flow is driven by the tangential motion of the curvilinear boundary.
Source files for this tutorial
The source files for this tutorial are located in the directory: