unstructured_three_d_fluid.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 code for a simple unstructured fluid problem using a mesh
27 // generated from an input file generated by the 3d mesh generator
28 // tetgen
29 
30 
31 //Generic routines
32 #include "generic.h"
33 #include "constitutive.h"
34 #include "navier_stokes.h"
35 
36 // Get the mesh
37 #include "meshes/tetgen_mesh.h"
38 
39 using namespace std;
40 using namespace oomph;
41 
42 
43 /// ///////////////////////////////////////////////////////////////
44 /// ///////////////////////////////////////////////////////////////
45 /// ///////////////////////////////////////////////////////////////
46 
47 
48 //=======start_namespace==========================================
49 /// Global variables
50 //================================================================
52 {
53 
54  /// Default Reynolds number
55  double Re=100.0;
56 
57  /// Fluid pressure on inflow boundary
58  double P_in=0.5;
59 
60  /// Applied traction on fluid at the inflow boundary
61  void prescribed_inflow_traction(const double& t,
62  const Vector<double>& x,
63  const Vector<double>& n,
64  Vector<double>& traction)
65  {
66  traction[0]=0.0;
67  traction[1]=0.0;
68  traction[2]=P_in;
69  }
70 
71 
72  /// Fluid pressure on outflow boundary
73  double P_out=-0.5;
74 
75  /// Applied traction on fluid at the inflow boundary
76  void prescribed_outflow_traction(const double& t,
77  const Vector<double>& x,
78  const Vector<double>& n,
79  Vector<double>& traction)
80  {
81  traction[0]=0.0;
82  traction[1]=0.0;
83  traction[2]=-P_out;
84  }
85 
86 } //end namespace
87 
88 
89 
90 
91 
92 
93 //======start_problem_class===========================================
94 /// Unstructured fluid problem
95 //====================================================================
96 template<class ELEMENT>
97 class UnstructuredFluidProblem : public Problem
98 {
99 
100 public:
101 
102  /// Constructor:
104 
105  /// Destructor (empty)
107 
108  /// Doc the solution
109  void doc_solution(DocInfo& doc_info);
110 
111  /// Return total number of fluid inflow traction boundaries
113  {
114  return Inflow_boundary_id.size();
115  }
116 
117  /// Return total number of fluid outflow traction boundaries
119  {
120  return Outflow_boundary_id.size();
121  }
122 
123  /// Return total number of fluid outflow traction boundaries
125  {
126  return Inflow_boundary_id.size()+Outflow_boundary_id.size();
127  }
128 
129  //private:
130 
131  /// Create fluid traction elements at inflow
132  void create_fluid_traction_elements();
133 
134  /// Bulk fluid mesh
135  TetgenMesh<ELEMENT>* Fluid_mesh_pt;
136 
137  /// Meshes of fluid traction elements that apply pressure at in/outflow
138  Vector<Mesh*> Fluid_traction_mesh_pt;
139 
140  /// IDs of fluid mesh boundaries along which inflow boundary conditions
141  /// are applied
142  Vector<unsigned> Inflow_boundary_id;
143 
144  /// IDs of fluid mesh boundaries along which inflow boundary conditions
145  /// are applied
146  Vector<unsigned> Outflow_boundary_id;
147 
148 };
149 
150 
151 
152 //==========start_constructor=============================================
153 /// Constructor for unstructured 3D fluid problem
154 //========================================================================
155 template<class ELEMENT>
157 {
158 
159  //Create fluid bulk mesh, sub-dividing "corner" elements
160  string node_file_name="fsi_bifurcation_fluid.1.node";
161  string element_file_name="fsi_bifurcation_fluid.1.ele";
162  string face_file_name="fsi_bifurcation_fluid.1.face";
163  bool split_corner_elements=true;
164  Fluid_mesh_pt = new TetgenMesh<ELEMENT>(node_file_name,
165  element_file_name,
166  face_file_name,
167  split_corner_elements);
168 
169  // Find elements next to boundaries
170  //Fluid_mesh_pt->setup_boundary_element_info();
171 
172  // The following corresponds to the boundaries as specified by
173  // facets in the tetgen input:
174 
175  // Fluid mesh has one inflow boundary: Boundary 0
176  Inflow_boundary_id.resize(1);
177  Inflow_boundary_id[0]=0;
178 
179  // Fluid mesh has two outflow boundaries: Boundaries 1 and 2
180  Outflow_boundary_id.resize(2);
181  Outflow_boundary_id[0]=1;
182  Outflow_boundary_id[1]=2;
183 
184  // Apply BCs
185  //----------
186 
187  // Map to indicate which boundary has been done
188  std::map<unsigned,bool> done;
189 
190  // Loop over inflow/outflow boundaries to impose parallel flow
191  for (unsigned in_out=0;in_out<2;in_out++)
192  {
193  // Loop over in/outflow boundaries
194  unsigned n=nfluid_inflow_traction_boundary();
195  if (in_out==1) n=nfluid_outflow_traction_boundary();
196  for (unsigned i=0;i<n;i++)
197  {
198  // Get boundary ID
199  unsigned b=0;
200  if (in_out==0)
201  {
202  b=Inflow_boundary_id[i];
203  }
204  else
205  {
206  b=Outflow_boundary_id[i];
207  }
208 
209  // Number of nodes on that boundary
210  unsigned num_nod=Fluid_mesh_pt->nboundary_node(b);
211  for (unsigned inod=0;inod<num_nod;inod++)
212  {
213  // Get the node
214  Node* nod_pt=Fluid_mesh_pt->boundary_node_pt(b,inod);
215 
216  // Pin transverse velocities
217  nod_pt->pin(0);
218  nod_pt->pin(1);
219  }
220 
221  // Done!
222  done[b]=true;
223  }
224 
225  } // done in and outflow
226 
227 
228 
229  // Loop over all fluid mesh boundaries and pin velocities
230  // of nodes that haven't been dealt with yet
231  unsigned nbound=Fluid_mesh_pt->nboundary();
232  for(unsigned b=0;b<nbound;b++)
233  {
234 
235  // Has the boundary been done yet?
236  if (!done[b])
237  {
238  unsigned num_nod=Fluid_mesh_pt->nboundary_node(b);
239  for (unsigned inod=0;inod<num_nod;inod++)
240  {
241  // Get node
242  Node* nod_pt= Fluid_mesh_pt->boundary_node_pt(b,inod);
243 
244  // Pin all velocities
245  nod_pt->pin(0);
246  nod_pt->pin(1);
247  nod_pt->pin(2);
248  }
249  }
250 
251  } // done no slip elsewhere
252 
253 
254  // Complete the build of the fluid elements so they are fully functional
255  //----------------------------------------------------------------------
256  unsigned n_element = Fluid_mesh_pt->nelement();
257  for(unsigned e=0;e<n_element;e++)
258  {
259 
260  // Upcast from GeneralisedElement to the present element
261  ELEMENT* el_pt = dynamic_cast<ELEMENT*>(Fluid_mesh_pt->element_pt(e));
262 
263  //Set the Reynolds number
264  el_pt->re_pt() = &Global_Parameters::Re;
265 
266  }
267 
268 
269  // Create meshes of fluid traction elements at inflow/outflow
270  //-----------------------------------------------------------
271 
272  // Create the meshes
273  unsigned n=nfluid_traction_boundary();
274  Fluid_traction_mesh_pt.resize(n);
275  for (unsigned i=0;i<n;i++)
276  {
277  Fluid_traction_mesh_pt[i]=new Mesh;
278  }
279 
280  // Populate them with elements
281  create_fluid_traction_elements();
282 
283 
284  // Combine the lot
285  //----------------
286 
287  // Add sub meshes:
288 
289  // Fluid bulk mesh
290  add_sub_mesh(Fluid_mesh_pt);
291 
292  // The fluid traction meshes
293  n=nfluid_traction_boundary();
294  for (unsigned i=0;i<n;i++)
295  {
296  add_sub_mesh(Fluid_traction_mesh_pt[i]);
297  }
298 
299  // Build global mesh
300  build_global_mesh();
301 
302  // Setup equation numbering scheme
303  std::cout <<"Number of equations: " << assign_eqn_numbers() << std::endl;
304 
305 } // end constructor
306 
307 
308 
309 //============start_of_fluid_traction_elements==============================
310 /// Create fluid traction elements
311 //=======================================================================
312 template<class ELEMENT>
314 {
315 
316  // Counter for number of fluid traction meshes
317  unsigned count=0;
318 
319  // Loop over inflow/outflow boundaries
320  for (unsigned in_out=0;in_out<2;in_out++)
321  {
322  // Loop over boundaries with fluid traction elements
323  unsigned n=nfluid_inflow_traction_boundary();
324  if (in_out==1) n=nfluid_outflow_traction_boundary();
325  for (unsigned i=0;i<n;i++)
326  {
327  // Get boundary ID
328  unsigned b=0;
329  if (in_out==0)
330  {
331  b=Inflow_boundary_id[i];
332  }
333  else
334  {
335  b=Outflow_boundary_id[i];
336  }
337 
338  // How many bulk elements are adjacent to boundary b?
339  unsigned n_element = Fluid_mesh_pt->nboundary_element(b);
340 
341  // Loop over the bulk elements adjacent to boundary b
342  for(unsigned e=0;e<n_element;e++)
343  {
344  // Get pointer to the bulk element that is adjacent to boundary b
345  ELEMENT* bulk_elem_pt = dynamic_cast<ELEMENT*>(
346  Fluid_mesh_pt->boundary_element_pt(b,e));
347 
348  //What is the index of the face of the element e along boundary b
349  int face_index = Fluid_mesh_pt->face_index_at_boundary(b,e);
350 
351  // Create new element
352  NavierStokesTractionElement<ELEMENT>* el_pt=
353  new NavierStokesTractionElement<ELEMENT>(bulk_elem_pt,
354  face_index);
355 
356  // Add it to the mesh
357  Fluid_traction_mesh_pt[count]->add_element_pt(el_pt);
358 
359  // Set the pointer to the prescribed traction function
360  if (in_out==0)
361  {
362  el_pt->traction_fct_pt() =
364  }
365  else
366  {
367  el_pt->traction_fct_pt() =
369  }
370  }
371  // Bump up counter
372  count++;
373  }
374  }
375 
376  } // end of create_traction_elements
377 
378 
379 
380 //========================================================================
381 /// Doc the solution
382 //========================================================================
383 template<class ELEMENT>
385 {
386 
387  ofstream some_file;
388  char filename[100];
389 
390  // Number of plot points
391  unsigned npts;
392  npts=5;
393 
394 
395  // Output fluid solution
396  sprintf(filename,"%s/fluid_soln%i.dat",doc_info.directory().c_str(),
397  doc_info.number());
398  some_file.open(filename);
399  Fluid_mesh_pt->output(some_file,npts);
400  some_file.close();
401 
402 }
403 
404 
405 
406 
407 
408 //=============start_main=================================================
409 /// Demonstrate how to solve an unstructured 3D fluids problem
410 //========================================================================
411 int main(int argc, char **argv)
412 {
413  // Store command line arguments
414  CommandLineArgs::setup(argc,argv);
415 
416  // Label for output
417  DocInfo doc_info;
418 
419  // Parameter study
420  double Re_increment=100.0;
421  unsigned nstep=4;
422  if (CommandLineArgs::Argc==2)
423  {
424  std::cout << "Validation -- only doing two steps" << std::endl;
425  nstep=2;
426  }
427 
428 
429  //Taylor--Hood
430  {
431  // Output directory
432  doc_info.set_directory("RESLT_TH");
433 
434  //Set up the problem
436 
437  //Output initial guess
438  problem.doc_solution(doc_info);
439  doc_info.number()++;
440 
441  // Parameter study: Crank up the pressure drop along the vessel
442  for (unsigned istep=0;istep<nstep;istep++)
443  {
444  // Solve the problem
445  problem.newton_solve();
446 
447  //Output solution
448  problem.doc_solution(doc_info);
449  doc_info.number()++;
450 
451  // Bump up Reynolds number (equivalent to increasing the imposed pressure
452  // drop)
453  Global_Parameters::Re+=Re_increment;
454  }
455  }
456 
457  //Crouzeix Raviart
458  {
459  //Reset to default Reynolds number
460  Global_Parameters::Re = 100.0;
461 
462  //Reset doc info number
463  doc_info.number()=0;
464 
465  // Output directory
466  doc_info.set_directory("RESLT_CR");
467 
468  //Set up the problem
470 
471  //Output initial guess
472  problem.doc_solution(doc_info);
473  doc_info.number()++;
474 
475  // Parameter study: Crank up the pressure drop along the vessel
476  for (unsigned istep=0;istep<nstep;istep++)
477  {
478  // Solve the problem
479  problem.newton_solve();
480 
481  //Output solution
482  problem.doc_solution(doc_info);
483  doc_info.number()++;
484 
485  // Bump up Reynolds number (equivalent to increasing the imposed pressure
486  // drop)
487  Global_Parameters::Re+=Re_increment;
488  }
489  }
490 
491 } // end_of_main
492 
493 
494 
495 
Unstructured fluid problem.
Vector< unsigned > Inflow_boundary_id
IDs of fluid mesh boundaries along which inflow boundary conditions are applied.
~UnstructuredFluidProblem()
Destructor (empty)
unsigned nfluid_inflow_traction_boundary()
Return total number of fluid inflow traction boundaries.
Vector< unsigned > Outflow_boundary_id
IDs of fluid mesh boundaries along which inflow boundary conditions are applied.
unsigned nfluid_outflow_traction_boundary()
Return total number of fluid outflow traction boundaries.
void doc_solution(DocInfo &doc_info)
Doc the solution.
Vector< Mesh * > Fluid_traction_mesh_pt
Meshes of fluid traction elements that apply pressure at in/outflow.
TetgenMesh< ELEMENT > * Fluid_mesh_pt
Bulk fluid mesh.
unsigned nfluid_traction_boundary()
Return total number of fluid outflow traction boundaries.
void create_fluid_traction_elements()
Create fluid traction elements at inflow.
/////////////////////////////////////////////////////////////// /////////////////////////////////////...
double P_in
Fluid pressure on inflow boundary.
void prescribed_outflow_traction(const double &t, const Vector< double > &x, const Vector< double > &n, Vector< double > &traction)
Applied traction on fluid at the inflow boundary.
double Re
Default Reynolds number.
double P_out
Fluid pressure on outflow boundary.
void prescribed_inflow_traction(const double &t, const Vector< double > &x, const Vector< double > &n, Vector< double > &traction)
Applied traction on fluid at the inflow boundary.
int main(int argc, char **argv)
Demonstrate how to solve an unstructured 3D fluids problem.