LifeV
cylinder.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 
32 #include <Epetra_ConfigDefs.h>
33 #ifdef EPETRA_MPI
34 #include <mpi.h>
35 #include <Epetra_MpiComm.h>
36 #else
37 #include <Epetra_SerialComm.h>
38 #endif
39 
40 
41 //#include "life/lifesolver/NavierStokesSolver.hpp"
42 #include <lifev/core/array/MatrixEpetra.hpp>
43 #include <lifev/core/array/MapEpetra.hpp>
44 #include <lifev/core/mesh/MeshData.hpp>
45 #include <lifev/core/mesh/MeshPartitioner.hpp>
46 #include <lifev/navier_stokes/solver/OseenData.hpp>
47 #include <lifev/navier_stokes/fem/TimeAdvanceBDFNavierStokes.hpp>
48 #include <lifev/core/fem/FESpace.hpp>
49 #ifdef HAVE_HDF5
50 #include <lifev/core/filter/ExporterHDF5.hpp>
51 #endif
52 #include <lifev/core/filter/ExporterEnsight.hpp>
53 
54 #include <lifev/navier_stokes/solver/OseenSolver.hpp>
55 
56 #include "cylinder.hpp"
57 #include <iostream>
58 
59 
60 
61 using namespace LifeV;
62 
64 
65 const int INLET = 2;
66 const int WALL = 1;
67 const int OUTLET = 3;
68 const int RINGIN = 20;
69 const int RINGOUT = 30;
70 
71 
72 Real zero_scalar ( const Real& /* t */,
73  const Real& /* x */,
74  const Real& /* y */,
75  const Real& /* z */,
76  const ID& /* i */ )
77 {
78  return 0.;
79 }
80 
81 Real u2 (const Real& t, const Real& /*x*/, const Real& /*y*/, const Real& /*z*/, const ID& i)
82 {
83  switch (i)
84  {
85  case 0:
86  return 0.0;
87  break;
88  case 2:
89  if ( t <= 0.003 )
90  {
91  return 1.3332e4;
92  }
93  // return 0.01;
94  return 0.0;
95  break;
96  case 1:
97  return 0.0;
98  // return 1.3332e4;
99  // else
100  // return 0.0;
101  break;
102  }
103  return 0;
104 }
105 
106 void
107 postProcessFluxesPressures ( OseenSolver< mesh_Type >& nssolver,
108  BCHandler& bcHandler,
109  const LifeV::Real& t, bool _verbose )
110 {
111  LifeV::Real Q, P;
112  UInt flag;
113 
114  for ( BCHandler::bcBaseIterator_Type it = bcHandler.begin();
115  it != bcHandler.end(); ++it )
116  {
117  flag = it->flag();
118 
119  Q = nssolver.flux (flag);
120  P = nssolver.pressure (flag);
121 
122  if ( _verbose )
123  {
124  std::ofstream outfile;
125  std::stringstream filenamess;
126  std::string filename;
127 
128  // file name contains the label
129  filenamess << flag;
130  // writing down fluxes
131  filename = "flux_label" + filenamess.str() + ".m";
132  outfile.open (filename.c_str(), std::ios::app);
133  outfile << Q << " " << t << "\n";
134  outfile.close();
135  // writing down pressures
136  filename = "pressure_label" + filenamess.str() + ".m";
137  outfile.open (filename.c_str(), std::ios::app);
138  outfile << P << " " << t << "\n";
139  outfile.close();
140  // reset ostringstream
141  filenamess.str ("");
142  }
143  }
144 
145 }
146 
147 
149 {
151  //check(false),
152  nu (1),
153  //rho(1),
154  H (1), D (1)
155  //H(20), D(1)
156  //H(0.41), D(0.1)
157  {}
158  typedef std::function<Real ( Real const&, Real const&, Real const&, Real const&, ID const& ) > fct_Type;
159 
160  double Re;
161 
163 
164  double nu; /**< viscosity (in m^2/s) */
165  //const double rho; /**< density is constant (in kg/m^3) */
166  double H; /**< height and width of the domain (in m) */
167  double D; /**< diameter of the cylinder (in m) */
168  bool centered; /**< true if the cylinder is at the origin */
169 
171 
173  /**
174  * get the characteristic velocity
175  *
176  * @return the characteristic velocity
177  */
178  double Ubar() const
179  {
180  return nu * Re / D;
181  }
182 
183  /**
184  * get the magnitude of the profile velocity
185  *
186  *
187  * @return the magnitude of the profile velocity
188  */
189  double Um_3d() const
190  {
191  return 9 * Ubar() / 4;
192  }
193 
194  double Um_2d() const
195  {
196  return 3 * Ubar() / 2;
197  }
198 
199 
200  /**
201  * u3d 3D velocity profile.
202  *
203  * Define the velocity profile at the inlet for the 3D cylinder
204  */
205  Real u3d ( const Real& /* t */,
206  const Real& /* x */,
207  const Real& y,
208  const Real& z,
209  const ID& id ) const
210  {
211  if ( id == 0 )
212  {
213  if ( centered )
214  {
215  return Um_3d() * (H + y) * (H - y) * (H + z) * (H - z) / std::pow (H, 4);
216  }
217  else
218  {
219  return 16 * Um_3d() * y * z * (H - y) * (H - z) / std::pow (H, 4);
220  }
221  }
222  else
223  {
224  return 0;
225  }
226  }
227 
229  {
230  fct_Type f;
231  f = std::bind (&Cylinder::Private::u3d, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5);
232  return f;
233  }
234 
235  /**
236  * u2d flat 2D velocity profile.
237  *
238  * Define the velocity profile at the inlet for the 2D cylinder
239  */
240  Real u2d ( const Real& t,
241  const Real& /*x*/,
242  const Real& /*y*/,
243  const Real& /*z*/,
244  const ID& id ) const
245  {
246 
247  switch (id)
248  {
249  case 0: // x component
250  return 0.0;
251  break;
252  case 2: // z component
253  if ( t <= 0.003 )
254  {
255  return 1.3332e4;
256  }
257  // return 0.01;
258  return 0.0;
259  break;
260  case 1: // y component
261  return 0.0;
262  // return 1.3332e4;
263  // else
264  // return 0.0;
265  break;
266  }
267  return 0;
268  }
269 
271  {
272  fct_Type f;
273  f = std::bind (&Cylinder::Private::u2d, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5);
274  return f;
275  }
276 
277  /**
278  * one flat (1,1,1)
279  *
280  * Define the velocity profile at the inlet for the 2D cylinder
281  */
282  Real poiseuille ( const Real& /*t*/,
283  const Real& x,
284  const Real& y,
285  const Real& /*z*/,
286  const ID& id ) const
287  {
288  double r = std::sqrt (x * x + y * y);
289 
290  if (id == 2)
291  {
292  return Um_2d() * 2 * ( (D / 2.) * (D / 2.) - r * r);
293  }
294 
295  return 0.;
296  }
297 
299  {
300  fct_Type f;
301  f = std::bind (&Cylinder::Private::poiseuille, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5);
302  return f;
303  }
304 
305 
306  Real oneU ( const Real& /*t*/,
307  const Real& /*x*/,
308  const Real& /*y*/,
309  const Real& /*z*/,
310  const ID& /*id*/ ) const
311  {
312  // if (id == 3)
313  return 10.;
314 
315  return -1.;
316  }
317 
319  {
320  fct_Type f;
321  f = std::bind (&Cylinder::Private::oneU, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4, std::placeholders::_5);
322  return f;
323  }
324 
325 
326 };
327 
328 Cylinder::Cylinder ( int argc,
329  char** argv )
330  :
331  d ( new Private )
332 {
333  GetPot command_line (argc, argv);
334  std::string data_file_name = command_line.follow ("data", 2, "-f", "--file");
335  GetPot dataFile ( data_file_name );
336  d->data_file_name = data_file_name;
337 
338  d->Re = dataFile ( "fluid/problem/Re", 1. );
339  d->nu = dataFile ( "fluid/physics/viscosity", 1. ) /
340  dataFile ( "fluid/physics/density", 1. );
341  d->H = 20.;//dataFile( "fluid/problem/H", 20. );
342  d->D = dataFile ( "fluid/problem/D", 1. );
343  d->centered = (bool) dataFile ( "fluid/problem/centered", 0 );
344  d->initial_sol = (std::string) dataFile ( "fluid/problem/initial_sol", "stokes");
345  std::cout << d->initial_sol << std::endl;
346 
347 
348 #ifdef EPETRA_MPI
349  std::cout << "mpi initialization ... " << std::endl;
350 
351  // MPI_Init(&argc,&argv);
352 
353  int ntasks = 0;
354  d->comm.reset ( new Epetra_MpiComm ( MPI_COMM_WORLD ) );
355  if (!d->comm->MyPID() )
356  {
357  std::cout << "My PID = " << d->comm->MyPID() << " out of " << ntasks << " running." << std::endl;
358  std::cout << "Re = " << d->Re << std::endl
359  << "nu = " << d->nu << std::endl
360  << "H = " << d->H << std::endl
361  << "D = " << d->D << std::endl;
362  }
363  // int err = MPI_Comm_size(MPI_COMM_WORLD, &ntasks);
364 #else
365  d->comm.reset ( new Epetra_SerialComm() );
366 #endif
367 
368 }
369 
370 void
372 
373 {
374  typedef FESpace< mesh_Type, MapEpetra > feSpace_Type;
375  typedef std::shared_ptr<feSpace_Type> feSpacePtr_Type;
376  typedef OseenSolver< mesh_Type >::vector_Type vector_Type;
377  typedef std::shared_ptr<vector_Type> vectorPtr_Type;
378  // Reading from data file
379  //
380  GetPot dataFile ( d->data_file_name );
381 
382  // int save = dataFile("fluid/miscellaneous/save", 1);
383 
384  bool verbose = (d->comm->MyPID() == 0);
385 
386  // Boundary conditions
387  BCHandler bcH;
388  BCFunctionBase uZero ( zero_scalar );
389  std::vector<ID> zComp (1);
390  zComp[0] = 3;
391 
392  BCFunctionBase uIn ( d->getU_2d() );
393  BCFunctionBase uOne ( d->getU_one() );
394  BCFunctionBase uPois ( d->getU_pois() );
395 
396 
397  //BCFunctionBase unormal( d->get_normal() );
398 
399  //cylinder
400 
401  bcH.addBC ( "Inlet", INLET, Essential, Full, uPois , 3 );
402  bcH.addBC ( "Ringin", RINGIN, Essential, Full, uZero , 3 );
403  bcH.addBC ( "Ringout", RINGOUT, Essential, Full, uZero , 3 );
404  bcH.addBC ( "Outlet", OUTLET, Natural, Full, uZero, 3 );
405  bcH.addBC ( "Wall", WALL, Essential, Full, uZero, 3 );
406 
407  int numLM = 0;
408 
409  std::shared_ptr<OseenData> oseenData (new OseenData() );
410  oseenData->setup ( dataFile );
411 
412  MeshData meshData;
413  meshData.setup (dataFile, "fluid/space_discretization");
414 
415  std::shared_ptr<mesh_Type> fullMeshPtr ( new mesh_Type ( d->comm ) );
416  readMesh (*fullMeshPtr, meshData);
417 
418  std::shared_ptr<mesh_Type> meshPtr;
419  {
420  MeshPartitioner< mesh_Type > meshPart (fullMeshPtr, d->comm);
421  meshPtr = meshPart.meshPartition();
422  }
423  if (verbose)
424  {
425  std::cout << std::endl;
426  }
427  if (verbose)
428  {
429  std::cout << "Time discretization order " << oseenData->dataTimeAdvance()->orderBDF() << std::endl;
430  }
431 
432  //oseenData.meshData()->setMesh(meshPtr);
433 
434  std::string uOrder = dataFile ( "fluid/space_discretization/vel_order", "P1");
435  if (verbose)
436  {
437  std::cout << "Building the velocity FE space ... " << std::flush;
438  }
439 
440  feSpacePtr_Type uFESpacePtr ( new feSpace_Type (meshPtr, uOrder, 3, d->comm) );
441 
442  if (verbose)
443  {
444  std::cout << "ok." << std::endl;
445  }
446 
447 
448  std::string pOrder = dataFile ( "fluid/space_discretization/press_order", "P1");
449 
450  if (verbose)
451  {
452  std::cout << "Building the pressure FE space ... " << std::flush;
453  }
454 
455  feSpacePtr_Type pFESpacePtr ( new feSpace_Type (meshPtr, pOrder, 1, d->comm) );
456 
457  if (verbose)
458  {
459  std::cout << "ok." << std::endl;
460  }
461 
462  UInt totalVelDof = uFESpacePtr->map().map (Unique)->NumGlobalElements();
463  UInt totalPressDof = pFESpacePtr->map().map (Unique)->NumGlobalElements();
464 
465 
466 
467  if (verbose)
468  {
469  std::cout << "Total Velocity DOF = " << totalVelDof << std::endl;
470  }
471  if (verbose)
472  {
473  std::cout << "Total Pressure DOF = " << totalPressDof << std::endl;
474  }
475 
476  if (verbose)
477  {
478  std::cout << "Calling the fluid constructor ... ";
479  }
480 
481  bcH.setOffset ( "Inlet", totalVelDof + totalPressDof - 1 );
482 
483  OseenSolver< mesh_Type > fluid (oseenData,
484  *uFESpacePtr,
485  *pFESpacePtr,
486  d->comm, numLM);
487  MapEpetra fullMap (fluid.getMap() );
488 
489  if (verbose)
490  {
491  std::cout << "ok." << std::endl;
492  }
493 
494  fluid.setUp (dataFile);
495  fluid.buildSystem();
496 
497  MPI_Barrier (MPI_COMM_WORLD);
498 
499  // Initialization
500 
501  Real dt = oseenData->dataTime()->timeStep();
502  Real t0 = oseenData->dataTime()->initialTime();
503  Real tFinal = oseenData->dataTime()->endTime();
504 
505 
506  // bdf object to store the previous solutions
507 
508  TimeAdvanceBDFNavierStokes<vector_Type> bdf;
509  bdf.setup (oseenData->dataTimeAdvance()->orderBDF() );
510 
511  vector_Type beta ( fullMap );
512  vector_Type rhs ( fullMap );
513 
514 #ifdef HAVE_HDF5
515  ExporterHDF5<mesh_Type > ensight ( dataFile, meshPtr, "cylinder", d->comm->MyPID() );
516 #else
517  ExporterEnsight<mesh_Type > ensight ( dataFile, meshPtr, "cylinder", d->comm->MyPID() );
518 #endif
519 
520  vectorPtr_Type velAndPressure ( new vector_Type (*fluid.solution(), ensight.mapType() ) );
521 
522  ensight.addVariable ( ExporterData<mesh_Type>::VectorField, "velocity", uFESpacePtr,
523  velAndPressure, UInt (0) );
524 
525  ensight.addVariable ( ExporterData<mesh_Type>::ScalarField, "pressure", pFESpacePtr,
526  velAndPressure, UInt (3 * uFESpacePtr->dof().numTotalDof() ) );
527 
528  // initialization with stokes solution
529 
530  if (d->initial_sol == "stokes")
531  {
532  if (verbose)
533  {
534  std::cout << std::endl;
535  }
536  if (verbose)
537  {
538  std::cout << "Computing the stokes solution ... " << std::endl << std::endl;
539  }
540 
541  oseenData->dataTime()->setTime (t0);
542 
543  MPI_Barrier (MPI_COMM_WORLD);
544 
545  beta *= 0.;
546  rhs *= 0.;
547 
548  fluid.updateSystem (0, beta, rhs );
549  fluid.iterate ( bcH );
550 
551  // fluid.postProcess();
552 
553  *velAndPressure = *fluid.solution();
554  ensight.postProcess ( 0 );
555  fluid.resetPreconditioner();
556  }
557 
558  bdf.bdfVelocity().setInitialCondition ( *fluid.solution() );
559 
560  // Temporal loop
561 
562  LifeChrono chrono;
563  int iter = 1;
564 
565  for ( Real time = t0 + dt ; time <= tFinal + dt / 2.; time += dt, iter++)
566  {
567 
568  oseenData->dataTime()->setTime (time);
569 
570  if (verbose)
571  {
572  std::cout << std::endl;
573  std::cout << "We are now at time " << oseenData->dataTime()->time() << " s. " << std::endl;
574  std::cout << std::endl;
575  }
576 
577  chrono.start();
578 
579  double alpha = bdf.bdfVelocity().coefficientFirstDerivative ( 0 ) / oseenData->dataTime()->timeStep();
580  //beta = bdf.bdfVelocity().extrapolation( beta);
581  bdf.bdfVelocity().extrapolation (beta);
582  bdf.bdfVelocity().updateRHSContribution ( oseenData->dataTime()->timeStep() );
583  rhs = fluid.matrixMass() * bdf.bdfVelocity().rhsContributionFirstDerivative();
584 
585  fluid.updateSystem ( alpha, beta, rhs );
586  fluid.iterate ( bcH );
587 
588  bdf.bdfVelocity().shiftRight ( *fluid.solution() );
589 
590  // if (((iter % save == 0) || (iter == 1 )))
591  // {
592  *velAndPressure = *fluid.solution();
593  ensight.postProcess ( time );
594  // }
595  // postProcessFluxesPressures(fluid, bcH, time, verbose);
596 
597 
598  MPI_Barrier (MPI_COMM_WORLD);
599 
600  chrono.stop();
601  if (verbose)
602  {
603  std::cout << "Total iteration time " << chrono.diff() << " s." << std::endl;
604  }
605  }
606 
607 }
608 
609 
610 //////////////////////
double H
height and width of the domain (in m)
Definition: cylinder.cpp:166
const int OUTLET
Definition: cylinder.cpp:67
std::function< Real(Real const &, Real const &, Real const &, Real const &, ID const &) > fct_Type
Definition: cylinder.cpp:158
fct_Type getU_one()
Definition: cylinder.cpp:318
std::shared_ptr< Epetra_Comm > comm
Definition: cylinder.cpp:172
ExporterEnsight data exporter.
FESpace - Short description here please!
Definition: FESpace.hpp:78
GetPot(const int argc_, char **argv_, const char *FieldSeparator=0x0)
Definition: GetPot.hpp:507
double nu
viscosity (in m^2/s)
Definition: cylinder.cpp:164
std::string initial_sol
Definition: cylinder.cpp:170
Real poiseuille(const Real &, const Real &x, const Real &y, const Real &, const ID &id) const
one flat (1,1,1)
Definition: cylinder.cpp:282
2D/3D Cylinder Simulation class
Definition: cylinder.hpp:44
Epetra_Import const & importer()
Getter for the Epetra_Import.
Definition: MapEpetra.cpp:394
uint32_type ID
IDs.
Definition: LifeV.hpp:194
const int WALL
Definition: cylinder.cpp:66
double D
diameter of the cylinder (in m)
Definition: cylinder.cpp:167
std::shared_ptr< std::vector< Int > > M_isOnProc
MeshData - class for handling spatial discretization.
Definition: MeshData.hpp:72
fct_Type getU_3d()
Definition: cylinder.cpp:228
Real oneU(const Real &, const Real &, const Real &, const Real &, const ID &) const
Definition: cylinder.cpp:306
fct_Type getU_2d()
Definition: cylinder.cpp:270
double Real
Generic real data.
Definition: LifeV.hpp:175
std::string data_file_name
Definition: cylinder.cpp:162
RegionMesh< LinearTetra > mesh_Type
Definition: cylinder.cpp:63
double Um_2d() const
Definition: cylinder.cpp:194
fct_Type getU_pois()
Definition: cylinder.cpp:298
void run()
Definition: cylinder.cpp:371
const int INLET
Definition: cylinder.cpp:65
Cylinder(int argc, char **argv)
Definition: cylinder.cpp:328
const int RINGOUT
Definition: cylinder.cpp:69
double Ubar() const
get the characteristic velocity
Definition: cylinder.cpp:178
bool centered
true if the cylinder is at the origin
Definition: cylinder.cpp:168
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191
Real u2d(const Real &t, const Real &, const Real &, const Real &, const ID &id) const
u2d flat 2D velocity profile.
Definition: cylinder.cpp:240
const int RINGIN
Definition: cylinder.cpp:68
Real u3d(const Real &, const Real &, const Real &y, const Real &z, const ID &id) const
u3d 3D velocity profile.
Definition: cylinder.cpp:205
double Um_3d() const
get the magnitude of the profile velocity
Definition: cylinder.cpp:189
Real u2(const Real &t, const Real &, const Real &, const Real &, const ID &i)
Definition: cylinder.cpp:81