LifeV
lifev/core/testsuite/linear_solver_preconditioner/main.cpp
Go to the documentation of this file.
1 //@HEADER
2 /*
3 *******************************************************************************
4 
5  Copyright (C) 2004, 2005, 2007 EPFL, Politecnico di Milano, INRIA
6  Copyright (C) 2010 EPFL, Politecnico di Milano, Emory University
7 
8  This file is part of LifeV.
9 
10  LifeV is free software; you can redistribute it and/or modify
11  it under the terms of the GNU Lesser General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14 
15  LifeV is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with LifeV. If not, see <http://www.gnu.org/licenses/>.
22 
23 *******************************************************************************
24 */
25 //@HEADER
26 
27 /*!
28  @file
29  @brief
30 
31  @author Gwenol Grandperrin <gwenol.grandperrin@epfl.ch>
32  @date 30-03-2011
33  */
34 
35 
36 #include <Epetra_ConfigDefs.h>
37 #ifdef EPETRA_MPI
38 #include <mpi.h>
39 #include <Epetra_MpiComm.h>
40 #else
41 #include <Epetra_SerialComm.h>
42 #endif
43 
44 #include <Teuchos_ParameterList.hpp>
45 #include <Teuchos_XMLParameterListHelpers.hpp>
46 #include <Teuchos_RCP.hpp>
47 
48 
49 #include <lifev/core/LifeV.hpp>
50 #include <lifev/core/mesh/RegionMesh3DStructured.hpp>
51 #include <lifev/core/mesh/MeshData.hpp>
52 #include <lifev/core/mesh/RegionMesh.hpp>
53 #include <lifev/core/mesh/MeshUtility.hpp>
54 #include <lifev/core/mesh/MeshPartitioner.hpp>
55 #include <lifev/core/fem/FESpace.hpp>
56 #include <lifev/core/fem/BCManage.hpp>
57 #include <lifev/core/array/MatrixEpetra.hpp>
58 #include <lifev/core/solver/ADRAssembler.hpp>
59 #include <lifev/core/algorithm/PreconditionerLinearSolver.hpp>
60 #include <lifev/core/algorithm/SolverAztecOO.hpp>
61 #include <lifev/core/algorithm/LinearSolver.hpp>
62 #include <lifev/core/function/Laplacian.hpp>
63 
64 #define TEST_TOLERANCE 1e-13
65 
66 using namespace LifeV;
67 
68 namespace
69 {
72 typedef MatrixEpetra<Real> matrix_Type;
73 typedef VectorEpetra vector_Type;
75 typedef FESpace< mesh_Type, MapEpetra > fespace_Type;
77 
78 typedef LifeV::Preconditioner basePrec_Type;
80 typedef LifeV::PreconditionerLinearSolver prec_Type;
82 typedef std::function < Real ( Real const&,
83  Real const&,
84  Real const&,
85  Real const&,
86  UInt const& ) > function_Type;
87 }
88 
89 void printErrors ( const vector_Type& solution, fespacePtr_Type uFESpace, bool verbose )
90 {
91  vector_Type velocity ( solution, Repeated );
92  Real uRelativeError, uL2Error;
93  uL2Error = uFESpace->l2Error (Laplacian::uexact, velocity, 0, &uRelativeError );
94  if ( verbose )
95  {
96  std::cout << "Velocity" << std::endl;
97  }
98  if ( verbose )
99  {
100  std::cout << " L2 error : " << uL2Error << std::endl;
101  }
102  if ( verbose )
103  {
104  std::cout << " Relative error: " << uRelativeError << std::endl;
105  }
106 }
107 
108 
109 int
110 main ( int argc, char** argv )
111 {
112  // +-----------------------------------------------+
113  // | Initialization of MPI |
114  // +-----------------------------------------------+
115 #ifdef HAVE_MPI
116  MPI_Init (&argc, &argv);
117 #endif
118  int exit_status;
119  bool verbose ( true );
120 
121  {
122 
123 #ifdef HAVE_MPI
124  std::shared_ptr<Epetra_Comm> Comm ( new Epetra_MpiComm ( MPI_COMM_WORLD ) );
125 #else
126  std::shared_ptr<Epetra_Comm> Comm ( new Epetra_SerialComm );
127 #endif
128 
129  verbose = (Comm->MyPID() == 0);
130 
131  if ( verbose )
132  {
133  std::cout
134  << " +-----------------------------------------------+" << std::endl
135  << " | LinearSolverPreconditioner Test |" << std::endl
136  << " +-----------------------------------------------+" << std::endl
137  << std::endl
138  << " +-----------------------------------------------+" << std::endl
139  << " | Author: Gwenol Grandperrin |" << std::endl
140  << " | Date: 2013-01-16 |" << std::endl
141  << " +-----------------------------------------------+" << std::endl
142  << std::endl;
143 
144  std::cout << "[Initilization of MPI]" << std::endl;
145 #ifdef HAVE_MPI
146  std::cout << "Using MPI (" << Comm->NumProc() << " proc.)" << std::endl;
147 #else
148  std::cout << "Using serial version" << std::endl;
149 #endif
150  }
151 
152  // +-----------------------------------------------+
153  // | Loading the data |
154  // +-----------------------------------------------+
155  if ( verbose )
156  {
157  std::cout << std::endl << "[Loading the data]" << std::endl;
158  }
159  LifeChrono globalChrono;
160 
161  globalChrono.start();
162 
163  // ********** GetPot **********
164  GetPot command_line ( argc, argv );
165  const std::string dataFileName = command_line.follow ( "data", 2, "-f", "--file" );
166  GetPot dataFile ( dataFileName );
167  // ****************************
168 
169  // Space discretization
170  const UInt numMeshElem = dataFile ( "mesh/num_elements", 10);
171  const std::string uOrder = dataFile ( "finite_element/velocity", "P1" );
172 
173  // Solution initialization
174  Laplacian::setModes ( 1, 1, 1 );
175 
176  // +-----------------------------------------------+
177  // | Loading the mesh |
178  // +-----------------------------------------------+
179  if ( verbose )
180  {
181  std::cout << std::endl << "[Loading the mesh]" << std::endl;
182  }
183 
184  meshPtr_Type fullMeshPtr ( new mesh_Type );
185  const UInt& geoDim = static_cast<UInt> ( mesh_Type::S_geoDimensions );
186 
187 
188  // Building the mesh from the source
189 
190  regularMesh3D ( *fullMeshPtr,
191  1,
192  numMeshElem, numMeshElem, numMeshElem,
193  false,
194  1.0, 1.0, 1.0,
195  0.0, 0.0, 0.0 );
196 
197  if ( verbose ) std::cout << "Mesh source: regular mesh("
198  << numMeshElem << "x" << numMeshElem << "x" << numMeshElem << ")" << std::endl;
199 
200  if ( verbose )
201  {
202  std::cout << "Mesh size : " << MeshUtility::MeshStatistics::computeSize ( *fullMeshPtr ).maxH << std::endl;
203  }
204  if ( verbose )
205  {
206  std::cout << "Partitioning the mesh ... " << std::endl;
207  }
208 
209  meshPtr_Type meshPtr;
210  {
211  MeshPartitioner< mesh_Type > meshPart ( fullMeshPtr, Comm );
212  meshPtr = meshPart.meshPartition();
213  }
214  fullMeshPtr.reset(); //Freeing the global mesh to save memory
215 
216  // +-----------------------------------------------+
217  // | Creating the FE spaces |
218  // +-----------------------------------------------+
219  if ( verbose )
220  {
221  std::cout << std::endl << "[Creating the FE spaces]" << std::endl;
222  }
223  if ( verbose )
224  {
225  std::cout << "FE for the velocity: " << uOrder << std::endl;
226  }
227 
228  if ( verbose )
229  {
230  std::cout << "Building the velocity FE space ... " << std::flush;
231  }
232  fespacePtr_Type uFESpace ( new fespace_Type ( meshPtr, uOrder, geoDim, Comm ) );
233  if ( verbose )
234  {
235  std::cout << "ok." << std::endl;
236  }
237 
238  // Pressure offset in the vector
239  UInt numDofs = geoDim * uFESpace->dof().numTotalDof();
240 
241  if ( verbose )
242  {
243  std::cout << "Total Velocity Dof: " << numDofs << std::endl;
244  }
245 
246  // +-----------------------------------------------+
247  // | Boundary conditions |
248  // +-----------------------------------------------+
249  if ( verbose )
250  {
251  std::cout << std::endl << "[Boundary conditions]" << std::endl;
252  }
253  BCHandler bcHandler;
254  BCFunctionBase uExact ( Laplacian::uexact );
255  BCFunctionBase fRHS ( Laplacian::f );
256 
257  if ( verbose )
258  {
259  std::cout << "Setting Dirichlet BC... " << std::flush;
260  }
261  for ( UInt iDirichlet ( 1 ); iDirichlet <= 26; ++iDirichlet )
262  {
263  bcHandler.addBC ( "Wall", iDirichlet, Essential, Full, uExact, geoDim );
264  }
265  if ( verbose )
266  {
267  std::cout << "ok." << std::endl;
268  }
269 
270  // Update the BCHandler (internal data related to FE)
271  bcHandler.bcUpdate ( *uFESpace->mesh(), uFESpace->feBd(), uFESpace->dof() );
272 
273  // +-----------------------------------------------+
274  // | Matrices Assembly |
275  // +-----------------------------------------------+
276  if ( verbose )
277  {
278  std::cout << std::endl << "[Matrices Assembly]" << std::endl;
279  }
280 
281  if ( verbose )
282  {
283  std::cout << "Setting up assembler... " << std::flush;
284  }
285  ADRAssembler<mesh_Type, matrix_Type, vector_Type> adrAssembler;
286  adrAssembler.setup ( uFESpace, uFESpace );
287  if ( verbose )
288  {
289  std::cout << "done" << std::endl;
290  }
291 
292  if ( verbose )
293  {
294  std::cout << "Defining the matrices... " << std::flush;
295  }
296  std::shared_ptr<matrix_Type> systemMatrix ( new matrix_Type ( uFESpace->map() ) );
297  if ( verbose )
298  {
299  std::cout << "done" << std::endl;
300  }
301 
302  if ( verbose )
303  {
304  std::cout << "Adding the viscous stress... " << std::flush;
305  }
306  adrAssembler.addDiffusion ( systemMatrix, 1.0 );
307  if ( verbose )
308  {
309  std::cout << "done" << std::endl;
310  }
311 
312  // +-----------------------------------------------+
313  // | Solver initialization |
314  // +-----------------------------------------------+
315  if ( verbose )
316  {
317  std::cout << std::endl << "[Solvers initialization]" << std::endl;
318  }
319  prec_Type* precRawPtr;
320  basePrecPtr_Type precPtr;
321  precRawPtr = new prec_Type;
322  precRawPtr->setDataFromGetPot ( dataFile, "prec/LinearSolver" );
323  precPtr.reset ( precRawPtr );
324 
325  if ( verbose )
326  {
327  std::cout << "Setting up LinearSolver (Belos)... " << std::flush;
328  }
329  Teuchos::RCP< Teuchos::ParameterList > belosList = Teuchos::rcp ( new Teuchos::ParameterList );
330  belosList = Teuchos::getParametersFromXmlFile ( "SolverParamList.xml" );
331 
332  LinearSolver linearSolver;
333  linearSolver.setCommunicator ( Comm );
334  linearSolver.setParameters ( *belosList );
335  linearSolver.setPreconditioner ( precPtr );
336  if ( verbose )
337  {
338  std::cout << "done" << std::endl;
339  }
340  linearSolver.showMe();
341 
342  // +-----------------------------------------------+
343  // | Simulation |
344  // +-----------------------------------------------+
345  if ( verbose )
346  {
347  std::cout << std::endl << "[Initialization of the simulation]" << std::endl;
348  }
349  if ( verbose )
350  {
351  std::cout << "Creation of vectors... " << std::flush;
352  }
353 
354  std::shared_ptr<vector_Type> rhs;
355  rhs.reset ( new vector_Type ( uFESpace->map(), Repeated ) );
356 
357  vector_Type fInterpolated ( uFESpace->map(), Repeated );
358  adrAssembler.addMassRhs ( *rhs, fRHS, 0.0 );
359  rhs->globalAssemble();
360  if ( verbose )
361  {
362  std::cout << "done" << std::endl;
363  }
364 
365  fInterpolated = 0.0;
366  uFESpace->interpolate ( uExact, fInterpolated, 0.0 );
367 
368 
369  if ( verbose )
370  {
371  std::cout << "Applying BC... " << std::flush;
372  }
373  systemMatrix->globalAssemble();
374  std::shared_ptr<vector_Type> rhsBC;
375  rhsBC.reset ( new vector_Type ( *rhs, Unique ) );
376  bcManage ( *systemMatrix, *rhsBC, *uFESpace->mesh(), uFESpace->dof(), bcHandler, uFESpace->feBd(), 1.0, 0.0 );
377  if ( verbose )
378  {
379  std::cout << "done" << std::endl;
380  }
381 
382  if ( verbose )
383  {
384  std::cout << std::endl << "Solving the system with LinearSolver (Belos)... " << std::endl;
385  }
386  std::shared_ptr<vector_Type> solution;
387  solution.reset ( new vector_Type ( uFESpace->map(), Unique ) );
388  linearSolver.setOperator ( systemMatrix );
389  linearSolver.setRightHandSide ( rhsBC );
390  linearSolver.solve ( solution );
391 
392  // +-----------------------------------------------+
393  // | Computing the error |
394  // +-----------------------------------------------+
395  if ( verbose )
396  {
397  std::cout << std::endl << "[Errors computation]" << std::endl;
398  }
399 
400  vector_Type solution2Err ( *solution );
401  solution2Err *= 0.0;
402  uFESpace->interpolate ( static_cast<function_Type> ( Laplacian::uexact ), solution2Err, 0.0 );
403  solution2Err -= *solution;
404  solution2Err.abs();
405 
406  if ( verbose )
407  {
408  std::cout << "Linear solver Belos" << std::endl;
409  }
410  printErrors ( *solution, uFESpace, verbose );
411 
412  // +-----------------------------------------------+
413  // | Ending the simulation |
414  // +-----------------------------------------------+
415  globalChrono.stop();
416  if ( verbose )
417  {
418  std::cout << std::endl << "Total simulation time: " << globalChrono.diff() << " s." << std::endl;
419  }
420  if ( verbose )
421  {
422  std::cout << std::endl << "[[END_SIMULATION]]" << std::endl;
423  }
424 
425  exit_status = (linearSolver.numIterations() >= 6 || precRawPtr->solverPtr()->numIterations() >= 8);
426 
427  }
428 
429 #ifdef HAVE_MPI
430  MPI_Finalize();
431 #endif
432 
433  if ( exit_status )
434  {
435  if ( verbose )
436  {
437  std::cout << "The number of iterations has changed." << std::endl;
438  }
439  if ( verbose )
440  {
441  std::cout << "Test status: FAILED" << std::endl;
442  }
443  return ( EXIT_FAILURE );
444  }
445 
446 
447  if ( verbose )
448  {
449  std::cout << "Test status: SUCCESS" << std::endl;
450  }
451 
452  return ( EXIT_SUCCESS );
453 }
FESpace - Short description here please!
Definition: FESpace.hpp:78
void printErrors(const vector_Type &solution, fespacePtr_Type uFESpace, bool verbose)
double Real
Generic real data.
Definition: LifeV.hpp:175
int main(int argc, char **argv)
std::function< Real(Real const &, Real const &, Real const &, Real const &, UInt const &) > function_Type