LifeV
navier_stokes.hpp
Go to the documentation of this file.
1 /* -*- mode: c++ -*-
2 
3  This file is part of the LifeV library.
4  Copyright (C) 2010 EPFL
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2.1 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful, but
12  WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  USA
20  */
21 /*!
22  @file navierStokes.hpp
23  @author Davide Forti <davide.forti@epfl.ch>
24  @date 2014-02-06
25  */
26 
27 #ifndef NAVIERSTOKES_H
28 #define NAVIERSTOKES_H 1
29 
30 #include <lifev/navier_stokes/solver/OseenSolver.hpp>
31 #include <lifev/core/mesh/ElementShapes.hpp>
32 #include <lifev/core/mesh/MeshData.hpp>
33 #include <lifev/core/array/MatrixEpetra.hpp>
34 #include <lifev/core/array/MapEpetra.hpp>
35 #include <lifev/core/mesh/MeshPartitioner.hpp>
36 #include <lifev/core/mesh/MeshData.hpp>
37 #include <lifev/navier_stokes/solver/OseenData.hpp>
38 #include <lifev/core/fem/FESpace.hpp>
39 #include <lifev/navier_stokes/fem/TimeAdvanceBDFNavierStokes.hpp>
40 #include <lifev/core/filter/ExporterEnsight.hpp>
41 #include <lifev/core/filter/ExporterHDF5.hpp>
42 #include <lifev/core/filter/ExporterVTK.hpp>
43 #include <lifev/core/filter/ExporterEmpty.hpp>
44 #include <lifev/core/mesh/MeshUtility.hpp>
45 #include <lifev/core/filter/PartitionIO.hpp>
46 
47 // Include for boundary conditions
48 #include "functions.hpp"
50 
51 using namespace LifeV;
52 
53 class NavierStokes
54 {
55 
56 public:
57 
59 
61 
62  typedef FESpace< mesh_Type, MapEpetra > feSpace_Type;
63 
65 
67 
69 
71 
73 
74  NavierStokes ( int argc,
75  char** argv,
76  boost::shared_ptr<Epetra_Comm> Comm,
77  const std::string defaultDataName = "data",
78  const std::string outputName = "result");
79 
81 
82  void run();
83 
84 private:
85 
88  std::string M_outputFilename;
89 };
90 
91 
92 using namespace LifeV;
93 
94 NavierStokes::NavierStokes ( int argc,
95  char** argv,
96  boost::shared_ptr<Epetra_Comm> Comm,
97  const std::string defaultDataName,
98  const std::string outputName):
99 M_comm (Comm)
100 {
101  GetPot command_line (argc, argv);
102  std::string data_file_name = command_line.follow (defaultDataName.c_str(), 2, "-f", "--file");
103  M_dataFile.reset(new GetPot ( data_file_name ) );
104  M_outputFilename = outputName;
105 }
106 
107 void NavierStokes::run()
108 {
109  //////////////////////////////////////////////////////////////
110  // Flag to set variable for parallel output on the terminal //
111  //////////////////////////////////////////////////////////////
112 
113  bool verbose = (M_comm->MyPID() == 0);
114 
115  //////////////////////
116  // Loading the mesh //
117  //////////////////////
118 
119  /*
120  MeshData meshData;
121  meshPtr_Type fullMeshPtr ( new mesh_Type ( M_comm ) );
122  meshData.setup (*M_dataFile, "fluid/space_discretization");
123  if (verbose){
124  std::cout << "\n\n[Reading the mesh " << meshData.meshFile() << " ]\n\n";
125  }
126  readMesh (*fullMeshPtr, meshData);
127 
128 
129  if (verbose){
130  std::cout << "\n[Mesh size max : " << MeshUtility::MeshStatistics::computeSize ( *fullMeshPtr ).maxH << " ]\n";
131  }
132  */
133 
134  meshPtr_Type fullMeshPtr ( new mesh_Type ( M_comm ) );
135  regularMesh3D( *fullMeshPtr, 1, 16, 16, 16, false, 2.0, 2.0, 2.0, -1.0, -1.0, -1.0);
136 
137  ///////////////////////////
138  // Partitioning the mesh //
139  ///////////////////////////
140 
141  meshPtr_Type localMeshPtr;
142  if (verbose){
143  std::cout << "\n[Partioning the mesh ]\n\n";
144  }
145  MeshPartitioner< mesh_Type > meshPart (fullMeshPtr, M_comm);
146  localMeshPtr = meshPart.meshPartition();
147  fullMeshPtr.reset();
148 
149  ///////////////////////////
150  // Finite element spaces //
151  ///////////////////////////
152 
153  std::string uOrder = (*M_dataFile)("fluid/space_discretization/vel_order","P1");
154  std::string pOrder = (*M_dataFile)("fluid/space_discretization/pres_order","P1");
155 
156  feSpacePtr_Type uFESpace;
157  uFESpace.reset (new feSpace_Type (localMeshPtr, uOrder, 3, M_comm) );
158 
159  feSpacePtr_Type pFESpace;
160  pFESpace.reset (new feSpace_Type (localMeshPtr, pOrder, 1, M_comm) );
161 
162  UInt totalPressDof = pFESpace->dof().numTotalDof();
163  UInt pressureOffset = uFESpace->fieldDim() * uFESpace->dof().numTotalDof();
164 
165  if (verbose)
166  std::cout << "\n\n[Total Velocity Dof = " << pressureOffset << " ]\n";
167 
168  if (verbose)
169  std::cout << "\n[Total Pressure Dof = " << totalPressDof << " ]\n";
170 
171  /////////////////////////////////////////
172  // Boundary conditions for the problem //
173  /////////////////////////////////////////
174 
175  BCFunctionBase u_dirichlet( exactVelocity );
176  BCFunctionBase u_neumann( normalStress );
177  BCHandler bcH;
178 
179  if (verbose)
180  std::cout << "\n[Setting boundary conditions ] \n";
181 
182  bcH.addBC( "S", 2, Essential, Full, u_dirichlet, 3 );
183  bcH.addBC( "S", 1, Essential, Full, u_dirichlet, 3 );
184  bcH.addBC( "S", 3, Essential, Full, u_dirichlet, 3 );
185  bcH.addBC( "S", 4, Essential, Full, u_dirichlet, 3 );
186  bcH.addBC( "S", 6, Essential, Full, u_dirichlet, 3 );
187  bcH.addBC( "S", 5, Natural, Full, u_neumann, 3 );
188  bcH.bcUpdate ( *localMeshPtr, uFESpace->feBd(), uFESpace->dof() );
189 
190  //////////////////////////
191  // Setting the exporter //
192  //////////////////////////
193 
194  std::string const exporterType = (*M_dataFile)( "exporter/type", "hdf5");
195  exporterPtr_Type exporter;
196 
197  if (verbose)
198  std::cout << "\n[Setting the exporter ] \n";
199 
200  if (exporterType.compare ("hdf5") == 0){
201  exporter.reset ( new ExporterHDF5<mesh_Type > ( *M_dataFile, M_outputFilename ) );
202  exporter->setMeshProcId ( localMeshPtr, M_comm->MyPID() );
203  }
204  else if(exporterType.compare ("vtk") == 0){
205  exporter.reset ( new ExporterVTK<mesh_Type > ( *M_dataFile, M_outputFilename ) );
206  exporter->setMeshProcId ( localMeshPtr, M_comm->MyPID() );
207  }
208 
209  ///////////////////////////
210  // Initialize the solver //
211  ///////////////////////////
212 
213  if (verbose)
214  std::cout << "\n[Initializing the solver ] \n";
215 
216  boost::shared_ptr<OseenData> oseenData (new OseenData() );
217  oseenData->setup ( (*M_dataFile) );
218 
219  OseenSolver< mesh_Type > fluid (oseenData, *uFESpace, *pFESpace, M_comm);
220  MapEpetra fullMap (fluid.getMap() );
221 
222  //////////////////////////////////////////////////
223  // Vectors that will contain the exact solution //
224  //////////////////////////////////////////////////
225 
226  vectorPtr_Type exactPressPtr ( new vector_Type(pFESpace->map(), Repeated) );
227  vectorPtr_Type exactVelPtr ( new vector_Type(uFESpace->map(), Repeated) );
228  pFESpace->interpolate ( static_cast<feSpace_Type::function_Type> ( exactPressure ), *exactPressPtr, 0 );
229  uFESpace->interpolate ( static_cast<feSpace_Type::function_Type> ( exactVelocity ), *exactVelPtr, 0 );
230 
231  /////////////////////////////////////////////////////
232  // Vector that will contain the numerical solution //
233  /////////////////////////////////////////////////////
234 
235  vectorPtr_Type velAndPressure ( new vector_Type (fullMap, exporter->mapType() ) );
236 
237  exporter->addVariable ( ExporterData<mesh_Type>::VectorField, "u", uFESpace, velAndPressure, UInt (0) );
238  exporter->addVariable ( ExporterData<mesh_Type>::ScalarField, "p", pFESpace, velAndPressure, pressureOffset );
239  exporter->addVariable ( ExporterData<mesh_Type>::VectorField, "u_exact", uFESpace, exactVelPtr, UInt (0) );
240  exporter->addVariable ( ExporterData<mesh_Type>::ScalarField, "p_exact", pFESpace, exactPressPtr, UInt (0) );
241  exporter->postProcess ( 0 );
242 
243 
244  ///////////////////////////////
245  // Initialize the simulation //
246  ///////////////////////////////
247 
248  // Building the constant matrices of Navier-Stokes
249  fluid.setUp (*M_dataFile);
250  fluid.buildSystem();
251 
252  Real dt = oseenData->dataTime()->timeStep();
253  Real t0 = oseenData->dataTime()->initialTime();
254  Real tFinal = oseenData->dataTime()->endTime();
255 
256  oseenData->dataTime()->setTime (t0);
257 
259  bdf.setup (oseenData->dataTimeAdvance()->orderBDF() );
260 
261  // For the moment just using interpolation
262  std::vector<vectorPtr_Type> solutionStencil;
263  solutionStencil.resize ( bdf.bdfVelocity().size() );
264  for ( UInt i(0); i < bdf.bdfVelocity().size() ; ++i){
265  *exactVelPtr *= 0;
266  *velAndPressure *= 0;
267  uFESpace->interpolate ( static_cast<feSpace_Type::function_Type> ( exactVelocity ), *exactVelPtr, t0-i*dt );
268  velAndPressure->subset(*exactVelPtr, uFESpace->map(), 0, 0);
269  solutionStencil[ i ] = velAndPressure;
270  }
271 
272  bdf.bdfVelocity().setInitialCondition (solutionStencil);
273 
274  Real alphaOverDt = bdf.bdfVelocity().coefficientFirstDerivative ( 0 ) / oseenData->dataTime()->timeStep();
275 
276  vector_Type u_star ( fullMap ); // extrapolated velocity
277 
278  vector_Type rhs ( fullMap ); // right hand side
279 
280  int iter = 1;
281 
282  Real time = t0 + dt;
283 
284  Real L2ErrorVelocity, H1ErrorVelocity, L2ErrorPressure;
285 
286  for ( ; time <= tFinal + dt / 2.; time += dt, iter++){
287 
288  if (verbose)
289  std::cout << "\n [Solving for time = " << time << " ] \n";
290 
291  oseenData->dataTime()->setTime (time);
292 
293  // extrapolate the velocity
294  bdf.bdfVelocity().extrapolation (u_star);
295 
296  // update the right hand side term
297  bdf.bdfVelocity().updateRHSContribution(dt);
298 
299  fluid.setVelocityRhs(bdf.bdfVelocity().rhsContributionFirstDerivative());
300 
301  // compute the right hand side, it contains just the term associated to the previous timesteps
302  // CAUTION: the vector bdf.bdfVelocity().rhsContributionFirstDerivative() is already divided by the timestep
303  rhs = fluid.matrixMass() * bdf.bdfVelocity().rhsContributionFirstDerivative();
304 
305  // update the convective term of the Navier Stokes matrix and set the right hand side in the solver
306  fluid.updateSystem ( alphaOverDt, u_star, rhs );
307 
308  // apply boundary conditions and solving the linear system
309  fluid.iterate ( bcH );
310 
311  // shifting right the computed solution in the time-advance stencil
312  bdf.bdfVelocity().shiftRight ( *fluid.solution() );
313 
314  // copy the solution for the postprocessing
315  *velAndPressure = *fluid.solution();
316 
317  // evaluate the exact fluid velocity and pressure at the current time
318  pFESpace->interpolate ( static_cast<typename feSpace_Type::function_Type> ( exactPressure ), *exactPressPtr, time );
319  uFESpace->interpolate ( static_cast<typename feSpace_Type::function_Type> ( exactVelocity ), *exactVelPtr, time );
320 
321  //////////////////////////////
322  // Evaluation of the errors //
323  //////////////////////////////
324 
325  vector_Type uComputed ( uFESpace->map() , Repeated );
326  uComputed.subset( *fluid.solution() );
327 
328  vector_Type pComputed ( pFESpace->map() , Repeated );
329  pComputed.subset( *fluid.solution(), uFESpace->dim() *uFESpace->fieldDim());
330 
331  AnalyticalSolution solutionAnal;
332 
333  // compute l2 norm of the error for the velocity
334  L2ErrorVelocity = uFESpace->l2Error(exactVelocity, uComputed, time);
335 
336  // compute h1 norm of the error for the velocity
337  H1ErrorVelocity = uFESpace->h1Error(solutionAnal, uComputed, time);
338 
339  // compute l2 norm of the error for the pressure
340  L2ErrorPressure = pFESpace->l20Error(exactPressure, pComputed, time);
341 
342  if (verbose){
343  std::cout << "\n [L2 error velocity = " << L2ErrorVelocity << " ] \n";
344  std::cout << "\n [H1 error velocity = " << H1ErrorVelocity << " ] \n";
345  std::cout << "\n [L2 error pressure = " << L2ErrorPressure << " ] \n\n";
346  }
347 
348  // postprocessing
349  exporter->postProcess ( time );
350 
351  }
352 }
353 
354 #endif /* NAVIERSTOKES_H */
VectorEpetra - The Epetra Vector format Wrapper.
VectorEpetra vector_Type
boost::shared_ptr< mesh_Type > meshPtr_Type
OseenSolver< mesh_Type > fluid_Type
std::string M_outputFilename
GetPot(const int argc_, char **argv_, const char *FieldSeparator=0x0)
Definition: GetPot.hpp:507
BCHandler - class for handling boundary conditions.
Definition: BCHandler.hpp:100
boost::shared_ptr< vector_Type > vectorPtr_Type
boost::shared_ptr< Exporter< mesh_Type > > exporterPtr_Type
VectorEpetra(const MapEpetra &map, const MapEpetraType &mapType=Unique, const combineMode_Type combineMode=Add)
Constructor - Using Maps.
BCFunctionBase - class that holds the function used for prescribing boundary conditions.
Definition: BCFunction.hpp:77
FESpace< mesh_Type, MapEpetra > feSpace_Type
Epetra_Import const & importer()
Getter for the Epetra_Import.
Definition: MapEpetra.cpp:394
boost::shared_ptr< GetPot > M_dataFile
RegionMesh< LinearTetra > mesh_Type
NavierStokes(int argc, char **argv, boost::shared_ptr< Epetra_Comm > Comm, const std::string defaultDataName="data", const std::string outputName="result")
double Real
Generic real data.
Definition: LifeV.hpp:175
boost::shared_ptr< feSpace_Type > feSpacePtr_Type
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191
boost::shared_ptr< Epetra_Comm > M_comm