LifeV
lifev/eta/tutorials/9_ETA_gradient_interpolation/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 Tutorial for gradient interpolation.
30 
31  @author Luca Pasquale <luca.pasquale@mail.polimi.it>
32  @date 2013-05
33 
34  In this tutorial we use two expressions available when
35  integrating with Expression Templates:
36  - interpoaltion of the gradient of a given function
37  - multiplication by a MatrixSmall
38  We do this by multiplying the gradient by the identity matrix
39  (i.e. we're integrating the divergence)
40 
41  Tutorials that should be read before: 1,3
42 
43  */
44 
45 // ---------------------------------------------------------------
46 // We reuse the same files as in the previous tutorial. We add the
47 // chrono to measure the timings.
48 // ---------------------------------------------------------------
49 
50 
51 #include <Epetra_ConfigDefs.h>
52 #ifdef EPETRA_MPI
53 #include <mpi.h>
54 #include <Epetra_MpiComm.h>
55 #else
56 #include <Epetra_SerialComm.h>
57 #endif
58 
59 
60 #include <lifev/core/LifeV.hpp>
61 
62 #include <lifev/core/mesh/MeshPartitioner.hpp>
63 #include <lifev/core/mesh/RegionMesh3DStructured.hpp>
64 #include <lifev/core/mesh/RegionMesh.hpp>
65 
66 #include <lifev/core/array/MatrixEpetra.hpp>
67 #include <lifev/core/array/VectorEpetra.hpp>
68 
69 #include <lifev/eta/fem/ETFESpace.hpp>
70 #include <lifev/eta/expression/Integrate.hpp>
71 
72 #include <lifev/core/fem/FESpace.hpp>
73 
74 #include <lifev/core/util/LifeChrono.hpp>
75 
76 #include <boost/shared_ptr.hpp>
77 
78 
79 // ---------------------------------------------------------------
80 // We work in the LifeV namespace and define the mesh, matrix and
81 // vector types that we will need several times.
82 // ---------------------------------------------------------------
83 
84 using namespace LifeV;
85 
87 typedef MatrixEpetra<Real> matrix_Type;
88 typedef VectorEpetra vector_Type;
89 
90 
91 // ===================================================
92 //! Functions
93 // ===================================================
94 
95 // ---------------------------------------------------------------
96 // We define a function whose gradient is
97 // (1 0 0)
98 // (0 5 0)
99 // (0 0 2)
100 // ---------------------------------------------------------------
101 
102 Real uFct ( const Real& /* t */, const Real& x , const Real& y , const Real& z , const ID& i )
103 {
104  if (i == 0)
105  {
106  return x;
107  }
108  else if (i == 1)
109  {
110  return 5 * y;
111  }
112  return 2 * z;
113 }
114 
115 // ---------------------------------------------------------------
116 // As usual, we start by the MPI communicator, the definition of
117 // the mesh and its partitioning.
118 // ---------------------------------------------------------------
119 
120 int main ( int argc, char** argv )
121 {
122 
123 #ifdef HAVE_MPI
124  MPI_Init (&argc, &argv);
125  std::shared_ptr<Epetra_Comm> Comm (new Epetra_MpiComm (MPI_COMM_WORLD) );
126 #else
127  std::shared_ptr<Epetra_Comm> Comm (new Epetra_SerialComm);
128 #endif
129 
130  const bool verbose (Comm->MyPID() == 0);
131 
132 
133  if (verbose)
134  {
135  std::cout << " -- Building and partitioning the mesh ... " << std::flush;
136  }
137 
138  const UInt Nelements (10);
139 
140  std::shared_ptr< mesh_Type > fullMeshPtr (new mesh_Type);
141 
142  regularMesh3D ( *fullMeshPtr, 1, Nelements, Nelements, Nelements, false,
143  2.0, 2.0, 2.0,
144  -1.0, -1.0, -1.0);
145 
146  MeshPartitioner< mesh_Type > meshPart (fullMeshPtr, Comm);
147  std::shared_ptr< mesh_Type > meshPtr (meshPart.meshPartition() );
148 
149  fullMeshPtr.reset();
150 
151  if (verbose)
152  {
153  std::cout << " done ! " << std::endl;
154  }
155 
156 
157  // ---------------------------------------------------------------
158  // We define then the ETFESpace, that we suppose scalar in this
159  // case. We also need a standard FESpace to perform the
160  // interpolation.
161  // ---------------------------------------------------------------
162 
163  if (verbose)
164  {
165  std::cout << " -- Building FESpaces ... " << std::flush;
166  }
167 
168  std::string uOrder ("P1");
169 
170  std::shared_ptr<FESpace< mesh_Type, MapEpetra > > uSpace
171  ( new FESpace< mesh_Type, MapEpetra > (meshPtr, uOrder, 3, Comm) );
172 
173  if (verbose)
174  {
175  std::cout << " done ! " << std::endl;
176  }
177  if (verbose)
178  {
179  std::cout << " ---> Dofs: " << uSpace->dof().numTotalDof() << std::endl;
180  }
181 
182  if (verbose)
183  {
184  std::cout << " -- Building ETFESpaces ... " << std::flush;
185  }
186 
187  std::shared_ptr<ETFESpace< mesh_Type, MapEpetra, 3, 3 > > ETuSpace
188  ( new ETFESpace< mesh_Type, MapEpetra, 3, 3 > (meshPtr, & (uSpace->refFE() ), & (uSpace->fe().geoMap() ), Comm) );
189 
190  if (verbose)
191  {
192  std::cout << " done ! " << std::endl;
193  }
194  if (verbose)
195  {
196  std::cout << " ---> Dofs: " << ETuSpace->dof().numTotalDof() << std::endl;
197  }
198 
199  // ---------------------------------------------------------------
200  // We interpolate then the function.
201  // This can only be performed with the classical FESpace.
202  // ---------------------------------------------------------------
203 
204  if (verbose)
205  {
206  std::cout << " -- Interpolating the function ... " << std::flush;
207  }
208 
209  vector_Type uInterpolated (uSpace->map(), Unique);
210  uSpace->interpolate (static_cast<FESpace< mesh_Type, MapEpetra >::function_Type> (uFct), uInterpolated, 0.0);
211  vector_Type uInterpolatedRepeated (uInterpolated, Repeated);
212 
213  if (verbose)
214  {
215  std::cout << " done! " << std::endl;
216  }
217 
218 
219  // ---------------------------------------------------------------
220  // We build the MatrixSmall used to extract the trace
221  // and a variable used to store the result of the integration.
222  // We only need to specify the diagonal elements of the MatrixSmall
223  // because its default constructor sets all the components to 0
224  // ---------------------------------------------------------------
225 
226  MatrixSmall<3, 3> identityMatrix;
227  identityMatrix (0, 0) = 1;
228  identityMatrix (1, 1) = 1;
229  identityMatrix (2, 2) = 1;
230 
231  Real ETintegral (0);
232 
233  if (verbose)
234  {
235  std::cout << " done! " << std::endl;
236  }
237 
238  // ---------------------------------------------------------------
239  // We integrate on the domain the trace of the gradient
240  // (1+5+2 in this case)
241  // ---------------------------------------------------------------
242 
243  LifeChrono ETChrono;
244  ETChrono.start();
245 
246  if (verbose)
247  {
248  std::cout << " -- ET assembly ... " << std::flush;
249  }
250 
251 
252  {
253  using namespace ExpressionAssembly;
254 
255  integrate ( elements (ETuSpace->mesh() ),
256  uSpace->qr(),
257 
258  dot ( grad (ETuSpace, uInterpolatedRepeated) , value (identityMatrix) )
259 
260  )
261  >> ETintegral;
262 
263  }
264 
265  ETChrono.stop();
266 
267  if (verbose)
268  {
269  std::cout << " done! " << std::endl;
270  }
271  if (verbose)
272  {
273  std::cout << " Time : " << ETChrono.diff() << std::endl;
274  }
275 
276  // ---------------------------------------------------------------
277  // Integrals computed on each processor must be summed together
278  // ---------------------------------------------------------------
279 
280  if (verbose)
281  {
282  std::cout << " -- Broadcasting and summing integrals across processes ... " << std::flush;
283  }
284 
285  Real globalIntegral (0.0);
286 
287  Comm->Barrier();
288  Comm->SumAll (&ETintegral, &globalIntegral, 1);
289 
290  if (verbose)
291  {
292  std::cout << " done ! " << std::endl;
293  }
294 
295  // ---------------------------------------------------------------
296  // We now compute the error as the difference between the integral
297  // computed and the exact value expected ( (1+5+2)*8 = 64 )
298  // ---------------------------------------------------------------
299 
300  if (verbose)
301  {
302  std::cout << " -- Computing the error ... " << std::flush;
303  }
304 
305  Real error = std::abs (globalIntegral - 64.0);
306 
307  if (verbose)
308  {
309  std::cout << "Error: " << error << std::endl;
310  }
311 
312  if (verbose)
313  {
314  std::cout << " done ! " << std::endl;
315  }
316 
317 
318 #ifdef HAVE_MPI
319  MPI_Finalize();
320 #endif
321 
322  Real tolerance (1e-10);
323 
324  if (error < tolerance)
325  {
326  return ( EXIT_SUCCESS );
327  }
328  return ( EXIT_FAILURE );
329 }
int main(int argc, char **argv)
MatrixEpetra< Real > matrix_Type
uint32_type ID
IDs.
Definition: LifeV.hpp:194
Real uFct(const Real &, const Real &x, const Real &y, const Real &z, const ID &i)
Functions.
double Real
Generic real data.
Definition: LifeV.hpp:175
RegionMesh< LinearTetra > mesh_Type