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