LifeV
navier_stokes/examples/resistanceBCs/resistance.cpp
Go to the documentation of this file.
1 /* -*- mode: c++ -*-
2 
3  This file is part of the LifeV Applications.
4 
5  Author(s): Christophe Prud'homme <christophe.prudhomme@epfl.ch>
6  Date: 2005-04-19
7 
8  Copyright (C) 2005 EPFL
9 
10  This program is free software; you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation; either version 2.1 of the License, or
13  (at your option) any later version.
14 
15  This program is distributed in the hope that it will be useful, but
16  WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with this program; if not, write to the Free Software
22  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23  USA
24 */
25 /**
26  \file cylinder.cpp
27  \author Christophe Prud'homme <christophe.prudhomme@epfl.ch>
28  \date 2005-04-19
29  */
30 
31 // Tell the compiler to ignore specific kind of warnings:
32 #pragma GCC diagnostic ignored "-Wunused-variable"
33 #pragma GCC diagnostic ignored "-Wunused-parameter"
34 
35 #include <Epetra_ConfigDefs.h>
36 #ifdef EPETRA_MPI
37 #include <mpi.h>
38 #include <Epetra_MpiComm.h>
39 #else
40 #include <Epetra_SerialComm.h>
41 #endif
42 
43 //Tell the compiler to restore the warning previously silented
44 #pragma GCC diagnostic warning "-Wunused-variable"
45 #pragma GCC diagnostic warning "-Wunused-parameter"
46 
47 //#include "life/lifesolver/NavierStokesSolver.hpp"
48 #include <lifev/core/array/MatrixEpetra.hpp>
49 #include <lifev/core/array/MapEpetra.hpp>
50 #include <lifev/core/mesh/MeshData.hpp>
51 #include <lifev/core/mesh/MeshPartitioner.hpp>
52 #include <lifev/navier_stokes/solver/OseenData.hpp>
53 #include <lifev/navier_stokes/fem/TimeAdvanceBDFNavierStokes.hpp>
54 #include <lifev/core/fem/FESpace.hpp>
55 #ifdef HAVE_HDF5
56 #include <lifev/core/filter/ExporterHDF5.hpp>
57 #endif
58 #include <lifev/core/filter/ExporterEnsight.hpp>
59 
60 #include <lifev/navier_stokes/solver/OseenSolver.hpp>
61 
62 #include "flowConditions.hpp"
63 #include "resistance.hpp"
64 #include <iostream>
65 
66 
67 using namespace LifeV;
68 
69 const int INLET = 3;
70 const int WALL = 200;
71 const int OUTLET = 2;
72 const int RINGIN = 30;
73 const int RINGOUT = 20;
74 
75 
76 void
77 postProcessFluxesPressures ( OseenSolver< RegionMesh<LinearTetra> >& nssolver,
78  BCHandler& bcHandler,
79  const LifeV::Real& t, bool _verbose )
80 {
81  LifeV::Real Q, P;
82  UInt flag;
83 
84  for ( BCHandler::bcBaseIterator_Type it = bcHandler.begin();
85  it != bcHandler.end(); ++it )
86  {
87  flag = it->flag();
88 
89  Q = nssolver.flux (flag);
90  P = nssolver.pressure (flag);
91 
92  if ( _verbose )
93  {
94  std::ofstream outfile;
95  std::stringstream filenamess;
96  std::string filename;
97 
98  // file name contains the label
99  filenamess << flag;
100  // writing down fluxes
101  filename = "flux_label" + filenamess.str() + ".m";
102  outfile.open (filename.c_str(), std::ios::app);
103  outfile << Q << " " << t << "\n";
104  outfile.close();
105  // writing down pressures
106  filename = "pressure_label" + filenamess.str() + ".m";
107  outfile.open (filename.c_str(), std::ios::app);
108  outfile << P << " " << t << "\n";
109  outfile.close();
110  // reset ostringstream
111  filenamess.str ("");
112  }
113  }
114 
115 }
116 
117 
118 struct ResistanceTest::Private
119 {
121  nu (1),
122  H (1), D (1)
123  {}
124  typedef std::function<Real ( Real const&, Real const&, Real const&, Real const&, ID const& ) > fct_Type;
125 
126  double Re;
127 
129 
130  double nu; /**< viscosity (in m^2/s) */
131  //const double rho; /**< density is constant (in kg/m^3) */
132  double H; /**< height and width of the domain (in m) */
133  double D; /**< diameter of the cylinder (in m) */
134  bool centered; /**< true if the cylinder is at the origin */
135 
137 
139 
140  // Static boost functions to impose boundary conditions
141  // Inlet BCs (for this test Poiseuille)
142  static Real fluxFunctionAneurysm (const Real& t, const Real& /*x*/, const Real& /*y*/, const Real& /*z*/, const ID& /*i*/)
143  {
144 
145  Real fluxFinal(0.0);
146  Real rampAmpl (0.2);
147  Real dt (0.001);
148 
149  if ( t <= rampAmpl )
150  {
151  fluxFinal = ( 0.09403 / rampAmpl) * t;
152  }
153  else
154  {
155 
156 
157  // We change the flux for our geometry
158  const Real pi = 3.141592653589793;
159  const Real area = 0.1950; // BigMesh
160 
161  const Real areaFactor = area / ( 0.195 * 0.195 * pi);
162  //const Real Average = (48.21 * pow (area, 1.84) ) * 60; //Mean Cebral's Flux per minut
163 
164  // Unit conversion from ml/min to cm^3/s
165  const Real unitFactor = 1. / 60.;
166 
167  // T is the period of the cardiac cycle
168  const Real T = 0.8;
169 
170  // a0 is the average VFR (the value is taken from Karniadakis p970)
171  const Real a0 = 255;
172  //const Real volumetric = Average / a0; //VolumetricFactor per minut
173 
174  // Fourrier
175  const Int M (7);
176  const Real a[M] = { -0.152001, -0.111619, 0.043304, 0.028871, 0.002098, -0.027237, -0.000557};
177  const Real b[M] = { 0.129013, -0.031435, -0.086106, 0.028263, 0.010177, 0.012160, -0.026303};
178 
179  Real flux (0);
180  // const Real xi(2*pi*t/T);
181  const Real xi (2 * pi * (t - rampAmpl + dt) / T);
182 
183  flux = a0;
184  Int k (1);
185  for (; k <= M ; ++k)
186  {
187  flux += a0 * (a[k - 1] * cos (k * xi) + b[k - 1] * sin (k * xi) );
188  }
189 
190  //return - (flux * areaFactor * unitFactor);
191  fluxFinal = (flux * areaFactor * unitFactor);
192  }
193 
194  return fluxFinal;
195 
196  }
197 
198  static Real aneurismFluxInVectorial (const Real& t, const Real& x, const Real& y, const Real& z, const ID& i)
199  {
200  Real n1 (-0.67463);
201  Real n2 (-0.19861);
202  Real n3 (-0.71094);
203 
204  Real x0 (6.752113);
205  Real y0 (9.398349);
206  Real z0 (18.336601);
207 
208  Real flux (fluxFunctionAneurysm (t, x, y, z, i) );
209 
210  Real area (0.195);
211 
212  //Parabolic profile
213  Real radius ( std::sqrt ( area / 3.14159265359 ) );
214 
215  Real radiusSquared = radius * radius;
216  Real peak (0);
217  peak = ( 2 * flux ) / ( area );
218 
219  switch (i)
220  {
221  case 0:
222  // Flat profile: flux / area;
223  // return n1 * flux / area;
224  return n1 * std::max ( 0.0, peak * ( (radiusSquared - ( (x - x0) * (x - x0) + (y - y0) * (y - y0) ) ) / radiusSquared) );
225  case 1:
226  // Flat profile: flux / area;
227  //return n2 * flux / area;
228  return n2 * std::max ( 0.0 , peak * ( (radiusSquared - ( (x - x0) * (x - x0) + (y - y0) * (y - y0) ) ) / radiusSquared) );
229  case 2:
230  // Flat profile: flux / area;
231  // return n3 * flux / area;
232  return n3 * std::max ( 0.0, peak * ( (radiusSquared - ( (x - x0) * (x - x0) + (y - y0) * (y - y0) ) ) / radiusSquared) );
233  default:
234  return 0.0;
235  }
236  }
237 
238  // External BCs ( u = 0 )
239  static Real zeroBCF (const Real& /*t*/, const Real& /*x*/, const Real& /*y*/, const Real& /*z*/, const ID& i)
240  {
241  switch (i)
242  {
243  case 0:
244  //Flat profile: flux / area;
245  //return n1 * flux / area;
246  return 0;
247  case 1:
248  //Flat profile: flux / area;
249  //return n2 * flux / area;
250  return 0;
251  case 2:
252  // Flat profile: flux / area;
253  // return n3 * flux / area;
254  return 0;
255  default:
256  return 0.0;
257  }
258  }
259 
260  // Outflow BC ( resistance BC - applied explicitly )
261  // Defined by the class FlowConditions
262 
263 
264 };
265 
266 ResistanceTest::ResistanceTest ( int argc,
267  char** argv )
268  :
269  parameters ( new Private )
270 {
271  GetPot command_line (argc, argv);
272  std::string data_file_name = command_line.follow ("data", 2, "-f", "--file");
273  GetPot dataFile ( data_file_name );
274  parameters->data_file_name = data_file_name;
275 
276  parameters->Re = dataFile ( "fluid/problem/Re", 1. );
277  parameters->nu = dataFile ( "fluid/physics/viscosity", 1. ) /
278  dataFile ( "fluid/physics/density", 1. );
279  parameters->H = 20.;//dataFile( "fluid/problem/H", 20. );
280  parameters->D = dataFile ( "fluid/problem/D", 1. );
281  parameters->centered = (bool) dataFile ( "fluid/problem/centered", 0 );
282  parameters->initial_sol = (std::string) dataFile ( "fluid/problem/initial_sol", "stokes");
283  std::cout << parameters->initial_sol << std::endl;
284 
285 
286 #ifdef EPETRA_MPI
287  std::cout << "mpi initialization ... " << std::endl;
288 
289  // MPI_Init(&argc,&argv);
290 
291  int ntasks = 0;
292  parameters->comm.reset ( new Epetra_MpiComm ( MPI_COMM_WORLD ) );
293 
294 #else
295  parameters->comm.reset ( new Epetra_SerialComm() );
296 #endif
297 
298 }
299 
300 void
301 ResistanceTest::run()
302 
303 {
304  typedef RegionMesh<LinearTetra> mesh_Type;
305  typedef FESpace< mesh_Type, MapEpetra > feSpace_Type;
306  typedef std::shared_ptr<feSpace_Type> feSpacePtr_Type;
307  typedef OseenSolver< mesh_Type >::vector_Type vector_Type;
308  typedef std::shared_ptr<vector_Type> vectorPtr_Type;
309  // Reading from data file
310  //
311  GetPot dataFile ( parameters->data_file_name );
312 
313  // int save = dataFile("fluid/miscellaneous/save", 1);
314 
315  bool verbose = (parameters->comm->MyPID() == 0);
316 
317  // Lagrange multiplier for flux BCs
318  int numLM = 0;
319 
320  std::shared_ptr<OseenData> oseenData (new OseenData() );
321  oseenData->setup ( dataFile );
322 
323  MeshData meshData;
324  meshData.setup (dataFile, "fluid/space_discretization");
325 
326  std::shared_ptr<mesh_Type> fullMeshPtr ( new mesh_Type ( parameters->comm ) );
327  readMesh (*fullMeshPtr, meshData);
328 
329  std::shared_ptr<mesh_Type> meshPtr;
330  {
331  MeshPartitioner< mesh_Type > meshPart (fullMeshPtr, parameters->comm);
332  meshPtr = meshPart.meshPartition();
333  }
334 
335  //oseenData.meshData()->setMesh(meshPtr);
336 
337  std::string uOrder = dataFile ( "fluid/space_discretization/vel_order", "P1");
338  if (verbose)
339  {
340  std::cout << "Building the velocity FE space ... " << std::flush;
341  }
342 
343  feSpacePtr_Type uFESpacePtr ( new feSpace_Type (meshPtr, uOrder, 3, parameters->comm) );
344 
345  if (verbose)
346  {
347  std::cout << "ok." << std::endl;
348  }
349 
350 
351  std::string pOrder = dataFile ( "fluid/space_discretization/press_order", "P1");
352 
353  if (verbose)
354  {
355  std::cout << "Building the pressure FE space ... " << std::flush;
356  }
357 
358  feSpacePtr_Type pFESpacePtr ( new feSpace_Type (meshPtr, pOrder, 1, parameters->comm) );
359 
360  if (verbose)
361  {
362  std::cout << "ok." << std::endl;
363  }
364 
365  UInt totalVelDof = uFESpacePtr->map().map (Unique)->NumGlobalElements();
366  UInt totalPressDof = pFESpacePtr->map().map (Unique)->NumGlobalElements();
367 
368  // Boundary conditions
369  BCHandler bcH;
370  BCFunctionBase uIn ( Private::aneurismFluxInVectorial );
371  BCFunctionBase uZero ( Private::zeroBCF );
372 
373  FlowConditions outFlowBC;
374 
375  // Read the resistance and hydrostatic pressure from data file
376  Real resistance = dataFile ( "fluid/physics/resistance", 0.0 );
377  Real hydrostatic = dataFile ( "fluid/physics/hydrostatic", 0.0 );
378 
379  // outFlowBC.initParameters( OUTLET, resistance, hydrostatic, "outlet-3" );
380 
381  vectorPtr_Type resistanceImplicit;
382  resistanceImplicit.reset( new vector_Type( uFESpacePtr->map(), Repeated ) );
383  resistanceImplicit->epetraVector().PutScalar(0.0);
384 
385  BCVector resistanceBCdefinition;
386  resistanceBCdefinition.setRhsVector( *resistanceImplicit, uFESpacePtr->dof().numTotalDof(), 1 );
387  resistanceBCdefinition.setResistanceCoeff( 600000.0 );
388 
389 
390  // Explicit Resistance BC
391  //BCFunctionBase resistanceBC( FlowConditions::outPressure0 );
392  //cylinder
393 
394  bcH.addBC ( "Inlet", INLET, Essential, Full, uIn , 3 );
395  bcH.addBC ( "Wall", WALL, Essential, Full, uZero, 3 );
396 
397  // Explicit Resistance BC
398  // bcH.addBC ( "Outlet", OUTLET, Natural, Normal, resistanceBC );
399  bcH.addBC ( "Outlet", OUTLET, Resistance, Full, resistanceBCdefinition, 3 );
400 
401 
402  if (verbose)
403  {
404  std::cout << "Total Velocity DOF = " << totalVelDof << std::endl;
405  }
406  if (verbose)
407  {
408  std::cout << "Total Pressure DOF = " << totalPressDof << std::endl;
409  }
410 
411  if (verbose)
412  {
413  std::cout << "Calling the fluid constructor ... ";
414  }
415 
416  OseenSolver< mesh_Type > fluid (oseenData,
417  *uFESpacePtr,
418  *pFESpacePtr,
419  parameters->comm, numLM);
420  MapEpetra fullMap (fluid.getMap() );
421 
422  if (verbose)
423  {
424  std::cout << "ok." << std::endl;
425  }
426 
427  fluid.setUp (dataFile);
428 
429  // Setting up the utility for post-processing
430  fluid.setupPostProc( );
431 
432  std::cout << "Inlet area: " << fluid.area( INLET ) << std::endl;
433  fluid.buildSystem();
434 
435  MPI_Barrier (MPI_COMM_WORLD);
436 
437  // Initialization
438 
439  Real dt = oseenData->dataTime()->timeStep();
440  Real t0 = oseenData->dataTime()->initialTime();
441  Real tFinal = oseenData->dataTime()->endTime();
442 
443 
444  // bdf object to store the previous solutions
445 
446  TimeAdvanceBDFNavierStokes<vector_Type> bdf;
447  bdf.setup (oseenData->dataTimeAdvance()->orderBDF() );
448 
449  vector_Type beta ( fullMap );
450  vector_Type rhs ( fullMap );
451 
452  std::string const exportFileName = dataFile ( "exporter/nameFile", "resistance");
453 
454 #ifdef HAVE_HDF5
455  ExporterHDF5<mesh_Type > exporter ( dataFile, meshPtr, exportFileName, parameters->comm->MyPID() );
456 #else
457  ExporterEnsight<mesh_Type > exporter ( dataFile, meshPtr, exportFileName, parameters->comm->MyPID() );
458 #endif
459 
460  vectorPtr_Type velAndPressure ( new vector_Type (*fluid.solution(), exporter.mapType() ) );
461 
462  exporter.addVariable ( ExporterData<mesh_Type>::VectorField, "velocity", uFESpacePtr,
463  velAndPressure, UInt (0) );
464 
465  exporter.addVariable ( ExporterData<mesh_Type>::ScalarField, "pressure", pFESpacePtr,
466  velAndPressure, UInt (3 * uFESpacePtr->dof().numTotalDof() ) );
467 
468  // Setting up the initial condition
469  bdf.bdfVelocity().setInitialCondition ( *fluid.solution() );
470 
471  // Temporal loop
472 
473  LifeChrono chrono;
474  int iter = 1;
475 
476  for ( Real time = t0 + dt ; time <= tFinal + dt / 2.; time += dt, iter++)
477  {
478 
479  std::cout << "Inlet area: " << fluid.area ( INLET ) << std::endl;
480 
481  // Updating the Neumann BC for resistance
482  outFlowBC.renewParameters ( fluid, *velAndPressure );
483  // if ( verbose )
484  // {
485  // std::cout << std::endl;
486  // std::cout << "Name: " << outFlowBC.name() << std::endl;
487  // std::cout << "Resistance: " << outFlowBC.resistance() << std::endl;
488  // std::cout << "Flow: " << outFlowBC.flow() << std::endl;
489  // std::cout << "Hydrostatic: " << outFlowBC.hydrostatic() << std::endl;
490  // std::cout << "Total Pressure: " << outFlowBC.outP() << std::endl;
491  // std::cout << std::endl;
492  // }
493 
494  oseenData->dataTime()->setTime (time);
495 
496  chrono.start();
497 
498  double alpha = bdf.bdfVelocity().coefficientFirstDerivative ( 0 ) / oseenData->dataTime()->timeStep();
499  bdf.bdfVelocity().extrapolation (beta);
500  bdf.bdfVelocity().updateRHSContribution ( oseenData->dataTime()->timeStep() );
501  rhs = fluid.matrixMass() * bdf.bdfVelocity().rhsContributionFirstDerivative();
502 
503  fluid.updateSystem ( alpha, beta, rhs );
504  fluid.iterate ( bcH );
505 
506  bdf.bdfVelocity().shiftRight ( *fluid.solution() );
507 
508  *velAndPressure = *fluid.solution();
509 
510  // if ( verbose )
511  // {
512  // std::cout << "Post-processing!" << std::endl;
513  // }
514  exporter.postProcess ( time );
515 
516  MPI_Barrier (MPI_COMM_WORLD);
517 
518  chrono.stop();
519  if (verbose)
520  {
521  std::cout << "Total iteration time " << chrono.diff() << " s." << std::endl;
522  }
523  }
524 
525 }
526 
527 
528 //////////////////////
std::function< Real(Real const &, Real const &, Real const &, Real const &, ID const &) > fct_Type
double operator()(const char *VarName, const double &Default) const
Definition: GetPot.hpp:2033
bool centered
true if the cylinder is at the origin
double H
height and width of the domain (in m)
ExporterEnsight data exporter.
FESpace - Short description here please!
Definition: FESpace.hpp:78
static Real zeroBCF(const Real &, const Real &, const Real &, const Real &, const ID &i)
GetPot(const int argc_, char **argv_, const char *FieldSeparator=0x0)
Definition: GetPot.hpp:507
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
Epetra_Import const & importer()
Getter for the Epetra_Import.
Definition: MapEpetra.cpp:394
uint32_type ID
IDs.
Definition: LifeV.hpp:194
std::shared_ptr< std::vector< Int > > M_isOnProc
MeshData - class for handling spatial discretization.
Definition: MeshData.hpp:72
double Real
Generic real data.
Definition: LifeV.hpp:175
static Real fluxFunctionAneurysm(const Real &t, const Real &, const Real &, const Real &, const ID &)
static Real aneurismFluxInVectorial(const Real &t, const Real &x, const Real &y, const Real &z, const ID &i)
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191