full_tube.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
27/// complete straight 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
36using namespace std;
37
38using namespace oomph;
39
40
41//=start_of_MyCylinder===================================
42//A geometric object that represents the geometry of the domain
43//================================================================
44class MyCylinder : public GeomObject
45{
46public:
47
48 /// Constructor that takes the radius of the tube as its argument
49 MyCylinder(const double &radius) :
50 GeomObject(3,3), Radius(radius) { }
51
52/// Destructor
53virtual~MyCylinder(){}
54
55/// Lagrangian coordinate xi
56void position (const Vector<double>& xi, Vector<double>& r) const
57{
58 r[0] = xi[2]*Radius*cos(xi[1]);
59 r[1] = xi[0];
60 r[2] = -xi[2]*Radius*sin(xi[1]);
61}
62
63
64/// Return the position of the tube as a function of time
65/// (doesn't move as a function of time)
66void position(const unsigned& t,
67 const Vector<double>& xi, Vector<double>& r) const
68 {
69 position(xi,r);
70 }
71
72private:
73
74 /// Storage for the radius of the tube
75 double Radius;
76
77};
78
79//=start_of_namespace================================================
80/// Namespace for physical parameters
81//===================================================================
83{
84 /// Reynolds number
85 double Re=25;
86
87} // end_of_namespace
88
89
90//=start_of_problem_class=============================================
91/// Entry flow problem in tapered tube domain
92//====================================================================
93template<class ELEMENT>
94class SteadyTubeProblem : public Problem
95{
96
97public:
98
99 /// Constructor: Pass DocInfo object and target errors
100 SteadyTubeProblem(DocInfo& doc_info, const double& min_error_target,
101 const double& max_error_target);
102
103 /// Destructor (empty)
105
106 /// Update the problem specs before solve
108
109 /// After adaptation: Pin redudant pressure dofs.
111 {
112 // Pin redudant pressure dofs
113 RefineableNavierStokesEquations<3>::
114 pin_redundant_nodal_pressures(mesh_pt()->element_pt());
115 }
116
117 /// Doc the solution
118 void doc_solution();
119
120 /// Overload generic access function by one that returns
121 /// a pointer to the specific mesh
122 RefineableTubeMesh<ELEMENT>* mesh_pt()
123 {
124 return dynamic_cast<RefineableTubeMesh<ELEMENT>*>(Problem::mesh_pt());
125 }
126
127private:
128
129 /// Doc info object
130 DocInfo Doc_info;
131
132 /// Pointer to GeomObject that specifies the domain volume
133 GeomObject *Volume_pt;
134
135}; // end_of_problem_class
136
137
138
139
140//=start_of_constructor===================================================
141/// Constructor: Pass DocInfo object and error targets
142//========================================================================
143template<class ELEMENT>
145 const double& min_error_target,
146 const double& max_error_target)
147 : Doc_info(doc_info)
148{
149
150 // Setup mesh:
151 //------------
152
153 // Create GeomObject that specifies the domain geometry
154 //The radius of the tube is one
155 Volume_pt=new MyCylinder(1.0);
156
157 //Define pi
158 const double pi = MathematicalConstants::Pi;
159
160 //Set the centerline coordinates spanning the mesh
161 //Tube is on length pi
162 Vector<double> centreline_limits(2);
163 centreline_limits[0] = 0.0;
164 centreline_limits[1] = pi;
165
166 //Set the positions of the angles that divide the outer ring
167 //These must be in the range -pi,pi, ordered from smallest to
168 //largest
169 Vector<double> theta_positions(4);
170 theta_positions[0] = -0.75*pi;
171 theta_positions[1] = -0.25*pi;
172 theta_positions[2] = 0.25*pi;
173 theta_positions[3] = 0.75*pi;
174
175 //Define the radial fraction of the central box (always halfway
176 //along the radius)
177 Vector<double> radial_frac(4,0.5);
178
179 // Number of layers in the initial mesh
180 unsigned nlayer=6;
181
182 // Build and assign mesh
183 Problem::mesh_pt()= new RefineableTubeMesh<ELEMENT>(Volume_pt,
184 centreline_limits,
185 theta_positions,
186 radial_frac,
187 nlayer);
188
189 // Set error estimator
190 Z2ErrorEstimator* error_estimator_pt=new Z2ErrorEstimator;
191 mesh_pt()->spatial_error_estimator_pt()=error_estimator_pt;
192
193 // Error targets for adaptive refinement
194 mesh_pt()->max_permitted_error()=max_error_target;
195 mesh_pt()->min_permitted_error()=min_error_target;
196
197 // Set the boundary conditions for this problem: All nodal values are
198 // free by default -- just pin the ones that have Dirichlet conditions
199 // here.
200 //Choose the conventional form by setting gamma to zero
201 //The boundary conditions will be pseudo-traction free (d/dn = 0)
202 ELEMENT::Gamma[0] = 0.0;
203 ELEMENT::Gamma[1] = 0.0;
204 ELEMENT::Gamma[2] = 0.0;
205
206 //Loop over the boundaries
207 unsigned num_bound = mesh_pt()->nboundary();
208 for(unsigned ibound=0;ibound<num_bound;ibound++)
209 {
210 unsigned num_nod= mesh_pt()->nboundary_node(ibound);
211 for (unsigned inod=0;inod<num_nod;inod++)
212 {
213 // Boundary 0 is the inlet symmetry boundary:
214 // Boundary 1 is the tube wall
215 // Pin all values
216 if((ibound==0) || (ibound==1))
217 {
218 mesh_pt()->boundary_node_pt(ibound,inod)->pin(0);
219 mesh_pt()->boundary_node_pt(ibound,inod)->pin(1);
220 mesh_pt()->boundary_node_pt(ibound,inod)->pin(2);
221 }
222 }
223 } // end loop over boundaries
224
225 // Loop over the elements to set up element-specific
226 // things that cannot be handled by constructor
227 unsigned n_element = mesh_pt()->nelement();
228 for(unsigned i=0;i<n_element;i++)
229 {
230 // Upcast from GeneralisedElement to the present element
231 ELEMENT* el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(i));
232
233 //Set the Reynolds number, etc
234 el_pt->re_pt() = &Global_Physical_Variables::Re;
235 }
236
237 // Pin redudant pressure dofs
238 RefineableNavierStokesEquations<3>::
239 pin_redundant_nodal_pressures(mesh_pt()->element_pt());
240
241 //Attach the boundary conditions to the mesh
242 cout <<"Number of equations: " << assign_eqn_numbers() << std::endl;
243
244} // end_of_constructor
245
246
247//=start_of_actions_before_newton_solve===================================
248/// Set the inflow boundary conditions
249//========================================================================
250template<class ELEMENT>
252{
253
254 // (Re-)assign velocity profile at inflow values
255 //--------------------------------------------
256 unsigned ibound=0;
257 unsigned num_nod= mesh_pt()->nboundary_node(ibound);
258 for (unsigned inod=0;inod<num_nod;inod++)
259 {
260 // Recover coordinates of tube relative to centre position
261 double x=mesh_pt()->boundary_node_pt(ibound,inod)->x(0);
262 double z=mesh_pt()->boundary_node_pt(ibound,inod)->x(2);
263 //Calculate the radius
264 double r=sqrt(x*x+z*z);
265
266 // Blunt profile for axial velocity (component 1 at the inlet)
267 mesh_pt()->boundary_node_pt(ibound,inod)->
268 set_value(1,(1.0-pow(r,10.0)));
269 }
270
271} // end_of_actions_before_newton_solve
272
273
274//=start_of_doc_solution==================================================
275/// Doc the solution
276//========================================================================
277template<class ELEMENT>
279{
280 //Output file stream
281 ofstream some_file;
282 char filename[100];
283
284 // Number of plot points
285 unsigned npts;
286 npts=5;
287
288 //Need high precision for large radii of curvature
289 //some_file.precision(10);
290 // Output solution labelled by the Reynolds number
291 snprintf(filename, sizeof(filename), "%s/soln_Re%g.dat",Doc_info.directory().c_str(),
293 some_file.open(filename);
294 mesh_pt()->output(some_file,npts);
295 some_file.close();
296
297} // end_of_doc_solution
298
299
300
301
302////////////////////////////////////////////////////////////////////////
303////////////////////////////////////////////////////////////////////////
304////////////////////////////////////////////////////////////////////////
305
306
307//=start_of_main=======================================================
308/// Driver for 3D entry flow into a straight tube.
309//=====================================================================
310int main(int argc, char* argv[])
311{
312 //The purpose of this code is to test that the position of nodes on
313 //curvilinear boundaries are correctly updated after nodes that were
314 //hanging become non-hanging.
315 unsigned max_adapt=1;
316 double max_error_target=0.02 , min_error_target=0.002;
317
318
319 // Set up doc info
320 DocInfo doc_info;
321
322 // Do Taylor-Hood elements
323 //------------------------
324 {
325 // Set output directory
326 doc_info.set_directory("RESLT_TH");
327
328 // Step number
329 doc_info.number()=0;
330
331 // Build problem
333 problem(doc_info,min_error_target,max_error_target);
334
335 cout << " Doing Taylor-Hood elements " << std::endl;
336
337 for(unsigned i=0;i<2;i++)
338 {
339 // Solve the problem
340 problem.newton_solve(max_adapt);
341 // Doc solution after solving
342 problem.doc_solution();
343
345 ++doc_info.number();
346 }
347 }
348
349 exit(1);
350 // Do Crouzeix-Raviart elements
351 //------------------------
352 {
353 // Set output directory
354 doc_info.set_directory("RESLT_CR");
355
356 // Step number
357 doc_info.number()=0;
358
359 // Build problem
361 problem(doc_info,min_error_target,max_error_target);
362
363 cout << " Doing Crouzeix-Raviart elements " << std::endl;
364
365 for(unsigned i=0;i<2;i++)
366 {
367 // Solve the problem
368 problem.newton_solve(max_adapt);
369 // Doc solution after solving
370 problem.doc_solution();
371
373 ++doc_info.number();
374 }
375 }
376} // end_of_main
377
378
double Radius
Storage for the radius of the tube.
Definition full_tube.cc:75
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 full_tube.cc:66
MyCylinder(const double &radius)
Constructor that takes the radius of the tube as its argument.
Definition full_tube.cc:49
virtual ~MyCylinder()
Destructor.
Definition full_tube.cc:53
void position(const Vector< double > &xi, Vector< double > &r) const
Lagrangian coordinate xi.
Definition full_tube.cc:56
Entry flow problem in tapered tube domain.
Definition full_tube.cc:95
RefineableTubeMesh< ELEMENT > * mesh_pt()
Overload generic access function by one that returns a pointer to the specific mesh.
Definition full_tube.cc:122
~SteadyTubeProblem()
Destructor (empty)
Definition full_tube.cc:104
DocInfo Doc_info
Doc info object.
Definition full_tube.cc:130
SteadyTubeProblem(DocInfo &doc_info, const double &min_error_target, const double &max_error_target)
Constructor: Pass DocInfo object and target errors.
Definition full_tube.cc:144
void actions_before_newton_solve()
Update the problem specs before solve.
Definition full_tube.cc:251
void doc_solution()
Doc the solution.
Definition full_tube.cc:278
void actions_after_adapt()
After adaptation: Pin redudant pressure dofs.
Definition full_tube.cc:110
GeomObject * Volume_pt
Pointer to GeomObject that specifies the domain volume.
Definition full_tube.cc:133
int main(int argc, char *argv[])
Driver for 3D entry flow into a straight tube.
Definition full_tube.cc:310
Namespace for physical parameters.
Definition full_tube.cc:83
double Re
Reynolds number.
Definition full_tube.cc:85