LifeV
lifev/eta/tutorials/4_ETA_vectorial_laplacian/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 the assembly of the vectorial laplacian.
30 
31  @author Samuel Quinodoz <samuel.quinodoz@epfl.ch>
32  @date 08-10-2010
33 
34  In this tutorial, we revisit the first tutorial and explain how
35  to transform it so that the vectorial laplacian is assembled. This
36  gives an example of how to deal with vectorial unknowns.
37 
38  Tutorials that should be read before: 1
39  */
40 
41 // ---------------------------------------------------------------
42 // We use the same structure as the tutorial number 2, so that we
43 // can compare the results of the ETA framework with the classical
44 // assembly.
45 // ---------------------------------------------------------------
46 
47 
48 #include <Epetra_ConfigDefs.h>
49 #ifdef EPETRA_MPI
50 #include <mpi.h>
51 #include <Epetra_MpiComm.h>
52 #else
53 #include <Epetra_SerialComm.h>
54 #endif
55 
56 
57 #include <lifev/core/LifeV.hpp>
58 
59 #include <lifev/core/mesh/MeshPartitioner.hpp>
60 #include <lifev/core/mesh/RegionMesh3DStructured.hpp>
61 #include <lifev/core/mesh/RegionMesh.hpp>
62 
63 #include <lifev/core/array/MatrixEpetra.hpp>
64 #include <lifev/core/array/VectorEpetra.hpp>
65 
66 #include <lifev/eta/fem/ETFESpace.hpp>
67 #include <lifev/eta/expression/Integrate.hpp>
68 
69 #include <boost/shared_ptr.hpp>
70 
71 #include <lifev/core/fem/FESpace.hpp>
72 #include <lifev/core/solver/ADRAssembler.hpp>
73 
74 
75 // ---------------------------------------------------------------
76 // We work in the LifeV namespace and define the mesh, matrix and
77 // vector types that we will need several times.
78 // ---------------------------------------------------------------
79 
80 using namespace LifeV;
81 
83 typedef MatrixEpetra<Real> matrix_Type;
84 typedef VectorEpetra vector_Type;
85 
86 
87 // ---------------------------------------------------------------
88 // As usual, we start with the definition of the MPI communicator
89 // and the boolean for the outputs.
90 // ---------------------------------------------------------------
91 
92 int main ( int argc, char** argv )
93 {
94 
95 #ifdef HAVE_MPI
96  MPI_Init (&argc, &argv);
97  std::shared_ptr<Epetra_Comm> Comm (new Epetra_MpiComm (MPI_COMM_WORLD) );
98 #else
99  std::shared_ptr<Epetra_Comm> Comm (new Epetra_SerialComm);
100 #endif
101 
102  const bool verbose (Comm->MyPID() == 0);
103 
104 
105  // ---------------------------------------------------------------
106  // We define the mesh and parition it. We use again the domain
107  // (-1,1)x(-1,1)x(-1,1) and a structured mesh.
108  // ---------------------------------------------------------------
109 
110  if (verbose)
111  {
112  std::cout << " -- Building and partitioning the mesh ... " << std::flush;
113  }
114 
115  const UInt Nelements (10);
116 
117  std::shared_ptr< mesh_Type > fullMeshPtr (new mesh_Type ( Comm ) );
118 
119  regularMesh3D ( *fullMeshPtr, 1, Nelements, Nelements, Nelements, false,
120  2.0, 2.0, 2.0,
121  -1.0, -1.0, -1.0);
122 
123  std::shared_ptr< mesh_Type > meshPtr;
124  {
125  MeshPartitioner< mesh_Type > meshPart (fullMeshPtr, Comm);
126  meshPtr = meshPart.meshPartition();
127  }
128 
129  fullMeshPtr.reset();
130 
131  if (verbose)
132  {
133  std::cout << " done ! " << std::endl;
134  }
135 
136 
137  // ---------------------------------------------------------------
138  // To assemble a vectorial problem, the main difference is in the
139  // finite element space. To have a vectorial problem, we have to
140  // indicate that the dimension of the field is not 1, but 3 (at
141  // least in this example, but it could be 2 for a 2D problem).
142  //
143  // The field dimension appears as argument of the FESpace
144  // constructor and as template argument for the ETFESpace (it is
145  // the second 3, the first one indicates the dimension of the
146  // space).
147  // ---------------------------------------------------------------
148 
149  if (verbose)
150  {
151  std::cout << " -- Building the FESpace ... " << std::flush;
152  }
153 
154  std::string uOrder ("P1");
155 
156  std::shared_ptr<FESpace< mesh_Type, MapEpetra > > uSpace
157  ( new FESpace< mesh_Type, MapEpetra > (meshPtr, uOrder, 3, Comm) );
158 
159  if (verbose)
160  {
161  std::cout << " done ! " << std::endl;
162  }
163  if (verbose)
164  {
165  std::cout << " ---> Dofs: " << uSpace->dof().numTotalDof() << std::endl;
166  }
167 
168  if (verbose)
169  {
170  std::cout << " -- Building the ETFESpace ... " << std::flush;
171  }
172 
173  std::shared_ptr<ETFESpace< mesh_Type, MapEpetra, 3, 3 > > ETuSpace
174  ( new ETFESpace< mesh_Type, MapEpetra, 3, 3 > (meshPtr, & (uSpace->refFE() ), & (uSpace->fe().geoMap() ), Comm) );
175 
176  if (verbose)
177  {
178  std::cout << " done ! " << std::endl;
179  }
180  if (verbose)
181  {
182  std::cout << " ---> Dofs: " << ETuSpace->dof().numTotalDof() << std::endl;
183  }
184 
185 
186  // ---------------------------------------------------------------
187  // We build now two matrices, one for each assembly procedure in
188  // order to compare them in the end. There is no difference in the
189  // construction of the matrices with respect to the scalar case,
190  // as the map of the finite element spaces is already aware of the
191  // field dimension.
192  // ---------------------------------------------------------------
193 
194  if (verbose)
195  {
196  std::cout << " -- Defining the matrices ... " << std::flush;
197  }
198 
199  std::shared_ptr<matrix_Type> systemMatrix (new matrix_Type ( uSpace->map() ) );
200  *systemMatrix *= 0.0;
201 
202  std::shared_ptr<matrix_Type> ETsystemMatrix (new matrix_Type ( ETuSpace->map() ) );
203  *ETsystemMatrix *= 0.0;
204 
205  if (verbose)
206  {
207  std::cout << " done! " << std::endl;
208  }
209 
210 
211  // ---------------------------------------------------------------
212  // With the classical assembly, nothing changes with respect to
213  // a scalar laplacian.
214  // ---------------------------------------------------------------
215 
216  if (verbose)
217  {
218  std::cout << " -- Classical assembly ... " << std::flush;
219  }
220 
221  ADRAssembler<mesh_Type, matrix_Type, vector_Type> adrAssembler;
222 
223  adrAssembler.setup (uSpace, uSpace);
224 
225  adrAssembler.addDiffusion (systemMatrix, 1.0);
226 
227  if (verbose)
228  {
229  std::cout << " done ! " << std::endl;
230  }
231 
232 
233  // ---------------------------------------------------------------
234  // With the ETA framework, there is also no change with respect
235  // to the scalar case.
236  // ---------------------------------------------------------------
237 
238  if (verbose)
239  {
240  std::cout << " -- ET assembly ... " << std::flush;
241  }
242 
243 
244  {
245  using namespace ExpressionAssembly;
246 
247  integrate ( elements (ETuSpace->mesh() ),
248  uSpace->qr(),
249  ETuSpace,
250  ETuSpace,
251 
252  dot ( grad (phi_i) , grad (phi_j) )
253 
254  )
255  >> ETsystemMatrix;
256  }
257 
258  if (verbose)
259  {
260  std::cout << " done! " << std::endl;
261  }
262 
263  // ---------------------------------------------------------------
264  // We finally need to check that both yield the same matrix. In
265  // that aim, we need to finalize both matrices.
266  // ---------------------------------------------------------------
267 
268  if (verbose)
269  {
270  std::cout << " -- Closing the matrices ... " << std::flush;
271  }
272 
273  systemMatrix->globalAssemble();
274  ETsystemMatrix->globalAssemble();
275 
276  if (verbose)
277  {
278  std::cout << " done ! " << std::endl;
279  }
280 
281 
282  // ---------------------------------------------------------------
283  // We compute now the matrix of the difference and finally the
284  // norm of the difference. This should be very low if the two
285  // matrices are identical.
286  // ---------------------------------------------------------------
287 
288  if (verbose)
289  {
290  std::cout << " -- Computing the error ... " << std::flush;
291  }
292 
293  std::shared_ptr<matrix_Type> checkMatrix (new matrix_Type ( ETuSpace->map() ) );
294  *checkMatrix *= 0.0;
295 
296  *checkMatrix += *systemMatrix;
297  *checkMatrix += (*ETsystemMatrix) * (-1);
298 
299  checkMatrix->globalAssemble();
300 
301  Real errorNorm ( checkMatrix->normInf() );
302 
303  if (verbose)
304  {
305  std::cout << " done ! " << std::endl;
306  }
307 
308 
309  // ---------------------------------------------------------------
310  // We finalize the MPI if needed.
311  // ---------------------------------------------------------------
312 
313 #ifdef HAVE_MPI
314  MPI_Finalize();
315 #endif
316 
317 
318  // ---------------------------------------------------------------
319  // We finally display the error norm and compare with the
320  // tolerance of the test.
321  // ---------------------------------------------------------------
322 
323  if (verbose)
324  {
325  std::cout << " Matrix Error : " << errorNorm << std::endl;
326  }
327 
328  Real testTolerance (1e-10);
329 
330  if (errorNorm < testTolerance)
331  {
332  return ( EXIT_SUCCESS );
333  }
334  return ( EXIT_FAILURE );
335 }
int main(int argc, char **argv)
MatrixEpetra< Real > matrix_Type
double Real
Generic real data.
Definition: LifeV.hpp:175
RegionMesh< LinearTetra > mesh_Type