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