LifeV
lifev/level_set/tutorials/1_Volume_computation/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 introducing the expression assembly specialized for the level set problem.
30 
31  @author Samuel Quinodoz <samuel.quinodoz@epfl.ch>
32  @date 08-08-2012
33 
34  In this simple tutorial, we show how to use a special integration scheme
35  to compute the volume comprise in the domain {phi>0} where phi is a given
36  level set function. To this aim, we define a mesh, interpolate the phi function
37  on it and then use the special integration.
38 
39  Before reading this tutorial, the tutorials concerning the ETA module
40  should be read.
41  */
42 
43 // ---------------------------------------------------------------
44 // We include here the MPI headers for the parallel computations.
45 // The specific "pragma" instructions are used to avoid warning
46 // coming from the MPI library, that are not useful to us.
47 // ---------------------------------------------------------------
48 
49 #pragma GCC diagnostic ignored "-Wunused-variable"
50 #pragma GCC diagnostic ignored "-Wunused-parameter"
51 
52 #include <Epetra_ConfigDefs.h>
53 #ifdef EPETRA_MPI
54 #include <mpi.h>
55 #include <Epetra_MpiComm.h>
56 #else
57 #include <Epetra_SerialComm.h>
58 #endif
59 
60 #pragma GCC diagnostic warning "-Wunused-variable"
61 #pragma GCC diagnostic warning "-Wunused-parameter"
62 
63 
64 // ---------------------------------------------------------------
65 // We include then the required headers from LifeV. First of all,
66 // the definition file and mesh related files.
67 // ---------------------------------------------------------------
68 
69 #include <lifev/core/LifeV.hpp>
70 
71 #include <lifev/core/mesh/MeshPartitioner.hpp>
72 #include <lifev/core/mesh/RegionMesh3DStructured.hpp>
73 #include <lifev/core/mesh/RegionMesh.hpp>
74 
75 // ---------------------------------------------------------------
76 // We will need the EpetraVector and the FESpace
77 // (for the interpolation).
78 // ---------------------------------------------------------------
79 
80 #include <lifev/core/fem/FESpace.hpp>
81 #include <lifev/core/array/VectorEpetra.hpp>
82 
83 
84 // ---------------------------------------------------------------
85 // We will also need the ETFESpace from the ETA framework
86 // ---------------------------------------------------------------
87 
88 #include <lifev/eta/fem/ETFESpace.hpp>
89 
90 
91 // ---------------------------------------------------------------
92 // To have the ETA framework working here, we need to include
93 // this file, which defines the mechanism for the integration.
94 // ---------------------------------------------------------------
95 
96 #include <lifev/eta/expression/Integrate.hpp>
97 
98 
99 // ---------------------------------------------------------------
100 // Finally, we include shared pointer from boost since we use
101 // them explicitly in this tutorial.
102 // ---------------------------------------------------------------
103 
104 #include <boost/shared_ptr.hpp>
105 
106 
107 // ---------------------------------------------------------------
108 // We also use the integration scheme for the level set. To have
109 // it working, we need the following file:
110 // ---------------------------------------------------------------
111 
112 #include <lifev/level_set/fem/LevelSetQRAdapter.hpp>
113 
114 
115 // ---------------------------------------------------------------
116 // As usual, we work in the LifeV namespace. For clarity, we also
117 // make two typedefs for the mesh type and vector type.
118 // ---------------------------------------------------------------
119 
120 using namespace LifeV;
121 
123 typedef VectorEpetra vector_Type;
124 
125 
126 // ---------------------------------------------------------------
127 // We define also the level set function. Here, we set it to
128 // phi(x,y,z) = (x-3y)/sqrt(10)
129 // ---------------------------------------------------------------
130 
131 Real phiFct (const Real& /*t*/, const Real& x, const Real& y, const Real& /*z*/, const ID& /*i*/)
132 {
133  return (x - 3 * y) / std::sqrt (10);
134 }
135 
136 
137 // ---------------------------------------------------------------
138 // Finally, we also need a functor, to represent the Heaviside
139 // function, that we will need to integrate.
140 // ---------------------------------------------------------------
141 
143 {
144 public:
145 
146  typedef Real return_Type;
147 
148  return_Type operator() (const Real& value)
149  {
150  if (value > 0)
151  {
152  return 1;
153  }
154  return 0;
155  }
156 
158 
160 
162 };
163 
164 
165 // ---------------------------------------------------------------
166 // We start the programm by the definition of the communicator
167 // (as usual) depending on whether MPI is available or not. We
168 // also define a boolean to allow only one process to display
169 // messages.
170 // ---------------------------------------------------------------
171 
172 int main ( int argc, char** argv )
173 {
174 
175 #ifdef HAVE_MPI
176  MPI_Init (&argc, &argv);
177  std::shared_ptr<Epetra_Comm> Comm (new Epetra_MpiComm (MPI_COMM_WORLD) );
178 #else
179  std::shared_ptr<Epetra_Comm> Comm (new Epetra_SerialComm);
180 #endif
181 
182  const bool verbose (Comm->MyPID() == 0);
183 
184 
185  // ---------------------------------------------------------------
186  // The next step is to build the mesh. We use here a structured
187  // cartesian mesh over the square domain (-1,1)x(-1,1)x(-1,1).
188  // The mesh is the partitioned for the parallel computations and
189  // the original mesh is deleted.
190  // ---------------------------------------------------------------
191 
192  if (verbose)
193  {
194  std::cout << " -- Building and partitioning the mesh ... " << std::flush;
195  }
196 
197  const UInt Nelements (10);
198 
199  std::shared_ptr< mesh_Type > fullMeshPtr (new mesh_Type);
200 
201  regularMesh3D ( *fullMeshPtr, 1, Nelements, Nelements, Nelements, false,
202  2.0, 2.0, 2.0,
203  -1.0, -1.0, -1.0);
204 
205  MeshPartitioner< mesh_Type > meshPart (fullMeshPtr, Comm);
206 
207  fullMeshPtr.reset();
208 
209  if (verbose)
210  {
211  std::cout << " done ! " << std::endl;
212  }
213 
214 
215  // ---------------------------------------------------------------
216  // We define now the finite element space for the level set
217  // function. We use here piecewise linear elements.
218  // ---------------------------------------------------------------
219 
220  if (verbose)
221  {
222  std::cout << " -- Building ETFESpace ... " << std::flush;
223  }
224 
225  std::shared_ptr<ETFESpace< mesh_Type, MapEpetra, 3, 1 > > phiSpace
226  ( new ETFESpace< mesh_Type, MapEpetra, 3, 1 > (meshPart, &feTetraP1, Comm) );
227 
228  if (verbose)
229  {
230  std::cout << " done ! " << std::endl;
231  }
232  if (verbose)
233  {
234  std::cout << " ---> Dofs: " << phiSpace->dof().numTotalDof() << std::endl;
235  }
236 
237 
238  // ---------------------------------------------------------------
239  // For the interpolation, we need the FESpace.
240  // ---------------------------------------------------------------
241 
242  if (verbose)
243  {
244  std::cout << " -- Interpolation ... " << std::flush;
245  }
246 
247  std::string phiOrder ("P1");
248  FESpace<mesh_Type, MapEpetra> interpolationSpace (meshPart, phiOrder, 1, Comm);
249 
250  vector_Type phiInterpolated (phiSpace->map(), Repeated);
251  interpolationSpace.interpolate (phiFct, phiInterpolated, 0.0);
252 
253  if (verbose)
254  {
255  std::cout << " done ! " << std::endl;
256  }
257 
258 
259  // ---------------------------------------------------------------
260  // We compute now the volume taken by the phase {phi>0}, that is
261  // the volume integral of the heaviside function of phi.
262  // ---------------------------------------------------------------
263 
264  if (verbose)
265  {
266  std::cout << " -- Computing the volume " << std::flush;
267  }
268 
269  Real localVolume (0.0);
270 
271  // ---------------------------------------------------------------
272  // We can now perform the integration. The evaluation (3rd
273  // argument) represents the heaviside function of phi.
274  //
275  // The interesting difference is the 2nd argument, which is
276  // usually the quadrature rule. Here, it is replaced by this
277  // call to the special function "adapt", which transforms the
278  // quadrature rule depending on the element encountered.
279  //
280  // The arguments to the adapt are the following:
281  // - phiSpace: the finite element space in which the level set
282  // values are defined
283  // - phiInterpolated: the values of the level set in the FE space
284  // - quadRuleTetra1pt: the quadrature to adapt.
285  // ---------------------------------------------------------------
286 
287  {
288  using namespace ExpressionAssembly;
289 
290  std::shared_ptr<HeavisideFunctor> heaviside (new HeavisideFunctor);
291 
292  integrate ( elements (phiSpace->mesh() ),
293  adapt (phiSpace, phiInterpolated, quadRuleTetra1pt),
294  eval (heaviside, value (phiSpace, phiInterpolated) )
295 
296  )
297  >> localVolume;
298  }
299 
300  Real globalVolume (0.0);
301 
302  Comm->Barrier();
303  Comm->SumAll (&localVolume, &globalVolume, 1);
304 
305  if (verbose)
306  {
307  std::cout << " done! " << std::endl;
308  }
309  if (verbose)
310  {
311  std::cout << " Volume: " << globalVolume << std::endl;
312  }
313 
314 
315  // ---------------------------------------------------------------
316  // We finalize the MPI session if MPI was used
317  // ---------------------------------------------------------------
318 
319 #ifdef HAVE_MPI
320  MPI_Finalize();
321 #endif
322 
323  // ---------------------------------------------------------------
324  // Finally, we check the norm with respect to a previously
325  // computed one to ensure that it has not changed.
326  // ---------------------------------------------------------------
327 
328  Real tol (1e-10);
329  Real absError (std::abs (globalVolume - 4) );
330 
331  if (verbose)
332  {
333  std::cout << " Error : " << absError << std::endl;
334  }
335 
336  if ( absError < tol )
337  {
338  return ( EXIT_SUCCESS );
339  }
340  return ( EXIT_FAILURE );
341 
342 }
int main(int argc, char **argv)
Real phiFct(const Real &, const Real &x, const Real &y, const Real &, const ID &)
uint32_type ID
IDs.
Definition: LifeV.hpp:194
double Real
Generic real data.
Definition: LifeV.hpp:175
RegionMesh< LinearTetra > mesh_Type