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