Toggle navigation
Documentation
Big picture
The finite element method
The data structure
Not-so-quick guide
Optimisation
Order of action functions
Example codes and tutorials
List of example codes and tutorials
Meshing
Solvers
MPI parallel processing
Post-processing/visualisation
Other
Change log
Creating documentation
Coding conventions
Index
FAQ
About
People
Contact/Get involved
Publications
Acknowledgements
Copyright
Picture show
Go
demo_drivers
navier_stokes
circular_driven_cavity
circular_driven_cavity.cc
Go to the documentation of this file.
1
//LIC// ====================================================================
2
//LIC// This file forms part of oomph-lib, the object-oriented,
3
//LIC// multi-physics finite-element library, available
4
//LIC// at http://www.oomph-lib.org.
5
//LIC//
6
//LIC// Copyright (C) 2006-2025 Matthias Heil and Andrew Hazel
7
//LIC//
8
//LIC// This library is free software; you can redistribute it and/or
9
//LIC// modify it under the terms of the GNU Lesser General Public
10
//LIC// License as published by the Free Software Foundation; either
11
//LIC// version 2.1 of the License, or (at your option) any later version.
12
//LIC//
13
//LIC// This library is distributed in the hope that it will be useful,
14
//LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15
//LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
//LIC// Lesser General Public License for more details.
17
//LIC//
18
//LIC// You should have received a copy of the GNU Lesser General Public
19
//LIC// License along with this library; if not, write to the Free Software
20
//LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21
//LIC// 02110-1301 USA.
22
//LIC//
23
//LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24
//LIC//
25
//LIC//====================================================================
26
// Driver for adaptive 2D quarter circle driven cavity. Solved with black
27
// box adaptation, using Taylor Hood and Crouzeix Raviart elements.
28
29
// Generic oomph-lib header
30
#include "generic.h"
31
32
// Navier Stokes headers
33
#include "navier_stokes.h"
34
35
// The mesh
36
#include "meshes/quarter_circle_sector_mesh.h"
37
38
using namespace
std;
39
40
using namespace
oomph;
41
42
43
//==start_of_namespace===================================================
44
/// Namespace for physical parameters
45
//=======================================================================
46
namespace
Global_Physical_Variables
47
{
48
/// Reynolds number
49
double
Re
=100;
50
51
/// Reynolds/Froude number
52
double
Re_invFr
=100;
53
54
/// Gravity vector
55
Vector<double>
Gravity
(2);
56
57
/// Functional body force
58
void
body_force
(
const
double
& time,
const
Vector<double>& x,
59
Vector<double>& result)
60
{
61
result[0]=0.0;
62
result[1]=-
Re_invFr
;
63
}
64
65
/// Zero functional body force
66
void
zero_body_force
(
const
double
& time,
const
Vector<double>& x,
67
Vector<double>& result)
68
{
69
result[0]=0.0;
70
result[1]=0.0;
71
}
72
73
}
// end_of_namespace
74
75
//////////////////////////////////////////////////////////////////////
76
//////////////////////////////////////////////////////////////////////
77
//////////////////////////////////////////////////////////////////////
78
79
//==start_of_problem_class============================================
80
/// Driven cavity problem in quarter circle domain, templated
81
/// by element type.
82
//====================================================================
83
template
<
class
ELEMENT>
84
class
QuarterCircleDrivenCavityProblem
:
public
Problem
85
{
86
87
public
:
88
89
/// Constructor
90
QuarterCircleDrivenCavityProblem
(
91
NavierStokesEquations<2>::NavierStokesBodyForceFctPt body_force_fct_pt);
92
93
/// Destructor: Empty
94
~QuarterCircleDrivenCavityProblem
() {}
95
96
/// Update the after solve (empty)
97
void
actions_after_newton_solve
() {}
98
99
/// Update the problem specs before solve.
100
/// (Re-)set velocity boundary conditions just to be on the safe side...
101
void
actions_before_newton_solve
()
102
{
103
// Setup tangential flow along boundary 0:
104
unsigned
ibound=0;
105
unsigned
num_nod= mesh_pt()->nboundary_node(ibound);
106
for
(
unsigned
inod=0;inod<num_nod;inod++)
107
{
108
// Tangential flow
109
unsigned
i=0;
110
mesh_pt()->boundary_node_pt(ibound,inod)->set_value(i,1.0);
111
// No penetration
112
i=1;
113
mesh_pt()->boundary_node_pt(ibound,inod)->set_value(i,0.0);
114
}
115
116
// Overwrite with no flow along all other boundaries
117
unsigned
num_bound = mesh_pt()->nboundary();
118
for
(
unsigned
ibound=1;ibound<num_bound;ibound++)
119
{
120
unsigned
num_nod= mesh_pt()->nboundary_node(ibound);
121
for
(
unsigned
inod=0;inod<num_nod;inod++)
122
{
123
for
(
unsigned
i=0;i<2;i++)
124
{
125
mesh_pt()->boundary_node_pt(ibound,inod)->set_value(i,0.0);
126
}
127
}
128
}
129
}
// end_of_actions_before_newton_solve
130
131
132
/// After adaptation: Unpin pressure and pin redudant pressure dofs.
133
void
actions_after_adapt
()
134
{
135
// Unpin all pressure dofs
136
RefineableNavierStokesEquations<2>::
137
unpin_all_pressure_dofs(mesh_pt()->element_pt());
138
139
// Pin redundant pressure dofs
140
RefineableNavierStokesEquations<2>::
141
pin_redundant_nodal_pressures(mesh_pt()->element_pt());
142
143
// Now pin the first pressure dof in the first element and set it to 0.0
144
fix_pressure
(0,0,0.0);
145
}
// end_of_actions_after_adapt
146
147
/// Doc the solution
148
void
doc_solution
(DocInfo& doc_info);
149
150
private
:
151
152
/// Pointer to body force function
153
NavierStokesEquations<2>::NavierStokesBodyForceFctPt
Body_force_fct_pt
;
154
155
/// Fix pressure in element e at pressure dof pdof and set to pvalue
156
void
fix_pressure
(
const
unsigned
&e,
const
unsigned
&pdof,
157
const
double
&pvalue)
158
{
159
//Cast to proper element and fix pressure
160
dynamic_cast<
ELEMENT*
>
(mesh_pt()->element_pt(e))->
161
fix_pressure
(pdof,pvalue);
162
}
// end_of_fix_pressure
163
164
};
// end_of_problem_class
165
166
167
168
//==start_of_constructor==================================================
169
/// Constructor for driven cavity problem in quarter circle domain
170
//========================================================================
171
template
<
class
ELEMENT>
172
QuarterCircleDrivenCavityProblem<ELEMENT>::QuarterCircleDrivenCavityProblem
(
173
NavierStokesEquations<2>::NavierStokesBodyForceFctPt body_force_fct_pt) :
174
Body_force_fct_pt(body_force_fct_pt)
175
{
176
177
// Build geometric object that parametrises the curved boundary
178
// of the domain
179
180
// Half axes for ellipse
181
double
a_ellipse=1.0;
182
double
b_ellipse=1.0;
183
184
// Setup elliptical ring
185
GeomObject* Wall_pt=
new
Ellipse(a_ellipse,b_ellipse);
186
187
// End points for wall
188
double
xi_lo=0.0;
189
double
xi_hi=2.0*atan(1.0);
190
191
//Now create the mesh
192
double
fract_mid=0.5;
193
Problem::mesh_pt() =
new
194
RefineableQuarterCircleSectorMesh<ELEMENT>(
195
Wall_pt,xi_lo,fract_mid,xi_hi);
196
197
// Set error estimator
198
Z2ErrorEstimator* error_estimator_pt=
new
Z2ErrorEstimator;
199
dynamic_cast<
RefineableQuarterCircleSectorMesh<ELEMENT>*
>
(
200
mesh_pt())->spatial_error_estimator_pt()=error_estimator_pt;
201
202
// Set the boundary conditions for this problem: All nodes are
203
// free by default -- just pin the ones that have Dirichlet conditions
204
// here: All boundaries are Dirichlet boundaries.
205
unsigned
num_bound = mesh_pt()->nboundary();
206
for
(
unsigned
ibound=0;ibound<num_bound;ibound++)
207
{
208
unsigned
num_nod= mesh_pt()->nboundary_node(ibound);
209
for
(
unsigned
inod=0;inod<num_nod;inod++)
210
{
211
// Loop over values (u and v velocities)
212
for
(
unsigned
i=0;i<2;i++)
213
{
214
mesh_pt()->boundary_node_pt(ibound,inod)->pin(i);
215
}
216
}
217
}
// end loop over boundaries
218
219
//Find number of elements in mesh
220
unsigned
n_element = mesh_pt()->nelement();
221
222
// Loop over the elements to set up element-specific
223
// things that cannot be handled by constructor: Pass pointer to Reynolds
224
// number
225
for
(
unsigned
e=0;e<n_element;e++)
226
{
227
// Upcast from GeneralisedElement to the present element
228
ELEMENT* el_pt =
dynamic_cast<
ELEMENT*
>
(mesh_pt()->element_pt(e));
229
230
//Set the Reynolds number, etc
231
el_pt->re_pt() = &
Global_Physical_Variables::Re
;
232
//Set the Re/Fr
233
el_pt->re_invfr_pt() = &
Global_Physical_Variables::Re_invFr
;
234
//Set Gravity vector
235
el_pt->g_pt() = &
Global_Physical_Variables::Gravity
;
236
//set body force function
237
el_pt->body_force_fct_pt() =
Body_force_fct_pt
;
238
239
}
// end loop over elements
240
241
// Initial refinement level
242
refine_uniformly();
243
refine_uniformly();
244
245
// Pin redudant pressure dofs
246
RefineableNavierStokesEquations<2>::
247
pin_redundant_nodal_pressures(mesh_pt()->element_pt());
248
249
// Now pin the first pressure dof in the first element and set it to 0.0
250
fix_pressure
(0,0,0.0);
251
252
// Setup equation numbering scheme
253
cout <<
"Number of equations: "
<< assign_eqn_numbers() << std::endl;
254
255
}
// end_of_constructor
256
257
258
259
//==start_of_doc_solution=================================================
260
/// Doc the solution
261
//========================================================================
262
template
<
class
ELEMENT>
263
void
QuarterCircleDrivenCavityProblem<ELEMENT>::doc_solution
(DocInfo& doc_info)
264
{
265
266
ofstream some_file;
267
char
filename[100];
268
269
// Number of plot points
270
unsigned
npts=5;
271
272
273
// Output solution
274
snprintf(filename,
sizeof
(filename),
"%s/soln%i.dat"
,doc_info.directory().c_str(),
275
doc_info.number());
276
some_file.open(filename);
277
mesh_pt()->output(some_file,npts);
278
some_file.close();
279
280
}
// end_of_doc_solution
281
282
283
284
285
//==start_of_main======================================================
286
/// Driver for QuarterCircleDrivenCavityProblem test problem
287
//=====================================================================
288
int
main
()
289
{
290
291
// Set output directory and initialise count
292
DocInfo doc_info;
293
doc_info.set_directory(
"RESLT"
);
294
295
// Set max. number of black-box adaptation
296
unsigned
max_adapt=3;
297
298
// Solve problem 1 with Taylor-Hood elements
299
//--------------------------------------------
300
{
301
// Set up downwards-Gravity vector
302
Global_Physical_Variables::Gravity
[0] = 0.0;
303
Global_Physical_Variables::Gravity
[1] = -1.0;
304
305
// Set up Gamma vector for stress-divergence form
306
NavierStokesEquations<2>::Gamma[0]=1;
307
NavierStokesEquations<2>::Gamma[1]=1;
308
309
// Build problem with Gravity vector in stress divergence form,
310
// using zero body force function
311
QuarterCircleDrivenCavityProblem<RefineableQTaylorHoodElement<2>
>
312
problem(&
Global_Physical_Variables::zero_body_force
);
313
314
// Solve the problem with automatic adaptation
315
problem.newton_solve(max_adapt);
316
317
// Step number
318
doc_info.number()=0;
319
320
// Output solution
321
problem.
doc_solution
(doc_info);
322
323
}
// end of problem 1
324
325
326
327
// Solve problem 2 with Taylor Hood elements
328
//--------------------------------------------
329
{
330
// Set up zero-Gravity vector
331
Global_Physical_Variables::Gravity
[0] = 0.0;
332
Global_Physical_Variables::Gravity
[1] = 0.0;
333
334
// Set up Gamma vector for simplified form
335
NavierStokesEquations<2>::Gamma[0]=0;
336
NavierStokesEquations<2>::Gamma[1]=0;
337
338
// Build problem with body force function and simplified form,
339
// using body force function
340
QuarterCircleDrivenCavityProblem<RefineableQTaylorHoodElement<2>
>
341
problem(&
Global_Physical_Variables::body_force
);
342
343
// Solve the problem with automatic adaptation
344
problem.newton_solve(max_adapt);
345
346
// Step number
347
doc_info.number()=1;
348
349
// Output solution
350
problem.
doc_solution
(doc_info);
351
352
}
// end of problem 2
353
354
}
// end_of_main
355
356
main
int main()
Driver for QuarterCircleDrivenCavityProblem test problem.
Definition
circular_driven_cavity.cc:288
QuarterCircleDrivenCavityProblem
Driven cavity problem in quarter circle domain, templated by element type.
Definition
circular_driven_cavity.cc:85
QuarterCircleDrivenCavityProblem::~QuarterCircleDrivenCavityProblem
~QuarterCircleDrivenCavityProblem()
Destructor: Empty.
Definition
circular_driven_cavity.cc:94
QuarterCircleDrivenCavityProblem::fix_pressure
void fix_pressure(const unsigned &e, const unsigned &pdof, const double &pvalue)
Fix pressure in element e at pressure dof pdof and set to pvalue.
Definition
circular_driven_cavity.cc:156
QuarterCircleDrivenCavityProblem::doc_solution
void doc_solution(DocInfo &doc_info)
Doc the solution.
Definition
circular_driven_cavity.cc:263
QuarterCircleDrivenCavityProblem::actions_after_adapt
void actions_after_adapt()
After adaptation: Unpin pressure and pin redudant pressure dofs.
Definition
circular_driven_cavity.cc:133
QuarterCircleDrivenCavityProblem::Body_force_fct_pt
NavierStokesEquations< 2 >::NavierStokesBodyForceFctPt Body_force_fct_pt
Pointer to body force function.
Definition
circular_driven_cavity.cc:153
QuarterCircleDrivenCavityProblem::actions_before_newton_solve
void actions_before_newton_solve()
Update the problem specs before solve. (Re-)set velocity boundary conditions just to be on the safe s...
Definition
circular_driven_cavity.cc:101
QuarterCircleDrivenCavityProblem::actions_after_newton_solve
void actions_after_newton_solve()
Update the after solve (empty)
Definition
circular_driven_cavity.cc:97
QuarterCircleDrivenCavityProblem::QuarterCircleDrivenCavityProblem
QuarterCircleDrivenCavityProblem(NavierStokesEquations< 2 >::NavierStokesBodyForceFctPt body_force_fct_pt)
Constructor.
Definition
circular_driven_cavity.cc:172
Global_Physical_Variables
Namespace for physical parameters.
Definition
circular_driven_cavity.cc:47
Global_Physical_Variables::body_force
void body_force(const double &time, const Vector< double > &x, Vector< double > &result)
Functional body force.
Definition
circular_driven_cavity.cc:58
Global_Physical_Variables::Gravity
Vector< double > Gravity(2)
Gravity vector.
Global_Physical_Variables::zero_body_force
void zero_body_force(const double &time, const Vector< double > &x, Vector< double > &result)
Zero functional body force.
Definition
circular_driven_cavity.cc:66
Global_Physical_Variables::Re_invFr
double Re_invFr
Reynolds/Froude number.
Definition
circular_driven_cavity.cc:52
Global_Physical_Variables::Re
double Re
Reynolds number.
Definition
circular_driven_cavity.cc:49