LifeV
TestRepeatedMesh.hpp
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 Antonio Cervone <ant.cervone@gmail.com>
32  @date 2013-12-05
33  */
34 
35 #ifndef TEST_REPEATED_MESH__
36 #define TEST_REPEATED_MESH__
37 
38 #include <Epetra_ConfigDefs.h>
39 #ifdef EPETRA_MPI
40 #include <mpi.h>
41 #include <Epetra_MpiComm.h>
42 #else
43 #include <Epetra_SerialComm.h>
44 #endif
45 
46 
47 #include <lifev/core/LifeV.hpp>
48 
49 #include <lifev/core/array/MatrixEpetra.hpp>
50 
51 #include <lifev/core/fem/FESpace.hpp>
52 
53 #include <lifev/core/mesh/MeshPartitioner.hpp>
54 #include <lifev/core/mesh/RegionMesh2DStructured.hpp>
55 #include <lifev/core/mesh/RegionMesh.hpp>
56 #include <lifev/core/mesh/MeshData.hpp>
57 
58 #include <lifev/core/solver/ADRAssembler.hpp>
59 
60 #include <lifev/core/util/LifeChronoManager.hpp>
61 
62 #ifdef HAVE_HDF5
63 #include <lifev/core/filter/ExporterHDF5.hpp>
64 #endif
65 
66 using namespace LifeV;
67 
68 Real fRhs ( const Real& /* t */, const Real& x, const Real& /* y */, const Real& /* z */ , const ID& /* i */ )
69 {
70  return sin ( x ) - 1.;
71 }
72 
73 template <uint Dim>
75 {
79 
80  static meshPtr_Type generateRegularMesh ( GetPot const& dataFile );
81 };
82 
83 template <>
84 struct DimSelector<2>
85 {
89 
90  static meshPtr_Type generateRegularMesh ( GetPot const& dataFile )
91  {
92  meshPtr_Type fullMeshPtr;
93  regularMesh2D ( *fullMeshPtr, 0,
94  dataFile ( "mesh/nx", 20 ), dataFile ( "mesh/ny", 20 ),
95  dataFile ( "mesh/verbose", false ),
96  dataFile ( "mesh/lx", 1. ), dataFile ( "mesh/ly", 1. ) );
97  return fullMeshPtr;
98  }
99 };
100 
101 template <>
102 struct DimSelector<3>
103 {
107 
108  static meshPtr_Type generateRegularMesh ( GetPot const& dataFile )
109  {
110  meshPtr_Type fullMeshPtr;
111  regularMesh3D ( *fullMeshPtr, 0,
112  dataFile ( "mesh/nelem", 8 ), dataFile ( "mesh/nelem", 8 ), dataFile ( "mesh/nelem", 8 ),
113  dataFile ( "mesh/verbose", false ),
114  dataFile ( "mesh/length", 1. ), dataFile ( "mesh/length", 1. ), dataFile ( "mesh/length", 1. ) );
115  return fullMeshPtr;
116  }
117 };
118 
119 template <uint Dim>
121 {
122  typedef typename DimSelector<Dim>::elem_Type elem_Type;
129  typedef FESpace<mesh_Type, MapEpetra> feSpace_Type;
131 
133 
134  void init();
135 
136  int run();
137 
138 private:
141 };
142 
143 template <uint Dim>
144 inline void TestRepeatedMesh<Dim>::init()
145 {
146 #ifdef HAVE_MPI
147  M_comm.reset ( new Epetra_MpiComm ( MPI_COMM_WORLD ) );
148 #else
149  M_comm.reset ( new Epetra_SerialComm );
150 #endif
151  M_chronoMgr.reset ( new LifeChronoManager<> ( M_comm ) );
152 }
153 
154 template <uint Dim>
155 int TestRepeatedMesh<Dim>::run()
156 {
157  int returnValue = EXIT_SUCCESS;
158  LifeChrono initTime;
159  M_chronoMgr->add ( "Initialization Time", &initTime );
160  initTime.start();
161 
162  GetPot dataFile ( "data" );
163  const bool isLeader ( M_comm->MyPID() == 0 );
164  const bool verbose = dataFile ( "miscellaneous/verbose", 0 ) && isLeader;
165 
166 #ifdef HAVE_LIFEV_DEBUG
167  std::ofstream debugOut ( ( "repeated_mesh." + ( M_comm->NumProc() > 1 ? std::to_string( M_comm->MyPID() ) : "s" ) + ".out" ).c_str() );
168 #else
169  std::ofstream debugOut ( "/dev/null" );
170 #endif
171 
172  initTime.stop();
173 
174  // Build and partition the mesh
175 
176  LifeChrono meshTime;
177  M_chronoMgr->add ( "Mesh reading/creation Time", &initTime );
178  meshTime.start();
179 
180  if ( verbose )
181  {
182  std::cout << " -- Reading the mesh ... " << std::flush;
183  }
184  meshPtr_Type fullMeshPtr (new mesh_Type() );
185  if ( dataFile ( "mesh/mesh_type", "structured" ) == "structured" )
186  {
187  fullMeshPtr = DimSelector<Dim>::generateRegularMesh ( dataFile );
188  }
189  else
190  {
191  MeshData meshData (dataFile, "mesh");
192  readMesh (*fullMeshPtr, meshData);
193  }
194  if ( verbose )
195  {
196  std::cout << " done ! " << std::endl;
197  }
198  if ( isLeader )
199  {
200  std::cout << "mesh elements = " << fullMeshPtr->numElements() << "\n"
201  << "mesh points = " << fullMeshPtr->numPoints() << std::endl;
202  }
203 
204  meshTime.stop();
205 
206  if ( verbose )
207  {
208  std::cout << " -- Partitioning the mesh ... " << std::flush;
209  }
210 
211  LifeChrono partTime;
212  M_chronoMgr->add ( "Partition Time", &partTime );
213  partTime.start();
214  meshPtr_Type localMesh;
215  {
216  MeshPartitioner< mesh_Type > meshPart;
217  meshPart.doPartition ( fullMeshPtr, M_comm );
218  localMesh = meshPart.meshPartition();
219  }
220  partTime.stop();
221  //if ( isLeader )
222  //{
223  // std::cout << "partitioning time = " << partTime.diff() << std::endl;
224  //}
225 
226  Int localMeshNum[ 2 ];
227  localMeshNum[ 0 ] = localMesh->numElements();
228  localMeshNum[ 1 ] = localMesh->numPoints();
229  Int maxMeshNum[ 2 ] = { 0, 0 };
230  M_comm->MaxAll ( localMeshNum, maxMeshNum, 2 );
231 
232  if ( isLeader )
233  {
234  std::cout << "part mesh elements = " << maxMeshNum[ 0 ] << "\n"
235  << "part mesh points = " << maxMeshNum[ 1 ] << std::endl;
236  }
237 
238  LifeChrono partTimeR;
239  M_chronoMgr->add ( "Partition Time (R)", &partTimeR );
240  partTimeR.start();
241  meshPtr_Type localMeshR;
242  {
243  MeshPartitioner< mesh_Type > meshPartR;
244  meshPartR.setPartitionOverlap ( 1 );
245  meshPartR.doPartition ( fullMeshPtr, M_comm );
246  localMeshR = meshPartR.meshPartition();
247  }
248  partTimeR.stop();
249  //if ( isLeader )
250  //{
251  // std::cout << "partitioningR time = " << partTimeR.diff() << std::endl;
252  //}
253 
254  localMeshNum[ 0 ] = localMeshR->numElements();
255  localMeshNum[ 1 ] = localMeshR->numPoints();
256  maxMeshNum[ 0 ] = 0;
257  maxMeshNum[ 1 ] = 0;
258  M_comm->MaxAll ( localMeshNum, maxMeshNum, 2 );
259 
260  if ( isLeader )
261  {
262  std::cout << "part mesh elements (R) = " << maxMeshNum[ 0 ] << "\n"
263  << "part mesh points (R) = " << maxMeshNum[ 1 ] << std::endl;
264  }
265 
266  if ( verbose )
267  {
268  std::cout << " done ! " << std::endl;
269  }
270 
271  if ( verbose )
272  {
273  std::cout << " -- Freeing the global mesh ... " << std::flush;
274  }
275  fullMeshPtr.reset();
276 #ifdef HAVE_LIFEV_DEBUG
277  ASSERT ( fullMeshPtr.use_count() == 0, "full mesh not properly freed." );
278 #endif
279  if ( verbose )
280  {
281  std::cout << " done ! " << std::endl;
282  }
283 
284  // Build the FESpaces
285 
286  if ( verbose )
287  {
288  std::cout << " -- Building FESpaces ... " << std::flush;
289  }
290  std::string uOrder = dataFile ( "fe/type", "P1" );
291  LifeChrono feSpaceTime;
292  M_chronoMgr->add ( "FESpace creation Time", &feSpaceTime );
293  feSpaceTime.start();
294  feSpacePtr_Type uFESpace ( new feSpace_Type ( localMesh, uOrder, 1, M_comm ) );
295  feSpaceTime.stop();
296 
297  LifeChrono feSpaceTimeR;
298  M_chronoMgr->add ( "FESpace creation Time (R)", &feSpaceTimeR );
299  feSpaceTimeR.start();
300  feSpacePtr_Type uFESpaceR ( new feSpace_Type ( localMeshR, uOrder, 1, M_comm ) );
301  feSpaceTimeR.stop();
302 
303  if ( verbose )
304  {
305  std::cout << " done ! " << std::endl;
306  }
307  if ( verbose )
308  {
309  std::cout << " ---> Dofs: " << uFESpaceR->dof().numTotalDof() << std::endl;
310  }
311 
312  // Build the assembler and the matrices
313 
314  if ( verbose )
315  {
316  std::cout << " -- Building assembler ... " << std::flush;
317  }
318 
319  LifeChrono matTime;
320  M_chronoMgr->add ( "Matrix initialization Time", &matTime );
321  matTime.start();
322  ADRAssembler<mesh_Type, matrix_Type, vector_Type> adrAssembler;
323  adrAssembler.setFespace ( uFESpace );
324  matrixPtr_Type systemMatrix ( new matrix_Type ( uFESpace->map() ) );
325  matTime.stop();
326 
327  LifeChrono matTimeR;
328  M_chronoMgr->add ( "Matrix initialization Time (R)", &matTimeR );
329  matTimeR.start();
330  ADRAssembler<mesh_Type, matrix_Type, vector_Type> adrAssemblerR;
331  adrAssemblerR.setFespace ( uFESpaceR );
332  matrixPtr_Type systemMatrixR ( new matrix_Type ( uFESpaceR->map(), 50, true ) );
333  matTimeR.stop();
334 
335  if ( verbose )
336  {
337  std::cout << " done! " << std::endl;
338  }
339 
340  // Perform the assembly of the matrix
341 
342  if ( verbose )
343  {
344  std::cout << " -- Adding the diffusion ... " << std::flush;
345  }
346 
347  if ( verbose )
348  {
349  std::cout << " done! " << std::endl;
350  }
351 
352  UInt timeSteps = dataFile ( "miscellaneous/timesteps", 1 );
353 
354  LifeChrono assemblyTime;
355  M_chronoMgr->add ( "Assembly Time", &assemblyTime );
356  assemblyTime.start();
357  for ( UInt n = 0; n < timeSteps; n++ )
358  {
359  systemMatrix->zero();
360  adrAssembler.addDiffusion ( systemMatrix, 1. );
361  adrAssembler.addMass ( systemMatrix, 1. );
362  systemMatrix->globalAssemble();
363  }
364  assemblyTime.stop();
365  if ( isLeader )
366  {
367  std::cout << "assembly time = " << assemblyTime.diff() << std::endl;
368  }
369 
370  LifeChrono assemblyTimeR;
371  M_chronoMgr->add ( "Assembly Time (R)", &assemblyTimeR );
372  assemblyTimeR.start();
373  for ( UInt n = 0; n < timeSteps; n++ )
374  {
375  systemMatrixR->zero();
376  adrAssemblerR.addDiffusion ( systemMatrixR, 1. );
377  adrAssemblerR.addMass ( systemMatrixR, 1. );
378  systemMatrixR->fillComplete();
379  }
380  assemblyTimeR.stop();
381  if ( isLeader )
382  {
383  std::cout << "assemblyR time = " << assemblyTimeR.diff() << std::endl;
384  }
385 
386  //if ( verbose )
387  //{
388  // std::cout << " Time needed : " << adrAssembler.diffusionAssemblyChrono().diffCumul() << std::endl;
389  //}
390  //if ( verbose )
391  //{
392  // std::cout << " Time needed : " << adrAssemblerR.diffusionAssemblyChrono().diffCumul() << std::endl;
393  //}
394 
395  // SPY
396  //systemMatrix->spy("matrixNoBC");
397  //systemMatrixR->spy("matrixNoBCR");
398 
399  // check that the assembled matrices are the same
400 
401  LifeChrono checkMatTime;
402  M_chronoMgr->add ( "Check (Matrix) Time", &checkMatTime );
403  checkMatTime.start();
404  matrix_Type matrixDiff ( *systemMatrix );
405  matrixDiff -= *systemMatrixR;
406 
407  Real diff = matrixDiff.normInf();
408  checkMatTime.stop();
409 
410  if ( isLeader )
411  {
412  std::cout << "Norm of the difference between the 2 matrices = " << diff << std::endl;
413  }
414 
415  if ( verbose )
416  {
417  std::cout << " -- Building the RHS ... " << std::flush;
418  }
419 
420  LifeChrono rhsTime;
421  M_chronoMgr->add ( "Rhs build Time", &rhsTime );
422  rhsTime.start();
423  vector_Type rhs ( uFESpace->map(), Unique );
424  adrAssembler.addMassRhs ( rhs, fRhs, 0. );
425  rhs.globalAssemble();
426  rhsTime.stop();
427 
428  LifeChrono rhsTimeR;
429  M_chronoMgr->add ( "Rhs build Time (R)", &rhsTimeR );
430  rhsTimeR.start();
431  vector_Type rhsR ( uFESpaceR->map(), Unique, Zero );
432  adrAssemblerR.addMassRhs ( rhsR, fRhs, 0. );
433  rhsR.globalAssemble ();
434  rhsTimeR.stop();
435 
436  LifeChrono checkVecTime;
437  M_chronoMgr->add ( "Check (Vector) Time", &checkVecTime );
438  checkVecTime.start();
439  vector_Type vectorDiff ( rhs );
440  vectorDiff -= rhsR;
441 
442  Real diffNormV = vectorDiff.normInf();
443  checkVecTime.stop();
444 
445  if ( isLeader )
446  {
447  std::cout << "Norm of the difference between the 2 vectors = " << diffNormV << std::endl;
448  }
449 
450  diff += diffNormV;
451 
452  vector_Type rhs2 ( uFESpace->map(), Unique );
453  vector_Type f ( uFESpace->map(), Repeated );
454  uFESpace->interpolate ( static_cast<typename feSpace_Type::function_Type> ( fRhs ), f, 0.0 );
455  adrAssembler.addMassRhs ( rhs2, f );
456  rhs2.globalAssemble();
457 
458  vector_Type rhs2R ( uFESpaceR->map(), Unique );
459  vector_Type fR ( uFESpaceR->map(), Repeated );
460  uFESpaceR->interpolate ( static_cast<typename feSpace_Type::function_Type> ( fRhs ), fR, 0.0 );
461  adrAssemblerR.addMassRhs ( rhs2R, fR );
462  rhs2R.globalAssemble ( Zero );
463 
464  vector_Type vectorDiff2 ( rhs2 );
465  vectorDiff2 -= rhs2R;
466 
467  Real diffNormV2 = vectorDiff2.normInf();
468 
469  if ( isLeader )
470  {
471  std::cout << "Norm of the difference between the 2 vectors = " << diffNormV2 << std::endl;
472  }
473 
474  diff += diffNormV2;
475 
476  // test exporting of a repeated mesh
477 #ifdef HAVE_HDF5
478  if ( dataFile ( "exporter/enable", false ) )
479  {
480  ExporterHDF5<mesh_Type> exporter ( dataFile, localMeshR, "pid", M_comm->MyPID() );
481  exporter.exportPID ( localMeshR, M_comm, true );
482  exporter.postProcess ( 0. );
483  }
484 #endif
485 
486  vector_Type rhsCopy ( rhs, Repeated );
487  vector_Type rhsCopyR ( rhsR, Repeated, Add );
488  Real l2Error = uFESpace->l2Error ( fRhs, rhsCopy, 0.0 );
489  Real l2ErrorR = uFESpaceR->l2Error ( fRhs, rhsCopyR, 0.0 );
490  Real diffL2Error = std::fabs ( l2Error - l2ErrorR );
491 
492  if ( isLeader )
493  {
494  std::cout << "difference in l2error = " << diffL2Error << std::endl;
495  }
496 
497  diff += diffL2Error;
498 
499  if ( diff < 1.e-14 )
500  {
501  if ( isLeader )
502  {
503  std::cout << "End Result: TEST PASSED" << std::endl;
504  }
505  }
506  else
507  {
508  returnValue = EXIT_FAILURE;
509  }
510 
511  // print out times
512  M_chronoMgr->print();
513 
514  return returnValue;
515 }
516 
517 #endif // TEST_REPEATED_MESH__
VectorEpetra - The Epetra Vector format Wrapper.
RegionMesh< elem_Type > mesh_Type
std::shared_ptr< mesh_Type > meshPtr_Type
std::shared_ptr< Epetra_Comm > commPtr_Type
RegionMesh< elem_Type > mesh_Type
A Geometric Shape.
void importFromHDF5(std::string const &fileName, std::string const &matrixName="matrix")
Read a matrix from a HDF5 (.h5) file.
static meshPtr_Type generateRegularMesh(GetPot const &dataFile)
std::shared_ptr< matrix_Type > matrixPtr_Type
RegionMesh< elem_Type > mesh_Type
FESpace< mesh_Type, MapEpetra > feSpace_Type
std::shared_ptr< feSpace_Type > feSpacePtr_Type
std::shared_ptr< mesh_Type > meshPtr_Type
Epetra_Import const & importer()
Getter for the Epetra_Import.
Definition: MapEpetra.cpp:394
std::shared_ptr< mesh_Type > meshPtr_Type
uint32_type ID
IDs.
Definition: LifeV.hpp:194
DimSelector< Dim >::elem_Type elem_Type
static meshPtr_Type generateRegularMesh(GetPot const &dataFile)
MatrixEpetra< Real > matrix_Type
double Real
Generic real data.
Definition: LifeV.hpp:175
RegionMesh< elem_Type > mesh_Type
static meshPtr_Type generateRegularMesh(GetPot const &dataFile)
VectorEpetra vector_Type
A Geometric Shape.
Real fRhs(const Real &, const Real &x, const Real &, const Real &, const ID &)
std::unique_ptr< LifeChronoManager<> > M_chronoMgr
LinearTriangle elem_Type
std::shared_ptr< mesh_Type > meshPtr_Type
nullShape elem_Type