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
curved_pipe
helical_pipe.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 a 3D navier stokes steady entry flow problem in a helical
27
/// tube
28
29
//Generic routines
30
#include "generic.h"
31
#include "navier_stokes.h"
32
33
// The mesh
34
#include "meshes/tube_mesh.h"
35
36
using namespace
std;
37
38
using namespace
oomph;
39
40
41
//=start_of_MyHelicalCylinder==============================================
42
/// The arguemts are the radius of the tube, its curvature in the x,y plane
43
/// and the pitch of the helix
44
//=========================================================================
45
class
MyHelicalCylinder
:
public
GeomObject
46
{
47
public
:
48
49
/// Constructor
50
MyHelicalCylinder
(
const
double
&radius,
const
double
& delta,
51
const
double
& pitch) :
52
GeomObject(3,3),
Radius
(radius),
Delta
(delta),
P
(pitch)
53
{
54
//Set the value of pi
55
Pi
= MathematicalConstants::Pi;
56
}
57
58
/// Destructor
59
virtual
~MyHelicalCylinder
(){}
60
61
/// Lagrangian coordinate xi
62
void
position
(
const
Vector<double>& xi, Vector<double>& r)
const
63
{
64
r[0] = (1.0/
Delta
)*cos(xi[0]) + xi[2]*
Radius
*cos(xi[0])*cos(xi[1]);
65
r[1] = (1.0/
Delta
)*sin(xi[0]) + xi[2]*
Radius
*sin(xi[0])*cos(xi[1]);
66
r[2] =
P
*xi[0]/(2.0*
Pi
) - xi[2]*
Radius
*sin(xi[1]);
67
}
68
69
70
/// Return the position of the tube as a function of time
71
/// (doesn't move as a function of time)
72
void
position
(
const
unsigned
& t,
73
const
Vector<double>& xi, Vector<double>& r)
const
74
{
75
position
(xi,r);
76
}
77
78
private
:
79
double
Pi
;
80
double
Radius
;
81
double
Delta
;
82
double
P
;
83
};
84
85
//=start_of_namespace================================================
86
/// Namespace for physical parameters
87
//===================================================================
88
namespace
Global_Physical_Variables
89
{
90
/// Reynolds number
91
double
Re
=50;
92
93
double
Delta
=0.5;
94
double
Pitch
= 1.0;
95
}
// end_of_namespace
96
97
98
//=start_of_problem_class=============================================
99
/// Entry flow problem in tapered tube domain
100
//====================================================================
101
template
<
class
ELEMENT>
102
class
SteadyHelicalProblem
:
public
Problem
103
{
104
105
public
:
106
107
/// Constructor: Pass DocInfo object and target errors
108
SteadyHelicalProblem
(DocInfo& doc_info,
const
double
& min_error_target,
109
const
double
& max_error_target);
110
111
/// Destructor (empty)
112
~SteadyHelicalProblem
() {}
113
114
/// Update the problem specs before solve
115
void
actions_before_newton_solve
();
116
117
/// After adaptation: Pin redudant pressure dofs.
118
void
actions_after_adapt
()
119
{
120
// Pin redudant pressure dofs
121
RefineableNavierStokesEquations<3>::
122
pin_redundant_nodal_pressures(
mesh_pt
()->element_pt());
123
}
124
125
/// Doc the solution
126
void
doc_solution
();
127
128
/// Overload generic access function by one that returns
129
/// a pointer to the specific mesh
130
RefineableTubeMesh<ELEMENT>*
mesh_pt
()
131
{
132
return
dynamic_cast<
RefineableTubeMesh<ELEMENT>*
>
(Problem::mesh_pt());
133
}
134
135
private
:
136
137
/// Exponent for bluntness of velocity profile
138
int
Alpha
;
139
140
/// Doc info object
141
DocInfo
Doc_info
;
142
143
/// Pointer to GeomObject that specifies the domain boundary
144
GeomObject*
Wall_pt
;
145
146
};
// end_of_problem_class
147
148
149
150
151
//=start_of_constructor===================================================
152
/// Constructor: Pass DocInfo object and error targets
153
//========================================================================
154
template
<
class
ELEMENT>
155
SteadyHelicalProblem<ELEMENT>::SteadyHelicalProblem
(DocInfo& doc_info,
156
const
double
& min_error_target,
157
const
double
& max_error_target)
158
: Doc_info(doc_info)
159
{
160
//Increase the value of the maximum residuals so that the first
161
//newton step converges.
162
Max_residuals = 100.0;
163
164
// Setup mesh:
165
//------------
166
167
//Build geometric object that forms the domain boundary: a tapered curved tube
168
double
d=
Global_Physical_Variables::Delta
;
169
double
p=
Global_Physical_Variables::Pitch
;
170
171
// Create GeomObject that specifies the domain boundary
172
Wall_pt
=
new
MyHelicalCylinder
(1.0,d,p);
173
174
//Define pi
175
const
double
pi = MathematicalConstants::Pi;
176
177
178
//Set the centerline coordinates for the start and end of the helix
179
Vector<double> centreline_limits(2);
180
centreline_limits[0] = 0.0;
181
centreline_limits[1] = pi;
182
183
//Set the positions of the angles that divide the outer ring of elements
184
Vector<double> theta_positions(4);
185
theta_positions[0] = -0.75*pi;
186
theta_positions[1] = -0.25*pi;
187
theta_positions[2] = 0.25*pi;
188
theta_positions[3] = 0.75*pi;
189
190
//Define the radial fraction for the central box in the domain
191
Vector<double> radial_frac(4,0.5);
192
193
// Number of layers in the mesh
194
unsigned
nlayer=6;
195
196
// Build and assign mesh
197
Problem::mesh_pt()=
198
new
RefineableTubeMesh<ELEMENT>(
Wall_pt
,
199
centreline_limits,
200
theta_positions,
201
radial_frac,
202
nlayer);
203
204
// Set error estimator
205
Z2ErrorEstimator* error_estimator_pt=
new
Z2ErrorEstimator;
206
mesh_pt
()->spatial_error_estimator_pt()=error_estimator_pt;
207
208
// Error targets for adaptive refinement
209
mesh_pt
()->max_permitted_error()=max_error_target;
210
mesh_pt
()->min_permitted_error()=min_error_target;
211
212
// Set the boundary conditions for this problem: All nodal values are
213
// free by default -- just pin the ones that have Dirichlet conditions
214
// here.
215
//Choose the conventional form by setting gamma to zero
216
//The boundary conditions will be pseudo-traction free (d/dn = 0)
217
ELEMENT::Gamma[0] = 0.0;
218
ELEMENT::Gamma[1] = 0.0;
219
ELEMENT::Gamma[2] = 0.0;
220
221
unsigned
num_bound =
mesh_pt
()->nboundary();
222
for
(
unsigned
ibound=0;ibound<num_bound;ibound++)
223
{
224
unsigned
num_nod=
mesh_pt
()->nboundary_node(ibound);
225
for
(
unsigned
inod=0;inod<num_nod;inod++)
226
{
227
// Boundary 0 is the inlet symmetry boundary:
228
// Boundary 1 is the tube wall
229
// Pin all values
230
if
((ibound==0) || (ibound==1))
231
{
232
mesh_pt
()->boundary_node_pt(ibound,inod)->pin(0);
233
mesh_pt
()->boundary_node_pt(ibound,inod)->pin(1);
234
mesh_pt
()->boundary_node_pt(ibound,inod)->pin(2);
235
}
236
237
//Boundary 2 is the outflow boundary, pin z,
238
//leave traction free
239
if
(ibound==2)
240
{
241
//mesh_pt()->boundary_node_pt(ibound,inod)->pin(2);
242
}
243
}
244
}
// end loop over boundaries
245
246
// Loop over the elements to set up element-specific
247
// things that cannot be handled by constructor
248
unsigned
n_element =
mesh_pt
()->nelement();
249
for
(
unsigned
i=0;i<n_element;i++)
250
{
251
// Upcast from GeneralisedElement to the present element
252
ELEMENT* el_pt =
dynamic_cast<
ELEMENT*
>
(
mesh_pt
()->element_pt(i));
253
254
//Set the Reynolds number, etc
255
el_pt->re_pt() = &
Global_Physical_Variables::Re
;
256
}
257
258
// Pin redudant pressure dofs
259
RefineableNavierStokesEquations<3>::
260
pin_redundant_nodal_pressures(
mesh_pt
()->element_pt());
261
262
//Attach the boundary conditions to the mesh
263
cout <<
"Number of equations: "
<< assign_eqn_numbers() << std::endl;
264
265
}
// end_of_constructor
266
267
268
//=start_of_actions_before_newton_solve==========================================
269
/// Set the inflow boundary conditions
270
//========================================================================
271
template
<
class
ELEMENT>
272
void
SteadyHelicalProblem<ELEMENT>::actions_before_newton_solve
()
273
{
274
275
// (Re-)assign velocity profile at inflow values
276
//--------------------------------------------
277
unsigned
ibound=0;
278
unsigned
num_nod= mesh_pt()->nboundary_node(ibound);
279
for
(
unsigned
inod=0;inod<num_nod;inod++)
280
{
281
// Recover coordinates
282
double
x=mesh_pt()->boundary_node_pt(ibound,inod)->x(0) -
283
1.0/
Global_Physical_Variables::Delta
;
284
double
z=mesh_pt()->boundary_node_pt(ibound,inod)->x(2);
285
double
r=sqrt(x*x+z*z);
286
287
// Bluntish profile for axial velocity (component 1)
288
mesh_pt()->boundary_node_pt(ibound,inod)->
289
set_value(1,(1.0-pow(r,2.0)));
290
}
291
292
}
// end_of_actions_before_newton_solve
293
294
295
//=start_of_doc_solution==================================================
296
/// Doc the solution
297
//========================================================================
298
template
<
class
ELEMENT>
299
void
SteadyHelicalProblem<ELEMENT>::doc_solution
()
300
{
301
302
ofstream some_file;
303
char
filename[100];
304
305
// Number of plot points
306
unsigned
npts;
307
npts=5;
308
309
//Need high precision for large radii of curvature
310
//some_file.precision(10);
311
// Output solution
312
snprintf(filename,
sizeof
(filename),
"%s/soln_Re%g.dat"
,Doc_info.directory().c_str(),
313
Global_Physical_Variables::Re
);
314
some_file.open(filename);
315
mesh_pt()->output(some_file,npts);
316
some_file.close();
317
318
}
// end_of_doc_solution
319
320
321
322
323
////////////////////////////////////////////////////////////////////////
324
////////////////////////////////////////////////////////////////////////
325
////////////////////////////////////////////////////////////////////////
326
327
328
//=start_of_main=======================================================
329
/// Driver for 3D entry flow into a tapered tube. If there are
330
/// any command line arguments, we regard this as a validation run
331
/// and perform only a single adaptation
332
//=====================================================================
333
int
main
(
int
argc,
char
* argv[])
334
{
335
336
// Store command line arguments
337
CommandLineArgs::setup(argc,argv);
338
339
// Allow (up to) two rounds of fully automatic adapation in response to
340
//-----------------------------------------------------------------------
341
// error estimate
342
//---------------
343
unsigned
max_adapt;
344
double
max_error_target,min_error_target;
345
346
// Set max number of adaptations in black-box Newton solver and
347
// error targets for adaptation
348
if
(CommandLineArgs::Argc==1)
349
{
350
// Up to two adaptations
351
max_adapt=2;
352
353
// Error targets for adaptive refinement
354
max_error_target=0.005;
355
min_error_target=0.0005;
356
}
357
// Validation run: Only one adaptation. Relax error targets
358
// to ensure that not all elements are refined so we're getting
359
// some hanging nodes.
360
else
361
{
362
// Validation run: Just one round of adaptation
363
max_adapt=1;
364
365
// Error targets for adaptive refinement
366
max_error_target=0.02;
367
min_error_target=0.002;
368
}
369
// end max_adapt setup
370
371
372
// Set up doc info
373
DocInfo doc_info;
374
375
// Do Taylor-Hood elements
376
//------------------------
377
{
378
// Set output directory
379
doc_info.set_directory(
"RESLT_TH"
);
380
381
// Step number
382
doc_info.number()=0;
383
384
// Build problem
385
SteadyHelicalProblem<RefineableQTaylorHoodElement<3>
>
386
problem(doc_info,min_error_target,max_error_target);
387
388
cout <<
" Doing Taylor-Hood elements "
<< std::endl;
389
390
// Solve the problem
391
problem.newton_solve(max_adapt);
392
// Doc solution after solving
393
problem.
doc_solution
();
394
}
395
396
// Do Crouzeix-Raviart elements
397
//------------------------
398
{
399
// Set output directory
400
doc_info.set_directory(
"RESLT_CR"
);
401
402
// Step number
403
doc_info.number()=0;
404
405
// Build problem
406
SteadyHelicalProblem<RefineableQCrouzeixRaviartElement<3>
>
407
problem(doc_info,min_error_target,max_error_target);
408
409
cout <<
" Doing Crouzeix-Raviart elements "
<< std::endl;
410
411
// Solve the problem
412
problem.newton_solve(max_adapt);
413
// Doc solution after solving
414
problem.
doc_solution
();
415
}
416
417
}
// end_of_main
418
419
MyHelicalCylinder
The arguemts are the radius of the tube, its curvature in the x,y plane and the pitch of the helix.
Definition
helical_pipe.cc:46
MyHelicalCylinder::Delta
double Delta
Definition
helical_pipe.cc:81
MyHelicalCylinder::Pi
double Pi
Definition
helical_pipe.cc:79
MyHelicalCylinder::MyHelicalCylinder
MyHelicalCylinder(const double &radius, const double &delta, const double &pitch)
Constructor.
Definition
helical_pipe.cc:50
MyHelicalCylinder::P
double P
Definition
helical_pipe.cc:82
MyHelicalCylinder::~MyHelicalCylinder
virtual ~MyHelicalCylinder()
Destructor.
Definition
helical_pipe.cc:59
MyHelicalCylinder::position
void position(const Vector< double > &xi, Vector< double > &r) const
Lagrangian coordinate xi.
Definition
helical_pipe.cc:62
MyHelicalCylinder::position
void position(const unsigned &t, const Vector< double > &xi, Vector< double > &r) const
Return the position of the tube as a function of time (doesn't move as a function of time)
Definition
helical_pipe.cc:72
MyHelicalCylinder::Radius
double Radius
Definition
helical_pipe.cc:80
SteadyHelicalProblem
Entry flow problem in tapered tube domain.
Definition
helical_pipe.cc:103
SteadyHelicalProblem::Doc_info
DocInfo Doc_info
Doc info object.
Definition
helical_pipe.cc:141
SteadyHelicalProblem::Wall_pt
GeomObject * Wall_pt
Pointer to GeomObject that specifies the domain boundary.
Definition
helical_pipe.cc:144
SteadyHelicalProblem::actions_before_newton_solve
void actions_before_newton_solve()
Update the problem specs before solve.
Definition
helical_pipe.cc:272
SteadyHelicalProblem::mesh_pt
RefineableTubeMesh< ELEMENT > * mesh_pt()
Overload generic access function by one that returns a pointer to the specific mesh.
Definition
helical_pipe.cc:130
SteadyHelicalProblem::actions_after_adapt
void actions_after_adapt()
After adaptation: Pin redudant pressure dofs.
Definition
helical_pipe.cc:118
SteadyHelicalProblem::SteadyHelicalProblem
SteadyHelicalProblem(DocInfo &doc_info, const double &min_error_target, const double &max_error_target)
Constructor: Pass DocInfo object and target errors.
Definition
helical_pipe.cc:155
SteadyHelicalProblem::~SteadyHelicalProblem
~SteadyHelicalProblem()
Destructor (empty)
Definition
helical_pipe.cc:112
SteadyHelicalProblem::Alpha
int Alpha
Exponent for bluntness of velocity profile.
Definition
helical_pipe.cc:138
SteadyHelicalProblem::doc_solution
void doc_solution()
Doc the solution.
Definition
helical_pipe.cc:299
main
int main(int argc, char *argv[])
Driver for 3D entry flow into a tapered tube. If there are any command line arguments,...
Definition
helical_pipe.cc:333
Global_Physical_Variables
Namespace for physical parameters.
Definition
curved_pipe.cc:86
Global_Physical_Variables::Pitch
double Pitch
Definition
helical_pipe.cc:94
Global_Physical_Variables::Re
double Re
Reynolds number.
Definition
curved_pipe.cc:88
Global_Physical_Variables::Delta
double Delta
The desired curvature of the pipe.
Definition
curved_pipe.cc:91