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