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