LifeV
cavity_ns.cpp
Go to the documentation of this file.
1 /* -*- mode: c++ -*-
2  This program is part of the LifeV library
3  Copyright (C) 2001,2002,2003,2004 EPFL, INRIA, Politechnico di Milano
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU General Public License
7  as published by the Free Software Foundation; either version 2
8  of the License, or (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 /**
20  \file cavity.cpp
21  \author Gwenol Grandperrin <gwenol.grandperrin@epfl.ch>
22  \date 2010-10-25
23  */
24 
25 // LifeV definition files
26 
27 #include <lifev/core/LifeV.hpp>
28 #include <lifev/core/util/LifeChrono.hpp>
29 #include <lifev/navier_stokes/solver/OseenSolver.hpp>
30 #include <lifev/core/mesh/MeshData.hpp>
31 #include <lifev/navier_stokes/solver/OseenData.hpp>
32 #include <lifev/core/array/MapEpetra.hpp>
33 #include <lifev/core/fem/FESpace.hpp>
34 #include <lifev/navier_stokes/fem/TimeAdvanceBDFNavierStokes.hpp>
35 #include <lifev/core/mesh/MeshPartitioner.hpp>
36 #include <lifev/core/filter/ExporterEnsight.hpp>
37 #include <lifev/core/filter/ExporterHDF5.hpp>
38 #include <lifev/core/filter/ExporterEmpty.hpp>
39 
40 
41 
42 //#include <fstream> // To create an output for the flux
43 
44 // Trilinos-MPI communication definitions
45 #include <Epetra_ConfigDefs.h>
46 #ifdef HAVE_MPI
47 #include "Epetra_MpiComm.h"
48 #else
49 #include "Epetra_SerialComm.h"
50 #endif
51 
52 
53 using namespace LifeV;
54 
55 
56 // Object type definitions
61 typedef FESpace< mesh_Type, MapEpetra > feSpace_Type;
63 
64 
65 // +-----------------------------------------------+
66 // | Data and functions for the boundary conditions|
67 // +-----------------------------------------------+
68 const int BACK = 1;
69 const int FRONT = 2;
70 const int LEFT = 3;
71 const int RIGHT = 4;
72 const int BOTTOM = 5;
73 const int TOP = 6;
74 
75 Real lidBC (const Real& /*t*/, const Real& /*x*/, const Real& /*y*/, const Real& /*z*/, const ID& i)
76 {
77  switch (i)
78  {
79  case 1:
80  return 1.0;
81  default:
82  return 0.0;
83  }
84 }
85 
86 Real fZero ( const Real& /* t */,
87  const Real& /* x */,
88  const Real& /* y */,
89  const Real& /* z */,
90  const ID& /* i */ )
91 {
92  return 0.0;
93 }
94 
95 
96 int main (int argc, char** argv)
97 {
98 
99  // +-----------------------------------------------+
100  // | Initialization of MPI |
101  // +-----------------------------------------------+
102 #ifdef HAVE_MPI
103  MPI_Init (&argc, &argv);
104 #endif
105 
106  std::shared_ptr<Epetra_Comm> comm;
107 #ifdef EPETRA_MPI
108  comm.reset ( new Epetra_MpiComm ( MPI_COMM_WORLD ) );
109  int nproc;
110  MPI_Comm_size (MPI_COMM_WORLD, &nproc);
111 #else
112  comm.reset ( new Epetra_SerialComm() );
113 #endif
114 
115  bool verbose (false);
116  if (comm->MyPID() == 0)
117  {
118  verbose = true;
119  std::cout
120  << " +-----------------------------------------------+" << std::endl
121  << " | Cavity example for LifeV |" << std::endl
122  << " +-----------------------------------------------+" << std::endl
123  << std::endl
124  << " +-----------------------------------------------+" << std::endl
125  << " | Author: Gwenol Grandperrin |" << std::endl
126  << " | Date: October 25, 2010 |" << std::endl
127  << " +-----------------------------------------------+" << std::endl
128  << std::endl;
129 
130  std::cout << "[Initilization of MPI]" << std::endl;
131 #ifdef HAVE_MPI
132  std::cout << "Using MPI (" << nproc << " proc.)" << std::endl;
133 #else
134  std::cout << "Using serial version" << std::endl;
135 #endif
136  }
137 
138  // Chronometer
139  LifeChrono globalChrono;
140  LifeChrono initChrono;
141  LifeChrono iterChrono;
142  globalChrono.start();
143  initChrono.start();
144 
145  // +-----------------------------------------------+
146  // | Loading the data |
147  // +-----------------------------------------------+
148  if (verbose)
149  {
150  std::cout << std::endl << "[Loading the data]" << std::endl;
151  }
152  GetPot command_line (argc, argv);
153  const std::string dataFileName = command_line.follow ("data", 2, "-f", "--file");
154  GetPot dataFile (dataFileName);
155 
156  // +-----------------------------------------------+
157  // | Loading the mesh |
158  // +-----------------------------------------------+
159  if (verbose)
160  {
161  std::cout << std::endl << "[Loading the mesh]" << std::endl;
162  }
163  MeshData meshData;
164  meshData.setup (dataFile, "fluid/space_discretization");
165  if (verbose)
166  {
167  std::cout << "Mesh file: " << meshData.meshDir() << meshData.meshFile() << std::endl;
168  }
169  std::shared_ptr< mesh_Type > fullMeshPtr (new mesh_Type);
170  readMesh (*fullMeshPtr, meshData);
171  // Split the mesh between processors
172  MeshPartitioner< mesh_Type > meshPart (fullMeshPtr, comm);
173 
174  // +-----------------------------------------------+
175  // | Creating the FE spaces |
176  // +-----------------------------------------------+
177  if (verbose)
178  {
179  std::cout << std::endl << "[Creating the FE spaces]" << std::endl;
180  }
181  std::string uOrder = dataFile ( "fluid/space_discretization/vel_order", "P2");
182  std::string pOrder = dataFile ( "fluid/space_discretization/press_order", "P1");
183  if (verbose) std::cout << "FE for the velocity: " << uOrder << std::endl
184  << "FE for the pressure: " << pOrder << std::endl;
185 
186  if (verbose)
187  {
188  std::cout << "Building the velocity FE space... " << std::flush;
189  }
190  feSpacePtr_Type uFESpacePtr ( new feSpace_Type (meshPart.meshPartition(), uOrder, 3, comm) );
191  if (verbose)
192  {
193  std::cout << "ok." << std::endl;
194  }
195 
196  if (verbose)
197  {
198  std::cout << "Building the pressure FE space... " << std::flush;
199  }
200  feSpacePtr_Type pFESpacePtr ( new feSpace_Type (meshPart.meshPartition(), pOrder, 1, comm) );
201  if (verbose)
202  {
203  std::cout << "ok." << std::endl;
204  }
205 
206  // Total degrees of freedom (elements of matrix)
207  UInt totalVelDof = uFESpacePtr->map().map (Unique)->NumGlobalElements();
208  UInt totalPressDof = pFESpacePtr->map().map (Unique)->NumGlobalElements();
209 
210  if (verbose)
211  {
212  std::cout << "Total Velocity Dof: " << totalVelDof << std::endl;
213  }
214  if (verbose)
215  {
216  std::cout << "Total Pressure Dof: " << totalPressDof << std::endl;
217  }
218 
219  // +-----------------------------------------------+
220  // | Boundary conditions |
221  // +-----------------------------------------------+
222  if (verbose)
223  {
224  std::cout << std::endl << "[Boundary conditions]" << std::endl;
225  }
226 
227  BCFunctionBase uZero (fZero);
228  BCFunctionBase uLid (lidBC);
229 
230  std::vector<ID> xComp (1);
231  xComp[0] = 1;
232 
233  BCHandler bcH;
234  // A boundary condition in every face
235  bcH.addBC ( "Top" , TOP , Essential, Full , uLid , 3 );
236  bcH.addBC ( "Left" , LEFT , Essential, Full , uZero, 3 );
237  bcH.addBC ( "Front" , FRONT , Essential, Component, uZero, xComp );
238  bcH.addBC ( "Right" , RIGHT , Essential, Full , uZero, 3 );
239  bcH.addBC ( "Back" , BACK , Essential, Component, uZero, xComp );
240  bcH.addBC ( "Bottom", BOTTOM, Essential, Full , uZero, 3 );
241 
242  // Get the number of Lagrange Multiplyers (LM) and set the offsets
243  std::vector<bcName_Type> fluxVector = bcH.findAllBCWithType ( Flux );
244  UInt numLM = static_cast<UInt> ( fluxVector.size() );
245 
246  UInt offset = uFESpacePtr->map().map (Unique)->NumGlobalElements()
247  + pFESpacePtr->map().map (Unique)->NumGlobalElements();
248 
249  for ( UInt i = 0; i < numLM; ++i )
250  {
251  bcH.setOffset ( fluxVector[i], offset + i );
252  }
253 
254  // +-----------------------------------------------+
255  // | Creating the problem |
256  // +-----------------------------------------------+
257  if (verbose)
258  {
259  std::cout << std::endl << "[Creating the problem]" << std::endl;
260  }
261  std::shared_ptr< OseenData > oseenData (new OseenData);
262  oseenData->setup ( dataFile );
263 
264 
265  if (verbose)
266  {
267  std::cout << "Time discretization order " << oseenData->dataTimeAdvance()->orderBDF() << std::endl;
268  }
269 
270  // The problem (matrix and rhs) is packed in an object called fluid
271  OseenSolver< mesh_Type > fluid (oseenData,
272  *uFESpacePtr,
273  *pFESpacePtr,
274  comm,
275  numLM);
276 
277  // Gets inputs from the data file
278  fluid.setUp (dataFile);
279 
280  // Assemble the matrices
281  fluid.buildSystem();
282 
283  // Communication map
284  MapEpetra fullMap (fluid.getMap() );
285 
286  // +-----------------------------------------------+
287  // | Initialization of the simulation |
288  // +-----------------------------------------------+
289  if (verbose)
290  {
291  std::cout << std::endl << "[Initialization of the simulation]" << std::endl;
292  }
293  Real dt = oseenData->dataTime()->timeStep();
294  Real t0 = oseenData->dataTime()->initialTime();
295  Real tFinal = oseenData->dataTime()->endTime ();
296 
297  // bdf object to store the previous solutions
299  bdf.setup (oseenData->dataTimeAdvance()->orderBDF() );
300 
301  t0 -= dt * bdf.bdfVelocity().order();
302 
303  vector_Type beta ( fullMap );
304  vector_Type rhs ( fullMap );
305  double alpha = 0.;
306  //MPI_Barrier(MPI_COMM_WORLD);
307 
308  // We get the initial solution using a steady Stokes problem
309  oseenData->dataTime()->setTime (t0);
310 
311  beta *= 0.;
312  rhs *= 0.;
313  fluid.updateSystem (alpha, beta, rhs);
314  fluid.iterate (bcH);
315  bdf.bdfVelocity().setInitialCondition ( *fluid.solution() );
316 
317  Real time = t0 + dt;
318  for ( ; time <= oseenData->dataTime()->initialTime() + dt / 2.; time += dt)
319  {
320  oseenData->dataTime()->setTime (time);
321 
322  fluid.updateSystem (alpha, beta, rhs);
323  fluid.iterate (bcH);
324  bdf.bdfVelocity().shiftRight ( *fluid.solution() );
325  }
326 
327  // We erase the preconditioner build for Stokes
328  // (A new one should be built for Navier-Stokes)
329  fluid.resetPreconditioner();
330 
331  std::shared_ptr< ExporterHDF5<mesh_Type> > exporter;
332 
333  std::string const exporterType = dataFile ( "exporter/type", "ensight");
334 
335  exporter.reset ( new ExporterHDF5<mesh_Type> ( dataFile, "cavity_example" ) );
336  exporter->setPostDir ( "./" ); // This is a test to see if M_post_dir is working
337  exporter->setMeshProcId ( meshPart.meshPartition(), comm->MyPID() );
338 
339  vectorPtr_Type velAndPressure;
340  velAndPressure.reset ( new vector_Type (*fluid.solution(), exporter->mapType() ) );
341 
342  exporter->addVariable ( ExporterData<mesh_Type>::VectorField, "velocity", uFESpacePtr,
343  velAndPressure, UInt (0) );
344 
345  exporter->addVariable ( ExporterData<mesh_Type>::ScalarField, "pressure", pFESpacePtr,
346  velAndPressure, UInt (3 * uFESpacePtr->dof().numTotalDof() ) );
347  exporter->postProcess ( 0 );
348 
349  initChrono.stop();
350  if (verbose)
351  {
352  std::cout << "Initialization time: " << initChrono.diff() << " s." << std::endl;
353  }
354 
355  // +-----------------------------------------------+
356  // | Solving the problem |
357  // +-----------------------------------------------+
358  if (verbose)
359  {
360  std::cout << std::endl << "[Solving the problem]" << std::endl;
361  }
362  int iter = 1;
363 
364  for ( ; time <= tFinal + dt / 2.; time += dt, iter++)
365  {
366 
367  oseenData->dataTime()->setTime (time);
368 
369  if (verbose)
370  {
371  std::cout << "[t = " << oseenData->dataTime()->time() << " s.]" << std::endl;
372  }
373 
374  iterChrono.start();
375 
376  double alpha = bdf.bdfVelocity().coefficientFirstDerivative ( 0 ) / oseenData->dataTime()->timeStep();
377 
378  bdf.bdfVelocity().extrapolation (beta); // Extrapolation for the convective term
379  bdf.bdfVelocity().updateRHSContribution (oseenData->dataTime()->timeStep() );
380  rhs = fluid.matrixMass() * bdf.bdfVelocity().rhsContributionFirstDerivative();
381 
382  fluid.getDisplayer().leaderPrint ("alpha ", alpha);
383  fluid.getDisplayer().leaderPrint ("\n");
384  fluid.getDisplayer().leaderPrint ("norm beta ", beta.norm2() );
385  fluid.getDisplayer().leaderPrint ("\n");
386  fluid.getDisplayer().leaderPrint ("norm rhs ", rhs.norm2() );
387  fluid.getDisplayer().leaderPrint ("\n");
388 
389  fluid.updateSystem ( alpha, beta, rhs );
390  fluid.iterate ( bcH );
391 
392  bdf.bdfVelocity().shiftRight ( *fluid.solution() );
393 
394  // Computation of the error
395  vector_Type vel (uFESpacePtr->map(), Repeated);
396  vector_Type press (pFESpacePtr->map(), Repeated);
397  vector_Type velpressure ( *fluid.solution(), Repeated );
398 
399  velpressure = *fluid.solution();
400  vel.subset (velpressure);
401  press.subset (velpressure, uFESpacePtr->dim() *uFESpacePtr->fieldDim() );
402 
403 
404  bool verbose = (comm->MyPID() == 0);
405 
406 
407  // Exporting the solution
408  *velAndPressure = *fluid.solution();
409  exporter->postProcess ( time );
410 
411  iterChrono.stop();
412  if (verbose)
413  {
414  std::cout << "Iteration time: " << iterChrono.diff() << " s." << std::endl << std::endl;
415  }
416  }
417 
418  globalChrono.stop();
419  if (verbose)
420  {
421  std::cout << "Total simulation time: " << globalChrono.diff() << " s." << std::endl;
422  }
423 
424  exporter->closeFile();
425 
426 #ifdef HAVE_MPI
427  MPI_Finalize();
428 #endif
429 
430  return 0;
431 }
Real fZero(const Real &, const Real &, const Real &, const Real &, const ID &)
const int TOP
Definition: cavity_ns.cpp:73
fluid_Type::vector_Type vector_Type
Definition: cavity_ns.cpp:59
void start()
Start the timer.
Definition: LifeChrono.hpp:93
OseenSolver< mesh_Type > fluid_Type
Definition: cavity_ns.cpp:58
GetPot(const int argc_, char **argv_, const char *FieldSeparator=0x0)
Definition: GetPot.hpp:507
BCHandler - class for handling boundary conditions.
Definition: BCHandler.hpp:100
const int BOTTOM
Definition: cavity_ns.cpp:72
const int FRONT
Definition: cavity_ns.cpp:69
Real lidBC(const Real &, const Real &, const Real &, const Real &, const ID &i)
BCFunctionBase - class that holds the function used for prescribing boundary conditions.
Definition: BCFunction.hpp:77
std::shared_ptr< vector_Type > vectorPtr_Type
Definition: cavity_ns.cpp:60
Epetra_Import const & importer()
Getter for the Epetra_Import.
Definition: MapEpetra.cpp:394
uint32_type ID
IDs.
Definition: LifeV.hpp:194
MeshData - class for handling spatial discretization.
Definition: MeshData.hpp:72
FESpace< mesh_Type, MapEpetra > feSpace_Type
Definition: cavity_ns.cpp:61
double Real
Generic real data.
Definition: LifeV.hpp:175
const int LEFT
Definition: cavity_ns.cpp:70
std::shared_ptr< feSpace_Type > feSpacePtr_Type
Definition: cavity_ns.cpp:62
const std::string operator()(const char *VarName, const char *Default) const
Definition: GetPot.hpp:2045
void stop()
Stop the timer.
Definition: LifeChrono.hpp:100
RegionMesh< LinearTetra > mesh_Type
Definition: cavity_ns.cpp:57
GetPot(const STRING_VECTOR &FileNameList)
Definition: GetPot.hpp:645
const std::string follow(const char *Default, unsigned No, const char *Option,...)
Definition: GetPot.hpp:1510
const int RIGHT
Definition: cavity_ns.cpp:71
int main(int argc, char **argv)
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191
const int BACK
Definition: cavity_ns.cpp:68