LifeV
ETA_ADR1DTest.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  @file ETA_ADR2DTest.cpp
28  @author L. Pasquale <luca.pasquale@mail.polimi.it>
29  @date 2012-11-20
30  */
31 
32 // ===================================================
33 //! Includes
34 // ===================================================
35 
36 #include "ETA_ADR1DTest.hpp"
37 
38 #include <lifev/eta/fem/ETFESpace.hpp>
39 #include <lifev/eta/expression/Integrate.hpp>
40 
41 
42 // ===================================================
43 //! Namespaces & define
44 // ===================================================
45 
46 // ---------------------------------------------------------------
47 // We work in the LifeV namespace and define the mesh, matrix and
48 // vector types that we will need several times.
49 // ---------------------------------------------------------------
50 
51 using namespace LifeV;
52 
56 
57 // ---------------------------------------------------------------
58 // We define then a function, which represents a velocity field,
59 // of magnitude 1 in the y direction (supposing an (x,y)
60 // reference frame).
61 // ---------------------------------------------------------------
62 
63 
64 // ===================================================
65 //! Functions
66 // ===================================================
67 
68 Real betaFct ( const Real& /* t */, const Real& /* x */, const Real& /* y */, const Real& /* z */, const ID& /* i */ )
69 {
70  return 1;
71 }
72 
73 Real fRhs ( const Real& /* t */, const Real& /*x*/, const Real& /*y*/, const Real& /* z */ , const ID& /* i */ )
74 {
75  return 2;
76 }
77 
78 
79 // ===================================================
80 //! Constructors
81 // ===================================================
82 
83 ETA_ADR1DTest::ETA_ADR1DTest ()
84 {
85 
86 #ifdef EPETRA_MPI
87  M_comm.reset ( new Epetra_MpiComm ( MPI_COMM_WORLD ) );
88 #else
89  M_comm.reset ( new Epetra_SerialComm() );
90 #endif
91 
92 }
93 
94 // ===================================================
95 //! Methods
96 // ===================================================
97 
98 Real
99 ETA_ADR1DTest::run()
100 {
101  bool verbose (M_comm->MyPID() == 0);
102  // ---------------------------------------------------------------
103  // We define the mesh and parition it. We use the domain
104  // (-1,1) and a structured mesh.
105  // ---------------------------------------------------------------
106 
107  if (verbose)
108  {
109  std::cout << " -- Building the mesh ... " << std::flush;
110  }
111 
112  const UInt Nelements (10);
113 
114  std::shared_ptr< mesh_Type > fullMeshPtr (new mesh_Type);
115 
116  regularMesh1D ( *fullMeshPtr, 0, Nelements, false,
117  1.0,
118  -1.0);
119 
120  // Mesh partitioning doesn't work yet with 1D meshes
121  //MeshPartitioner< mesh_Type > meshPart (fullMeshPtr, M_comm);
122  //std::shared_ptr< mesh_Type > meshPtr (meshPart.meshPartition() );
123  //fullMeshPtr.reset();
124 
125  if (verbose)
126  {
127  std::cout << " done ! " << std::endl;
128  }
129 
130 
131  // ---------------------------------------------------------------
132  // We start by defining the finite element spaces. We use the type
133  // FESpace for the classical way and copy it in an ETFESpace for
134  // the ET assembly.
135  //
136  // In the end, both solution spaces display their respective
137  // number of degrees of freedom, which must be the same.
138  // ---------------------------------------------------------------
139 
140  if (verbose)
141  {
142  std::cout << " -- Building FESpaces ... " << std::flush;
143  }
144 
145  std::string uOrder ("P1");
146  std::string bOrder ("P1");
147 
148  std::shared_ptr<FESpace< mesh_Type, MapEpetra > > uSpace
149  ( new FESpace< mesh_Type, MapEpetra > (fullMeshPtr, uOrder, 1, M_comm) );
150 
151  std::shared_ptr<FESpace< mesh_Type, MapEpetra > > betaSpace
152  ( new FESpace< mesh_Type, MapEpetra > (fullMeshPtr, bOrder, 1, M_comm) );
153 
154  if (verbose)
155  {
156  std::cout << " done ! " << std::endl;
157  }
158  if (verbose)
159  {
160  std::cout << " ---> Dofs: " << uSpace->dof().numTotalDof() << std::endl;
161  }
162 
163  if (verbose)
164  {
165  std::cout << " -- Building ETFESpaces ... " << std::flush;
166  }
167 
168  std::shared_ptr<ETFESpace< mesh_Type, MapEpetra, 1, 1 > > ETuSpace
169  ( new ETFESpace< mesh_Type, MapEpetra, 1, 1 > (fullMeshPtr, & (uSpace->refFE() ), & (uSpace->fe().geoMap() ), M_comm) );
170 
171  std::shared_ptr<ETFESpace< mesh_Type, MapEpetra, 1, 1 > > ETbetaSpace
172  ( new ETFESpace< mesh_Type, MapEpetra, 1, 1 > (fullMeshPtr, & (betaSpace->refFE() ), & (betaSpace->fe().geoMap() ), M_comm) );
173 
174  if (verbose)
175  {
176  std::cout << " done ! " << std::endl;
177  }
178  if (verbose)
179  {
180  std::cout << " ---> Dofs: " << ETuSpace->dof().numTotalDof() << std::endl;
181  }
182 
183 
184  // ---------------------------------------------------------------
185  // We then interpolate the advection function.
186  // This is can only be performed with the classical FESpace.
187  // ---------------------------------------------------------------
188 
189  if (verbose)
190  {
191  std::cout << " -- Interpolating the advection field ... " << std::flush;
192  }
193 
194  vector_Type beta (betaSpace->map(), Repeated);
195  betaSpace->interpolate (static_cast<FESpace< mesh_Type, MapEpetra >::function_Type> (betaFct), beta, 0.0);
196 
197  if (verbose)
198  {
199  std::cout << " done! " << std::endl;
200  }
201 
202 
203  // ---------------------------------------------------------------
204  // We build now two matrices, one for each assembly procedure in
205  // order to compare them in the end. There is no difference in the
206  // construction of the matrices.
207  // ---------------------------------------------------------------
208 
209  if (verbose)
210  {
211  std::cout << " -- Defining the matrices ... " << std::flush;
212  }
213 
214  std::shared_ptr<matrix_Type> systemMatrix (new matrix_Type ( uSpace->map() ) );
215  *systemMatrix *= 0.0;
216 
217  std::shared_ptr<matrix_Type> ETsystemMatrix (new matrix_Type ( ETuSpace->map() ) );
218  *ETsystemMatrix *= 0.0;
219 
220  if (verbose)
221  {
222  std::cout << " done! " << std::endl;
223  }
224 
225  // ---------------------------------------------------------------
226  // Definition of the RHS
227  // ---------------------------------------------------------------
228 
229  if (verbose)
230  {
231  std::cout << " -- Defining and interpolating the RHS ... " << std::flush;
232  }
233 
234  vector_Type rhs (uSpace->map(), Repeated);
235  rhs *= 0.0;
236  vector_Type ETrhs (uSpace->map(), Repeated);
237  ETrhs *= 0.0;
238 
239  vector_Type fInterpolated (uSpace->map(), Repeated);
240  fInterpolated *= 0.0;
241  uSpace->interpolate ( static_cast<FESpace< mesh_Type, MapEpetra >::function_Type> (fRhs) , fInterpolated, 0.0 );
242 
243  if (verbose)
244  {
245  std::cout << " done! " << std::endl;
246  }
247 
248  // ---------------------------------------------------------------
249  // We come now to the assembly itself. We start with the classical
250  // way, which consists in instentiating an ADRAssembler and call
251  // the different methods from that class.
252  //
253  // Using a LifeChrono, we monitor the time required for the
254  // assembly.
255  //
256  // The terms assembled correspond, in the order of appearance, to
257  // - a laplacian term
258  // - an advection term
259  // - a reaction term (with coefficient 2.0), aka mass term.
260  //
261  // We also assemble the RHS
262  // ---------------------------------------------------------------
263 
264  LifeChrono StdChrono;
265  StdChrono.start();
266 
267  if (verbose)
268  {
269  std::cout << " -- Classical assembly ... " << std::flush;
270  }
271 
272  ADRAssembler<mesh_Type, matrix_Type, vector_Type> adrAssembler;
273 
274  adrAssembler.setup (uSpace, betaSpace);
275 
276  adrAssembler.addDiffusion (systemMatrix, 1.0);
277 
278  adrAssembler.addAdvection (systemMatrix, beta);
279 
280  adrAssembler.addMass (systemMatrix, 2.0);
281 
282  adrAssembler.addMassRhs (rhs, fInterpolated);
283 
284  StdChrono.stop();
285 
286  if (verbose)
287  {
288  std::cout << " done ! " << std::endl;
289  }
290  if (verbose)
291  {
292  std::cout << " Time : " << StdChrono.diff() << std::endl;
293  }
294 
295 
296  // ---------------------------------------------------------------
297  // We perform now the same assembly with the ET assembly and still
298  // monitor the timings required.
299  //
300  // Remark also that the Real constants and VectorSmall constants
301  // can be used directly in the expressions to integrate.
302  // ---------------------------------------------------------------
303 
304  LifeChrono ETChrono;
305  ETChrono.start();
306 
307  if (verbose)
308  {
309  std::cout << " -- ET assembly ... " << std::flush;
310  }
311 
312  // Workaround for 1D case where grad(phi_j) is a VectorSmall<1>
313  // and not a double: we use a dot product with a unitary VectorSmall<1>
314  // to obtain its value as adouble
315  VectorSmall<1> oneVector;
316  oneVector[0] = 1.0;
317 
318 
319  {
320  using namespace ExpressionAssembly;
321 
322  integrate ( elements (ETuSpace->mesh() ),
323  uSpace->qr(),
324  ETuSpace,
325  ETuSpace,
326 
327  dot ( grad (phi_i) , grad (phi_j) )
328  + dot ( grad (phi_j) , value (oneVector) ) * value (ETbetaSpace, beta) *phi_i
329  + 2.0 * phi_i * phi_j
330 
331  )
332  >> ETsystemMatrix;
333 
334  integrate ( elements (ETuSpace->mesh() ),
335  uSpace->qr(),
336  ETuSpace,
337 
338  value (ETuSpace, fInterpolated) *phi_i
339 
340  )
341  >> ETrhs;
342 
343  }
344 
345  ETChrono.stop();
346 
347  if (verbose)
348  {
349  std::cout << " done! " << std::endl;
350  }
351  if (verbose)
352  {
353  std::cout << " Time : " << ETChrono.diff() << std::endl;
354  }
355 
356 
357  // ---------------------------------------------------------------
358  // We finally need to check that both yield the same matrix. In
359  // that aim, we need to finalize both matrices.
360  // ---------------------------------------------------------------
361 
362  if (verbose)
363  {
364  std::cout << " -- Closing the matrices and vectors... " << std::flush;
365  }
366 
367  systemMatrix->globalAssemble();
368  ETsystemMatrix->globalAssemble();
369 
370  rhs.globalAssemble();
371  ETrhs.globalAssemble();
372 
373  if (verbose)
374  {
375  std::cout << " done ! " << std::endl;
376  }
377 
378  // ---------------------------------------------------------------
379  // We compute now the matrix of the difference and finally the
380  // norm of the difference. This should be very low if the two
381  // matrices are identical.
382  // ---------------------------------------------------------------
383 
384  if (verbose)
385  {
386  std::cout << " -- Computing the error ... " << std::flush;
387  }
388 
389  std::shared_ptr<matrix_Type> checkMatrix (new matrix_Type ( ETuSpace->map() ) );
390  *checkMatrix *= 0.0;
391 
392  *checkMatrix += *systemMatrix;
393  *checkMatrix += (*ETsystemMatrix) * (-1);
394 
395  checkMatrix->globalAssemble();
396 
397  Real errorNorm ( checkMatrix->normInf() );
398 
399 
400  // ---------------------------------------------------------------
401  // Finally, we check that the two right hand sides are similar
402  // with the two assembly procedures. We also check that the two
403  // integrals correspond to their exact values.
404  // ---------------------------------------------------------------
405 
406  vector_Type checkRhs (ETuSpace->map(), Repeated);
407  checkRhs = 0.0;
408 
409  checkRhs += rhs;
410  checkRhs -= ETrhs;
411 
412  checkRhs.globalAssemble();
413 
414  vector_Type checkRhsUnique (checkRhs, Unique);
415 
416  Real errorRhsNorm ( checkRhsUnique.normInf() );
417 
418  if (verbose)
419  {
420  std::cout << " done ! " << std::endl;
421  }
422 
423  if (verbose)
424  {
425  std::cout << " Matrix Error : " << errorNorm << std::endl;
426  }
427  if (verbose)
428  {
429  std::cout << " Rhs error : " << errorRhsNorm << std::endl;
430  }
431 
432 
433  // ---------------------------------------------------------------
434  // Finally we return the maximum of the two errors
435  // ---------------------------------------------------------------
436 
437 
438  return std::max (errorNorm, errorRhsNorm);
439 
440 } // run
VectorEpetra - The Epetra Vector format Wrapper.
RegionMesh< LinearLine > mesh_Type
VectorEpetra(const VectorEpetra &vector, const MapEpetraType &mapType)
Copy constructor.
void importFromHDF5(std::string const &fileName, std::string const &matrixName="matrix")
Read a matrix from a HDF5 (.h5) file.
Real betaFct(const Real &, const Real &, const Real &, const Real &, const ID &)
Functions.
Real normInf() const
Compute and return the norm inf.
uint32_type ID
IDs.
Definition: LifeV.hpp:194
MatrixEpetra< Real > matrix_Type
VectorEpetra vector_Type
double Real
Generic real data.
Definition: LifeV.hpp:175
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191
Real beta(1.0)
Real fRhs(const Real &, const Real &, const Real &, const Real &, const ID &)