three_d_entry_flow.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 entry flow problem in quarter tube domain
27 
28 //Generic routines
29 #include "generic.h"
30 #include "navier_stokes.h"
31 
32 // The mesh
33 #include "meshes/quarter_tube_mesh.h"
34 
35 using namespace std;
36 
37 using namespace oomph;
38 
39 //=start_of_namespace================================================
40 /// Namespace for physical parameters
41 //===================================================================
43 {
44  /// Reynolds number
45  double Re=100;
46 } // end_of_namespace
47 
48 
49 //=start_of_problem_class=============================================
50 /// Entry flow problem in quarter tube domain
51 //====================================================================
52 template<class ELEMENT>
53 class EntryFlowProblem : public Problem
54 {
55 
56 public:
57 
58  /// Constructor: Pass DocInfo object and target errors
59  EntryFlowProblem(DocInfo& doc_info, const double& min_error_target,
60  const double& max_error_target);
61 
62  /// Destructor (empty)
64 
65  /// Doc the solution after solve
67  {
68  // Doc solution after solving
69  doc_solution();
70 
71  // Increment label for output files
72  Doc_info.number()++;
73  }
74 
75  /// Update the problem specs before solve
76  void actions_before_newton_solve();
77 
78  /// After adaptation: Pin redudant pressure dofs.
80  {
81  // Pin redudant pressure dofs
82  RefineableNavierStokesEquations<3>::
83  pin_redundant_nodal_pressures(mesh_pt()->element_pt());
84  }
85 
86  /// Doc the solution
87  void doc_solution();
88 
89  /// Overload generic access function by one that returns
90  /// a pointer to the specific mesh
91  RefineableQuarterTubeMesh<ELEMENT>* mesh_pt()
92  {
93  return dynamic_cast<RefineableQuarterTubeMesh<ELEMENT>*>(Problem::mesh_pt());
94  }
95 
96 private:
97 
98  /// Exponent for bluntness of velocity profile
99  int Alpha;
100 
101  /// Doc info object
102  DocInfo Doc_info;
103 
104 }; // end_of_problem_class
105 
106 
107 
108 
109 //=start_of_constructor===================================================
110 /// Constructor: Pass DocInfo object and error targets
111 //========================================================================
112 template<class ELEMENT>
114  const double& min_error_target,
115  const double& max_error_target)
116  : Doc_info(doc_info)
117 {
118 
119  // Setup mesh:
120  //------------
121 
122  // Create geometric objects: Elliptical tube with half axes = radius = 1.0
123  double radius=1.0;
124  GeomObject* Wall_pt=new EllipticalTube(radius,radius);
125 
126  // Boundaries on object
127  Vector<double> xi_lo(2);
128  // height of inflow
129  xi_lo[0]=0.0;
130  // start of Wall_pt
131  xi_lo[1]=0.0;
132 
133  Vector<double> xi_hi(2);
134  // height of outflow
135  xi_hi[0]=7.0;
136  // end of Wall_pt
137  xi_hi[1]=2.0*atan(1.0);
138 
139  // # of layers
140  unsigned nlayer=6;
141 
142  //Radial divider is located half-way along the circumference
143  double frac_mid=0.5;
144 
145  // Build and assign mesh
146  Problem::mesh_pt()=
147  new RefineableQuarterTubeMesh<ELEMENT>(Wall_pt,xi_lo,frac_mid,xi_hi,nlayer);
148 
149 
150  // Set error estimator
151  Z2ErrorEstimator* error_estimator_pt=new Z2ErrorEstimator;
152  mesh_pt()->spatial_error_estimator_pt()=error_estimator_pt;
153 
154  // Error targets for adaptive refinement
155  mesh_pt()->max_permitted_error()=max_error_target;
156  mesh_pt()->min_permitted_error()=min_error_target;
157 
158 
159 
160  //Doc the boundaries
161  ofstream some_file;
162  char filename[100];
163  sprintf(filename,"boundaries.dat");
164  some_file.open(filename);
165  mesh_pt()->output_boundaries(some_file);
166  some_file.close();
167 
168 
169  // Set the boundary conditions for this problem: All nodal values are
170  // free by default -- just pin the ones that have Dirichlet conditions
171  // here.
172  unsigned num_bound = mesh_pt()->nboundary();
173  for(unsigned ibound=0;ibound<num_bound;ibound++)
174  {
175  unsigned num_nod= mesh_pt()->nboundary_node(ibound);
176  for (unsigned inod=0;inod<num_nod;inod++)
177  {
178  // Boundary 1 is the vertical symmetry boundary: We allow flow in
179  //the y-direction. Elsewhere, pin the y velocity
180  if(ibound!=1) mesh_pt()->boundary_node_pt(ibound,inod)->pin(1);
181 
182  // Boundary 2 is the horizontal symmetry boundary: We allow flow in
183  //the x-direction. Elsewhere, pin the x velocity
184  if(ibound!=2) mesh_pt()->boundary_node_pt(ibound,inod)->pin(0);
185 
186  // Boundaries 0 and 3 are the inflow and the wall respectively.
187  // Pin the axial velocity because of the prescribed inflow
188  // profile and the no slip on the stationary wall, respectively
189  if((ibound==0) || (ibound==3))
190  {
191  mesh_pt()->boundary_node_pt(ibound,inod)->pin(2);
192  }
193  }
194  } // end loop over boundaries
195 
196  // Loop over the elements to set up element-specific
197  // things that cannot be handled by constructor
198  unsigned n_element = mesh_pt()->nelement();
199  for(unsigned i=0;i<n_element;i++)
200  {
201  // Upcast from GeneralisedElement to the present element
202  ELEMENT* el_pt = dynamic_cast<ELEMENT*>(mesh_pt()->element_pt(i));
203 
204  //Set the Reynolds number, etc
205  el_pt->re_pt() = &Global_Physical_Variables::Re;
206  }
207 
208  // Pin redudant pressure dofs
209  RefineableNavierStokesEquations<3>::
210  pin_redundant_nodal_pressures(mesh_pt()->element_pt());
211 
212  // Set Poiseuille flow as initial for solution
213  // Inflow will be overwritten in actions_before_newton_solve()
214  unsigned n_nod=mesh_pt()->nnode();
215  for (unsigned j=0;j<n_nod;j++)
216  {
217  Node* node_pt=mesh_pt()->node_pt(j);
218  // Recover coordinates
219  double x=node_pt->x(0);
220  double y=node_pt->x(1);
221  double r=sqrt(x*x+y*y );
222 
223  // Poiseuille flow
224  node_pt->set_value(0,0.0);
225  node_pt->set_value(1,0.0);
226  node_pt->set_value(2,(1.0-r*r));
227  }
228 
229  // Set the exponent for bluntness: Alpha=2 --> Poisseuille; anything
230  // larger makes the inflow blunter
231  Alpha=20;
232 
233  //Attach the boundary conditions to the mesh
234  cout <<"Number of equations: " << assign_eqn_numbers() << std::endl;
235 
236 } // end_of_constructor
237 
238 
239 //=start_of_actions_before_newton_solve==========================================
240 /// Set the inflow boundary conditions
241 //========================================================================
242 template<class ELEMENT>
244 {
245 
246  // (Re-)assign velocity profile at inflow values
247  //--------------------------------------------
248 
249  // Setup bluntish parallel inflow on boundary 0:
250  unsigned ibound=0;
251  unsigned num_nod= mesh_pt()->nboundary_node(ibound);
252  for (unsigned inod=0;inod<num_nod;inod++)
253  {
254  // Recover coordinates
255  double x=mesh_pt()->boundary_node_pt(ibound,inod)->x(0);
256  double y=mesh_pt()->boundary_node_pt(ibound,inod)->x(1);
257  double r=sqrt(x*x+y*y);
258 
259  // Bluntish profile for axial velocity (component 2)
260  mesh_pt()->boundary_node_pt(ibound,inod)->
261  set_value(2,(1.0-pow(r,Alpha)));
262  }
263 
264 } // end_of_actions_before_newton_solve
265 
266 
267 //=start_of_doc_solution==================================================
268 /// Doc the solution
269 //========================================================================
270 template<class ELEMENT>
272 {
273 
274  ofstream some_file;
275  char filename[100];
276 
277  // Number of plot points
278  unsigned npts;
279  npts=5;
280 
281  // Output solution
282  sprintf(filename,"%s/soln%i.dat",Doc_info.directory().c_str(),
283  Doc_info.number());
284  some_file.open(filename);
285  mesh_pt()->output(some_file,npts);
286  some_file.close();
287 
288 } // end_of_doc_solution
289 
290 
291 
292 
293 /// /////////////////////////////////////////////////////////////////////
294 /// /////////////////////////////////////////////////////////////////////
295 /// /////////////////////////////////////////////////////////////////////
296 
297 
298 //=start_of_main=======================================================
299 /// Driver for 3D entry flow into a quarter tube. If there are
300 /// any command line arguments, we regard this as a validation run
301 /// and perform only a single adaptation
302 //=====================================================================
303 int main(int argc, char* argv[])
304 {
305 
306  // Store command line arguments
307  CommandLineArgs::setup(argc,argv);
308 
309  // Allow (up to) five rounds of fully automatic adapation in response to
310  //-----------------------------------------------------------------------
311  // error estimate
312  //---------------
313  unsigned max_adapt;
314  double max_error_target,min_error_target;
315 
316  // Set max number of adaptations in black-box Newton solver and
317  // error targets for adaptation
318  if (CommandLineArgs::Argc==1)
319  {
320  // Up to five adaptations
321  max_adapt=5;
322 
323  // Error targets for adaptive refinement
324  max_error_target=0.005;
325  min_error_target=0.0005;
326  }
327  // Validation run: Only one adaptation. Relax error targets
328  // to ensure that not all elements are refined so we're getting
329  // some hanging nodes.
330  else
331  {
332  // Validation run: Just one round of adaptation
333  max_adapt=1;
334 
335  // Error targets for adaptive refinement
336  max_error_target=0.02;
337  min_error_target=0.002;
338  }
339  // end max_adapt setup
340 
341 
342  // Set up doc info
343  DocInfo doc_info;
344 
345  // Do Taylor-Hood elements
346  //------------------------
347  {
348  // Set output directory
349  doc_info.set_directory("RESLT_TH");
350 
351  // Step number
352  doc_info.number()=0;
353 
354  // Build problem
356  problem(doc_info,min_error_target,max_error_target);
357 
358  cout << " Doing Taylor-Hood elements " << std::endl;
359 
360 
361  // Doc solution after solving
362  problem.doc_solution();
363 
364  // Solve the problem
365  problem.newton_solve(max_adapt);
366  }
367 
368 
369  // Do Crouzeix-Raviart elements
370  //-----------------------------
371  {
372  // Set output directory
373  doc_info.set_directory("RESLT_CR");
374 
375  // Step number
376  doc_info.number()=0;
377 
378  // Build problem
380  problem(doc_info,min_error_target,max_error_target);
381 
382  cout << " Doing Crouzeix-Raviart elements " << std::endl;
383 
384  // Solve the problem
385  problem.newton_solve(max_adapt);
386  }
387 
388 } // end_of_main
389 
390 
Entry flow problem in quarter tube domain.
void actions_after_newton_solve()
Doc the solution after solve.
EntryFlowProblem(DocInfo &doc_info, const double &min_error_target, const double &max_error_target)
Constructor: Pass DocInfo object and target errors.
~EntryFlowProblem()
Destructor (empty)
RefineableQuarterTubeMesh< ELEMENT > * mesh_pt()
Overload generic access function by one that returns a pointer to the specific mesh.
int Alpha
Exponent for bluntness of velocity profile.
void doc_solution()
Doc the solution.
DocInfo Doc_info
Doc info object.
void actions_after_adapt()
After adaptation: Pin redudant pressure dofs.
void actions_before_newton_solve()
Update the problem specs before solve.
Namespace for physical parameters.
Definition: full_tube.cc:83
double Re
Reynolds number.
Definition: full_tube.cc:85
int main(int argc, char *argv[])
///////////////////////////////////////////////////////////////////// ///////////////////////////////...