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_cavity2.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_Variables2
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
QuarterCircleDrivenCavityProblem2
:
public
Problem
85
{
86
87
public
:
88
89
/// Constructor
90
QuarterCircleDrivenCavityProblem2
(
91
NavierStokesEquations<2>::NavierStokesBodyForceFctPt body_force_fct_pt);
92
93
/// Destructor: Empty
94
~QuarterCircleDrivenCavityProblem2
() {}
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 1:
104
unsigned
ibound=1;
105
unsigned
num_nod= mesh_pt()->nboundary_node(ibound);
106
for
(
unsigned
inod=0;inod<num_nod;inod++)
107
{
108
// get coordinates
109
double
x=mesh_pt()->boundary_node_pt(ibound,inod)->x(0);
110
double
y=mesh_pt()->boundary_node_pt(ibound,inod)->x(1);
111
// find Lagrangian coordinate (the angle)
112
double
zeta=0.0;
113
if
(x!=0.0)
114
{
115
zeta=atan(y/x);
116
}
117
// Tangential flow u0
118
unsigned
i=0;
119
mesh_pt()->boundary_node_pt(ibound,inod)->set_value(i,-sin(zeta));
120
// Tangential flow u1
121
i=1;
122
mesh_pt()->boundary_node_pt(ibound,inod)->set_value(i,cos(zeta));
123
}
124
125
// Overwrite with no flow along all boundaries
126
unsigned
num_bound = mesh_pt()->nboundary();
127
for
(
unsigned
ibound=0;ibound<num_bound;ibound++)
128
{
129
if
(ibound!=1)
130
{
131
unsigned
num_nod= mesh_pt()->nboundary_node(ibound);
132
for
(
unsigned
inod=0;inod<num_nod;inod++)
133
{
134
for
(
unsigned
i=0;i<2;i++)
135
{
136
mesh_pt()->boundary_node_pt(ibound,inod)->set_value(i,0.0);
137
}
138
}
139
}
140
}
141
142
}
// end_of_actions_before_newton_solve
143
144
145
/// After adaptation: Unpin pressure and pin redudant pressure dofs.
146
void
actions_after_adapt
()
147
{
148
// Unpin all pressure dofs
149
RefineableNavierStokesEquations<2>::
150
unpin_all_pressure_dofs(mesh_pt()->element_pt());
151
152
// Pin redundant pressure dofs
153
RefineableNavierStokesEquations<2>::
154
pin_redundant_nodal_pressures(mesh_pt()->element_pt());
155
156
// Now pin the first pressure dof in the first element and set it to 0.0
157
fix_pressure
(0,0,0.0);
158
}
// end_of_actions_after_adapt
159
160
/// Doc the solution
161
void
doc_solution
(DocInfo& doc_info);
162
163
private
:
164
165
/// Pointer to body force function
166
NavierStokesEquations<2>::NavierStokesBodyForceFctPt
Body_force_fct_pt
;
167
168
/// Fix pressure in element e at pressure dof pdof and set to pvalue
169
void
fix_pressure
(
const
unsigned
&e,
const
unsigned
&pdof,
170
const
double
&pvalue)
171
{
172
//Cast to proper element and fix pressure
173
dynamic_cast<
ELEMENT*
>
(mesh_pt()->element_pt(e))->
174
fix_pressure
(pdof,pvalue);
175
}
// end_of_fix_pressure
176
177
};
// end_of_problem_class
178
179
180
181
//==start_of_constructor==================================================
182
/// Constructor for driven cavity problem in quarter circle domain
183
//========================================================================
184
template
<
class
ELEMENT>
185
QuarterCircleDrivenCavityProblem2<ELEMENT>::QuarterCircleDrivenCavityProblem2
(
186
NavierStokesEquations<2>::NavierStokesBodyForceFctPt body_force_fct_pt) :
187
Body_force_fct_pt(body_force_fct_pt)
188
{
189
190
// Build geometric object that parametrises the curved boundary
191
// of the domain
192
193
// Half axes for ellipse
194
double
a_ellipse=1.0;
195
double
b_ellipse=1.0;
196
197
// Setup elliptical ring
198
GeomObject* Wall_pt=
new
Ellipse(a_ellipse,b_ellipse);
199
200
// End points for wall
201
double
xi_lo=0.0;
202
double
xi_hi=2.0*atan(1.0);
203
204
//Now create the mesh
205
double
fract_mid=0.5;
206
Problem::mesh_pt() =
new
207
RefineableQuarterCircleSectorMesh<ELEMENT>(
208
Wall_pt,xi_lo,fract_mid,xi_hi);
209
210
// Set error estimator
211
Z2ErrorEstimator* error_estimator_pt=
new
Z2ErrorEstimator;
212
dynamic_cast<
RefineableQuarterCircleSectorMesh<ELEMENT>*
>
(
213
mesh_pt())->spatial_error_estimator_pt()=error_estimator_pt;
214
215
// Set the boundary conditions for this problem: All nodes are
216
// free by default -- just pin the ones that have Dirichlet conditions
217
// here: All boundaries are Dirichlet boundaries.
218
unsigned
num_bound = mesh_pt()->nboundary();
219
for
(
unsigned
ibound=0;ibound<num_bound;ibound++)
220
{
221
unsigned
num_nod= mesh_pt()->nboundary_node(ibound);
222
for
(
unsigned
inod=0;inod<num_nod;inod++)
223
{
224
// Loop over values (u and v velocities)
225
for
(
unsigned
i=0;i<2;i++)
226
{
227
mesh_pt()->boundary_node_pt(ibound,inod)->pin(i);
228
}
229
}
230
}
// end loop over boundaries
231
232
//Find number of elements in mesh
233
unsigned
n_element = mesh_pt()->nelement();
234
235
// Loop over the elements to set up element-specific
236
// things that cannot be handled by constructor: Pass pointer to Reynolds
237
// number
238
for
(
unsigned
e=0;e<n_element;e++)
239
{
240
// Upcast from GeneralisedElement to the present element
241
ELEMENT* el_pt =
dynamic_cast<
ELEMENT*
>
(mesh_pt()->element_pt(e));
242
243
//Set the Reynolds number, etc
244
el_pt->re_pt() = &
Global_Physical_Variables2::Re
;
245
//Set the Re/Fr
246
el_pt->re_invfr_pt() = &
Global_Physical_Variables2::Re_invFr
;
247
//Set Gravity vector
248
el_pt->g_pt() = &
Global_Physical_Variables2::Gravity
;
249
//set body force function
250
el_pt->body_force_fct_pt() =
Body_force_fct_pt
;
251
252
}
// end loop over elements
253
254
// Initial refinement level
255
refine_uniformly();
256
refine_uniformly();
257
258
// Pin redudant pressure dofs
259
RefineableNavierStokesEquations<2>::
260
pin_redundant_nodal_pressures(mesh_pt()->element_pt());
261
262
// Now pin the first pressure dof in the first element and set it to 0.0
263
fix_pressure
(0,0,0.0);
264
265
// Setup equation numbering scheme
266
cout <<
"Number of equations: "
<< assign_eqn_numbers() << std::endl;
267
268
}
// end_of_constructor
269
270
271
272
//==start_of_doc_solution=================================================
273
/// Doc the solution
274
//========================================================================
275
template
<
class
ELEMENT>
276
void
QuarterCircleDrivenCavityProblem2<ELEMENT>::doc_solution
(DocInfo& doc_info)
277
{
278
279
ofstream some_file;
280
char
filename[100];
281
282
// Number of plot points
283
unsigned
npts=5;
284
285
286
// Output solution
287
snprintf(filename,
sizeof
(filename),
"%s/soln%i.dat"
,doc_info.directory().c_str(),
288
doc_info.number());
289
some_file.open(filename);
290
mesh_pt()->output(some_file,npts);
291
some_file.close();
292
293
}
// end_of_doc_solution
294
295
296
297
298
//==start_of_main======================================================
299
/// Driver for QuarterCircleDrivenCavityProblem2 test problem
300
//=====================================================================
301
int
main
()
302
{
303
304
// Set output directory and initialise count
305
DocInfo doc_info;
306
doc_info.set_directory(
"RESLT2"
);
307
308
// Set max. number of black-box adaptation
309
unsigned
max_adapt=3;
310
311
// Solve problem 1 with Taylor-Hood elements
312
//--------------------------------------------
313
{
314
// Set up downwards-Gravity vector
315
Global_Physical_Variables2::Gravity
[0] = 0.0;
316
Global_Physical_Variables2::Gravity
[1] = -1.0;
317
318
// Set up Gamma vector for stress-divergence form
319
NavierStokesEquations<2>::Gamma[0]=1;
320
NavierStokesEquations<2>::Gamma[1]=1;
321
322
// Build problem with Gravity vector in stress divergence form,
323
// using zero body force function
324
QuarterCircleDrivenCavityProblem2<RefineableQTaylorHoodElement<2>
>
325
problem(&
Global_Physical_Variables2::zero_body_force
);
326
327
// Solve the problem with automatic adaptation
328
problem.newton_solve(max_adapt);
329
330
// Step number
331
doc_info.number()=0;
332
333
// Output solution
334
problem.
doc_solution
(doc_info);
335
336
}
// end of problem 1
337
338
339
340
// Solve problem 2 with Taylor Hood elements
341
//--------------------------------------------
342
{
343
// Set up zero-Gravity vector
344
Global_Physical_Variables2::Gravity
[0] = 0.0;
345
Global_Physical_Variables2::Gravity
[1] = 0.0;
346
347
// Set up Gamma vector for simplified form
348
NavierStokesEquations<2>::Gamma[0]=0;
349
NavierStokesEquations<2>::Gamma[1]=0;
350
351
// Build problem with body force function and simplified form,
352
// using body force function
353
QuarterCircleDrivenCavityProblem2<RefineableQTaylorHoodElement<2>
>
354
problem(&
Global_Physical_Variables2::body_force
);
355
356
// Solve the problem with automatic adaptation
357
problem.newton_solve(max_adapt);
358
359
// Step number
360
doc_info.number()=1;
361
362
// Output solution
363
problem.
doc_solution
(doc_info);
364
365
}
// end of problem 2
366
367
}
// end_of_main
368
369
main
int main()
Driver for QuarterCircleDrivenCavityProblem2 test problem.
Definition
circular_driven_cavity2.cc:301
QuarterCircleDrivenCavityProblem2
Driven cavity problem in quarter circle domain, templated by element type.
Definition
circular_driven_cavity2.cc:85
QuarterCircleDrivenCavityProblem2::actions_after_newton_solve
void actions_after_newton_solve()
Update the after solve (empty)
Definition
circular_driven_cavity2.cc:97
QuarterCircleDrivenCavityProblem2::QuarterCircleDrivenCavityProblem2
QuarterCircleDrivenCavityProblem2(NavierStokesEquations< 2 >::NavierStokesBodyForceFctPt body_force_fct_pt)
Constructor.
Definition
circular_driven_cavity2.cc:185
QuarterCircleDrivenCavityProblem2::doc_solution
void doc_solution(DocInfo &doc_info)
Doc the solution.
Definition
circular_driven_cavity2.cc:276
QuarterCircleDrivenCavityProblem2::actions_after_adapt
void actions_after_adapt()
After adaptation: Unpin pressure and pin redudant pressure dofs.
Definition
circular_driven_cavity2.cc:146
QuarterCircleDrivenCavityProblem2::Body_force_fct_pt
NavierStokesEquations< 2 >::NavierStokesBodyForceFctPt Body_force_fct_pt
Pointer to body force function.
Definition
circular_driven_cavity2.cc:166
QuarterCircleDrivenCavityProblem2::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_cavity2.cc:169
QuarterCircleDrivenCavityProblem2::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_cavity2.cc:101
QuarterCircleDrivenCavityProblem2::~QuarterCircleDrivenCavityProblem2
~QuarterCircleDrivenCavityProblem2()
Destructor: Empty.
Definition
circular_driven_cavity2.cc:94
Global_Physical_Variables2
Namespace for physical parameters.
Definition
circular_driven_cavity2.cc:47
Global_Physical_Variables2::Re_invFr
double Re_invFr
Reynolds/Froude number.
Definition
circular_driven_cavity2.cc:52
Global_Physical_Variables2::zero_body_force
void zero_body_force(const double &time, const Vector< double > &x, Vector< double > &result)
Zero functional body force.
Definition
circular_driven_cavity2.cc:66
Global_Physical_Variables2::Gravity
Vector< double > Gravity(2)
Gravity vector.
Global_Physical_Variables2::body_force
void body_force(const double &time, const Vector< double > &x, Vector< double > &result)
Functional body force.
Definition
circular_driven_cavity2.cc:58
Global_Physical_Variables2::Re
double Re
Reynolds number.
Definition
circular_driven_cavity2.cc:49