LifeV
lifev/core/testsuite/linear_solver/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/PreconditionerIfpack.hpp>
60 #include <lifev/core/algorithm/SolverAztecOO.hpp>
61 #include <lifev/core/algorithm/LinearSolver.hpp>
62 #include <lifev/core/function/Laplacian.hpp>
63 
64 
65 #define TEST_TOLERANCE 1e-13
66 
67 using namespace LifeV;
68 
69 namespace
70 {
73 typedef MatrixEpetra<Real> matrix_Type;
74 typedef VectorEpetra vector_Type;
76 typedef FESpace< mesh_Type, MapEpetra > fespace_Type;
78 
79 typedef LifeV::Preconditioner basePrec_Type;
81 typedef LifeV::PreconditionerIfpack prec_Type;
83 typedef std::function < Real ( Real const&,
84  Real const&,
85  Real const&,
86  Real const&,
87  UInt const& ) > function_Type;
88 }
89 
90 class ExactSol
91 {
92 public:
93  Real operator() (const Real& t , const Real& x, const Real& y, const Real& z, const ID& i ) const
94  {
95  return Laplacian::uexact (t, x, y, z, i);
96  }
97 
98  Real grad ( const ID& iCoor, const Real& t, const Real& x, const Real& y,
99  const Real& z, const ID& i ) const
100  {
101  switch (iCoor)
102  {
103  case 0:
104  return Laplacian::duexactdx ( t, x, y, z, i );
105  case 1:
106  return Laplacian::duexactdy ( t, x, y, z, i );
107  case 2:
108  return Laplacian::duexactdz ( t, x, y, z, i );
109  default:
110  return 0;
111  }
112  return 0;
113  }
114 
115 };
116 
117 
118 void printErrors ( const vector_Type& solution, fespacePtr_Type uFESpace,
119  Real& uL2Error, Real& uH1Error, bool verbose )
120 {
121  ExactSol exactU;
122 
123 
124  vector_Type velocity ( solution, Repeated );
125  Real uRelativeError;
126  uL2Error = uFESpace->l2Error (exactU, velocity, 0, &uRelativeError );
127  Real uH1RelativeError;
128  uH1Error = uFESpace->h1Error (exactU, velocity, 0, &uH1RelativeError );
129 
130  if ( verbose )
131  {
132  std::cout << "Velocity" << std::endl;
133  }
134  if ( verbose )
135  {
136  std::cout << " L2 error : " << uL2Error << std::endl;
137  }
138  if ( verbose )
139  {
140  std::cout << " Relative error: " << uRelativeError << std::endl;
141  }
142  if ( verbose )
143  {
144  std::cout << " H1 error : " << uH1Error << std::endl;
145  }
146  if ( verbose )
147  {
148  std::cout << " Relative error: " << uH1RelativeError << std::endl;
149  }
150 }
151 
152 
153 int
154 main ( int argc, char** argv )
155 {
156  // +-----------------------------------------------+
157  // | Initialization of MPI |
158  // +-----------------------------------------------+
159 #ifdef HAVE_MPI
160  MPI_Init (&argc, &argv);
161 #endif
162 
163  {
164 
165 #ifdef HAVE_MPI
166  std::shared_ptr<Epetra_Comm> Comm ( new Epetra_MpiComm ( MPI_COMM_WORLD ) );
167 #else
168  std::shared_ptr<Epetra_Comm> Comm ( new Epetra_SerialComm );
169 #endif
170 
171  const bool verbose ( Comm->MyPID() == 0 );
172  if ( verbose )
173  {
174  std::cout
175  << " +-----------------------------------------------+" << std::endl
176  << " | LinearSolver Test |" << std::endl
177  << " +-----------------------------------------------+" << std::endl
178  << std::endl
179  << " +-----------------------------------------------+" << std::endl
180  << " | Author: Gwenol Grandperrin |" << std::endl
181  << " | Date: 2010-08-03 |" << std::endl
182  << " +-----------------------------------------------+" << std::endl
183  << std::endl;
184 
185  std::cout << "[Initilization of MPI]" << std::endl;
186 #ifdef HAVE_MPI
187  std::cout << "Using MPI (" << Comm->NumProc() << " proc.)" << std::endl;
188 #else
189  std::cout << "Using serial version" << std::endl;
190 #endif
191  }
192 
193  // +-----------------------------------------------+
194  // | Loading the data |
195  // +-----------------------------------------------+
196  if ( verbose )
197  {
198  std::cout << std::endl << "[Loading the data]" << std::endl;
199  }
200  LifeChrono globalChrono;
201 
202  globalChrono.start();
203 
204  // ********** GetPot **********
205  GetPot command_line ( argc, argv );
206  const std::string dataFileName = command_line.follow ( "data", 2, "-f", "--file" );
207  GetPot dataFile ( dataFileName );
208  // ****************************
209 
210  // Space discretization
211  const UInt numMeshElem = dataFile ( "mesh/num_elements", 10);
212  const std::string uOrder = dataFile ( "finite_element/velocity", "P1" );
213 
214  // Solution initialization
215  Laplacian::setModes ( 1, 1, 1 );
216 
217  // +-----------------------------------------------+
218  // | Loading the mesh |
219  // +-----------------------------------------------+
220  if ( verbose )
221  {
222  std::cout << std::endl << "[Loading the mesh]" << std::endl;
223  }
224 
225  meshPtr_Type fullMeshPtr ( new mesh_Type ( Comm ) );
226  const UInt& geoDim = static_cast<UInt> ( mesh_Type::S_geoDimensions );
227 
228 
229  // Building the mesh from the source
230 
231  regularMesh3D ( *fullMeshPtr,
232  1,
233  numMeshElem, numMeshElem, numMeshElem,
234  false,
235  1.0, 1.0, 1.0,
236  0.0, 0.0, 0.0 );
237 
238  if ( verbose ) std::cout << "Mesh source: regular mesh("
239  << numMeshElem << "x" << numMeshElem << "x" << numMeshElem << ")" << std::endl;
240 
241  if ( verbose )
242  {
243  std::cout << "Mesh size : " << MeshUtility::MeshStatistics::computeSize ( *fullMeshPtr ).maxH << std::endl;
244  }
245  if ( verbose )
246  {
247  std::cout << "Partitioning the mesh ... " << std::endl;
248  }
249  meshPtr_Type meshPtr;
250  {
251  MeshPartitioner< mesh_Type > meshPart ( fullMeshPtr, Comm );
252  meshPtr = meshPart.meshPartition();
253  }
254  fullMeshPtr.reset(); //Freeing the global mesh to save memory
255 
256  // +-----------------------------------------------+
257  // | Creating the FE spaces |
258  // +-----------------------------------------------+
259  if ( verbose )
260  {
261  std::cout << std::endl << "[Creating the FE spaces]" << std::endl;
262  }
263  if ( verbose )
264  {
265  std::cout << "FE for the velocity: " << uOrder << std::endl;
266  }
267 
268  if ( verbose )
269  {
270  std::cout << "Building the velocity FE space ... " << std::flush;
271  }
272  fespacePtr_Type uFESpace ( new fespace_Type ( meshPtr, uOrder, geoDim, Comm ) );
273  if ( verbose )
274  {
275  std::cout << "ok." << std::endl;
276  }
277 
278  // Pressure offset in the vector
279  UInt numDofs = geoDim * uFESpace->dof().numTotalDof();
280 
281  if ( verbose )
282  {
283  std::cout << "Total Velocity Dof: " << numDofs << std::endl;
284  }
285 
286  // +-----------------------------------------------+
287  // | Boundary conditions |
288  // +-----------------------------------------------+
289  if ( verbose )
290  {
291  std::cout << std::endl << "[Boundary conditions]" << std::endl;
292  }
293  BCHandler bcHandler;
294  BCFunctionBase uExact ( Laplacian::uexact );
295  BCFunctionBase fRHS ( Laplacian::f );
296 
297  if ( verbose )
298  {
299  std::cout << "Setting Dirichlet BC... " << std::flush;
300  }
301  for ( UInt iDirichlet ( 1 ); iDirichlet <= 26; ++iDirichlet )
302  {
303  bcHandler.addBC ( "Wall", iDirichlet, Essential, Full, uExact, geoDim );
304  }
305  if ( verbose )
306  {
307  std::cout << "ok." << std::endl;
308  }
309 
310  // Update the BCHandler (internal data related to FE)
311  bcHandler.bcUpdate ( *uFESpace->mesh(), uFESpace->feBd(), uFESpace->dof() );
312 
313  // +-----------------------------------------------+
314  // | Matrices Assembly |
315  // +-----------------------------------------------+
316  if ( verbose )
317  {
318  std::cout << std::endl << "[Matrices Assembly]" << std::endl;
319  }
320 
321  if ( verbose )
322  {
323  std::cout << "Setting up assembler... " << std::flush;
324  }
325  ADRAssembler<mesh_Type, matrix_Type, vector_Type> adrAssembler;
326  adrAssembler.setup ( uFESpace, uFESpace );
327  if ( verbose )
328  {
329  std::cout << "done" << std::endl;
330  }
331 
332  if ( verbose )
333  {
334  std::cout << "Defining the matrices... " << std::flush;
335  }
336  std::shared_ptr<matrix_Type> systemMatrix ( new matrix_Type ( uFESpace->map() ) );
337  if ( verbose )
338  {
339  std::cout << "done" << std::endl;
340  }
341 
342  if ( verbose )
343  {
344  std::cout << "Adding the viscous stress... " << std::flush;
345  }
346  adrAssembler.addDiffusion ( systemMatrix, 1.0 );
347  if ( verbose )
348  {
349  std::cout << "done" << std::endl;
350  }
351 
352  // +-----------------------------------------------+
353  // | Solver initialization |
354  // +-----------------------------------------------+
355  if ( verbose )
356  {
357  std::cout << std::endl << "[Solvers initialization]" << std::endl;
358  }
359  prec_Type* precRawPtr;
360  basePrecPtr_Type precPtr;
361  precRawPtr = new prec_Type;
362  precRawPtr->setDataFromGetPot ( dataFile, "prec" );
363  precPtr.reset ( precRawPtr );
364 
365  if ( verbose )
366  {
367  std::cout << "Setting up SolverAztecOO... " << std::flush;
368  }
369  SolverAztecOO linearSolver1;
370  linearSolver1.setCommunicator ( Comm );
371  linearSolver1.setDataFromGetPot ( dataFile, "solver" );
372  linearSolver1.setTolerance ( 1e-10 );
373  linearSolver1.setPreconditioner ( precPtr );
374  if ( verbose )
375  {
376  std::cout << "done" << std::endl;
377  }
378 
379  if ( verbose )
380  {
381  std::cout << "Setting up LinearSolver (Belos)... " << std::flush;
382  }
383  Teuchos::RCP< Teuchos::ParameterList > belosList2 = Teuchos::rcp ( new Teuchos::ParameterList );
384  belosList2 = Teuchos::getParametersFromXmlFile ( "SolverParamList2.xml" );
385 
386  LinearSolver linearSolver2;
387  linearSolver2.setCommunicator ( Comm );
388  linearSolver2.setParameters ( *belosList2 );
389  linearSolver2.setPreconditioner ( precPtr );
390  if ( verbose )
391  {
392  std::cout << "done" << std::endl;
393  }
394  linearSolver2.showMe();
395 
396  if ( verbose )
397  {
398  std::cout << "Setting up LinearSolver (AztecOO)... " << std::flush;
399  }
400  Teuchos::RCP< Teuchos::ParameterList > belosList3 = Teuchos::rcp ( new Teuchos::ParameterList );
401  belosList3 = Teuchos::getParametersFromXmlFile ( "SolverParamList3.xml" );
402 
403  LinearSolver linearSolver3;
404  linearSolver3.setCommunicator ( Comm );
405  linearSolver3.setParameters ( *belosList3 );
406  linearSolver3.setPreconditioner ( precPtr );
407  if ( verbose )
408  {
409  std::cout << "done" << std::endl;
410  }
411  linearSolver3.showMe();
412 
413  // +-----------------------------------------------+
414  // | Simulation |
415  // +-----------------------------------------------+
416  if ( verbose )
417  {
418  std::cout << std::endl << "[Initialization of the simulation]" << std::endl;
419  }
420  if ( verbose )
421  {
422  std::cout << "Creation of vectors... " << std::flush;
423  }
424 
425  std::shared_ptr<vector_Type> rhs;
426  rhs.reset ( new vector_Type ( uFESpace->map(), Repeated ) );
427 
428  vector_Type fInterpolated ( uFESpace->map(), Repeated );
429  adrAssembler.addMassRhs ( *rhs, fRHS, 0.0 );
430  rhs->globalAssemble();
431  if ( verbose )
432  {
433  std::cout << "done" << std::endl;
434  }
435 
436  fInterpolated = 0.0;
437  uFESpace->interpolate ( uExact, fInterpolated, 0.0 );
438 
439 
440  if ( verbose )
441  {
442  std::cout << "Applying BC... " << std::flush;
443  }
444  systemMatrix->globalAssemble();
445  std::shared_ptr<vector_Type> rhsBC;
446  rhsBC.reset ( new vector_Type ( *rhs, Unique ) );
447  bcManage ( *systemMatrix, *rhsBC, *uFESpace->mesh(), uFESpace->dof(), bcHandler, uFESpace->feBd(), 1.0, 0.0 );
448  if ( verbose )
449  {
450  std::cout << "done" << std::endl;
451  }
452 
453  if ( verbose )
454  {
455  std::cout << std::endl << "Solving the system with SolverAztec00... " << std::endl;
456  }
457  std::shared_ptr<vector_Type> solution;
458  solution.reset ( new vector_Type ( uFESpace->map(), Unique ) );
459  linearSolver1.setMatrix ( *systemMatrix );
460  linearSolver1.solveSystem ( *rhsBC, *solution, systemMatrix );
461 
462  if ( verbose )
463  {
464  std::cout << std::endl << "Solving the system with LinearSolver (Belos)... " << std::endl;
465  }
466  std::shared_ptr<vector_Type> solution2;
467  solution2.reset ( new vector_Type ( uFESpace->map(), Unique ) );
468  linearSolver2.setOperator ( systemMatrix );
469  linearSolver2.setRightHandSide ( rhsBC );
470  linearSolver2.solve ( solution2 );
471 
472  if ( verbose )
473  {
474  std::cout << std::endl << "Solving the system with LinearSolver (AztecOO)... " << std::endl;
475  }
476  std::shared_ptr<vector_Type> solution3;
477  solution3.reset ( new vector_Type ( uFESpace->map(), Unique ) );
478  linearSolver3.setOperator ( systemMatrix );
479  linearSolver3.setRightHandSide ( rhsBC );
480  linearSolver3.solve ( solution3 );
481 
482  // +-----------------------------------------------+
483  // | Computing the error |
484  // +-----------------------------------------------+
485  if ( verbose )
486  {
487  std::cout << std::endl << "[Errors computation]" << std::endl;
488  }
489  vector_Type solutionErr ( *solution );
490  solutionErr *= 0.0;
491  uFESpace->interpolate ( static_cast<function_Type> ( Laplacian::uexact ), solutionErr, 0.0 );
492  solutionErr -= *solution;
493  solutionErr.abs();
494 
495  vector_Type solution2Err ( *solution2 );
496  solution2Err *= 0.0;
497  uFESpace->interpolate ( static_cast<function_Type> ( Laplacian::uexact ), solution2Err, 0.0 );
498  solution2Err -= *solution2;
499  solution2Err.abs();
500 
501  vector_Type solution3Err ( *solution3 );
502  solution3Err *= 0.0;
503  uFESpace->interpolate ( static_cast<function_Type> ( Laplacian::uexact ), solution3Err, 0.0 );
504  solution3Err -= *solution3;
505  solution3Err.abs();
506 
507  vector_Type solutionsDiff ( *solution2 );
508  solutionsDiff -= *solution;
509  Real solutionsDiffNorm = solutionsDiff.norm2();
510 
511  vector_Type solutionsDiff2 ( *solution2 );
512  solutionsDiff2 -= *solution3;
513  Real solutionsDiffNorm2 = solutionsDiff2.norm2();
514 
515 
516  // +-----------------------------------------------+
517  // | Reporting |
518  // +-----------------------------------------------+
519 
520 
521  if ( verbose )
522  {
523  std::cout << "AztecOO solver" << std::endl;
524  }
525  Real uL2AztecOO, uH1AztecOO;
526  printErrors ( *solution, uFESpace, uL2AztecOO, uH1AztecOO, verbose );
527 
528  if ( verbose )
529  {
530  std::cout << "Linear solver Belos" << std::endl;
531  }
532  Real uL2Belos, uH1Belos;
533  printErrors ( *solution2, uFESpace, uL2Belos, uH1Belos, verbose );
534 
535  if ( verbose )
536  {
537  std::cout << "Linear solver AztecOO" << std::endl;
538  }
539  Real uL2AztecOO3, uH1AztecOO3;
540  printErrors ( *solution3, uFESpace, uL2AztecOO3, uH1AztecOO3, verbose );
541 
542  if ( verbose )
543  {
544  std::cout << "Difference between the Azteco and the Belos solutions: " << solutionsDiffNorm << std::endl;
545  }
546  if ( solutionsDiffNorm > TEST_TOLERANCE )
547  {
548  if ( verbose )
549  {
550  std::cout << "The difference between the two solutions is too large." << std::endl;
551  }
552  if ( verbose )
553  {
554  std::cout << "Test status: FAILED" << std::endl;
555  }
556  return ( EXIT_FAILURE );
557  }
558  if ( verbose )
559  {
560  std::cout << "Difference between the two AztecOO solvers solutions: " << solutionsDiffNorm2 << std::endl;
561  }
562  if ( solutionsDiffNorm2 > TEST_TOLERANCE )
563  {
564  if ( verbose )
565  {
566  std::cout << "The difference between the two solutions is too large." << std::endl;
567  }
568  if ( verbose )
569  {
570  std::cout << "Test status: FAILED" << std::endl;
571  }
572  return ( EXIT_FAILURE );
573  }
574 
575  if ( uL2AztecOO > 4.602e-03 || uH1AztecOO > 3.855e-01
576  || uL2Belos > 4.602e-03 || uH1Belos > 3.855e-01
577  || uL2AztecOO3 > 4.602e-03 || uH1AztecOO3 > 3.855e-01)
578  {
579  if ( verbose )
580  {
581  std::cout << "The error in L2 norm or H1 norm is too large." << std::endl;
582  }
583  if ( verbose )
584  {
585  std::cout << "Test status: FAILED" << std::endl;
586  }
587  return ( EXIT_FAILURE );
588  }
589 
590  // +-----------------------------------------------+
591  // | Ending the simulation |
592  // +-----------------------------------------------+
593  globalChrono.stop();
594  if ( verbose )
595  {
596  std::cout << std::endl << "Total simulation time: " << globalChrono.diff() << " s." << std::endl;
597  }
598  if ( verbose )
599  {
600  std::cout << std::endl << "[[END_SIMULATION]]" << std::endl;
601  }
602 
603  }
604 
605 #ifdef HAVE_MPI
606  MPI_Finalize();
607 #endif
608 
609  /*if( verbose )*/ std::cout << "Test status: SUCCESS" << std::endl;
610 
611  return ( EXIT_SUCCESS );
612 }
FESpace - Short description here please!
Definition: FESpace.hpp:78
uint32_type ID
IDs.
Definition: LifeV.hpp:194
Real operator()(const Real &t, const Real &x, const Real &y, const Real &z, const ID &i) const
void printErrors(const vector_Type &solution, fespacePtr_Type uFESpace, Real &uL2Error, Real &uH1Error, bool verbose)
double Real
Generic real data.
Definition: LifeV.hpp:175
Real grad(const ID &iCoor, const Real &t, const Real &x, const Real &y, const Real &z, const ID &i) const
int main(int argc, char **argv)
std::function< Real(Real const &, Real const &, Real const &, Real const &, UInt const &) > function_Type