LifeV
ADRAssembler.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 File containing the ADRAssembler class.
30 
31  @author Samuel Quinodoz <samuel.quinodoz@epfl.ch>
32  @date 28-09-2010
33 
34  @contributor Samuel Quinodoz <samuel.quinodoz@epfl.ch>
35  @mantainer Samuel Quinodoz <samuel.quinodoz@epfl.ch>
36 
37  */
38 
39 #ifndef ADRASSEMBLER_H
40 #define ADRASSEMBLER_H 1
41 
42 
43 #include <boost/scoped_ptr.hpp>
44 
45 
46 #include <lifev/core/LifeV.hpp>
47 
48 #include <lifev/core/util/LifeChrono.hpp>
49 
50 #include <lifev/core/fem/Assembly.hpp>
51 #include <lifev/core/fem/FESpace.hpp>
52 #include <lifev/core/fem/AssemblyElemental.hpp>
53 
54 namespace LifeV
55 {
56 
57 //! ADRAssembler - This class add into given matrices terms corresponding to the space discretization of the ADR problem.
58 /*!
59 
60  <b> Scope </b>
61 
62  This class has been designed for assembling the terms arising
63  from the space discretization with finite elements of the advection-diffusion-reaction
64  problem, i.e. of the PDE
65 
66  \f$ - \alpha \Delta u + \beta \cdot \nabla u + \sigma u = f \f$
67 
68  where \f$\alpha\f$ and \f$\sigma\f$ are constants, \f$\beta\f$ a vectorial field.
69 
70  Time discretization of the parabolic version of this equation is not in the scope of
71  this assembler (it is usually not a finite element discretization) and has to be
72  treated outside of the class.
73 
74  This class is also not supposed to provide any stabilization for the discretization.
75 
76 
77  <b> Good Practice </b>
78 
79  Here is the way this class is intended to be used. First, one should define the
80  assembler. Only the empty constructor is available, so there is no choice.
81 
82  \code
83  ADRAssembler<mesh_type,matrix_type,vector_type> myAssembler;
84  \endcode
85 
86  Then, one should setup the assembler by providing the finite element spaces
87  required, namely the space for the unknown and the space where the advection
88  field \f$\beta\f$ is defined
89 
90  \code
91  std::shared_ptr<FESpace< mesh_type, MapEpetra > > uFESpace( new FESpace< mesh_type, MapEpetra >( ... ));
92  std::shared_ptr<FESpace< mesh_type, MapEpetra > > betaFESpace( new FESpace< mesh_type, MapEpetra >( ... ));
93 
94  myAssembler.setup(uFESpace,betaFESpace);
95  \endcode
96 
97  When this setup method is used, the quadrature rules are set as the one
98  stored in the FESpace of the unknown. One should then change them if one wants to
99  have a more precise or a faster assembly (usually, the default quadrature is too
100  precise for diffusion and the advection terms, so one should consider this option
101  to make the assembly faster without affecting the results).
102 
103  \code
104  myAssembler.setQuadRuleForDiffusionMatrix( ... );
105  myAssembler.setQuadRuleForAdvectionMatrix( ... );
106  \endcode
107 
108  Now that everything has been set up, one can assemble the terms:
109 
110  \code
111  std::shared_ptr<matrix_type> systemMatrix(new matrix_type( uFESpace->map() ));
112  *systemMatrix*=0.0;
113 
114  myAssembler.addDiffusion(systemMatrix,4.0);
115  myAssembler.addMass(systemMatrix);
116  \endcode
117 
118  These two last lines have added the required terms into the matrix. Here one should
119  be aware that the matrix is NOT finalized after the assembly of any of the terms.
120  Therefore, before passing the matrix to a linear solver (and before applying boundary
121  conditions), one should close the matrix using
122 
123  \code
124  systemMatrix->GlobalAssemble();
125  \endcode
126 
127 
128  <b> Remarks </b>
129 
130  <ol>
131  <li> Changing the quadratures of the assembler is in many case a good idea. However, try to
132  avoid calling the setters for the quadratures when it is not necessary, as these methods change
133  some internal containers and are then more expensive than "simple setters".
134  <li> In case the FESpace for the unknown is vectorial (and not scalar), the problem is assembled
135  for each component of the FESpace.
136  <li> The matrices assembled are NOT stored in this class, so calling twice the same assembly method
137  will not make it faster. If your code calles repeatedly the assembly procedures, consider storing the
138  matrices outside the class.
139  </ol>
140 
141 
142  <b> Troubleshooting </b>
143 
144  <i> Empty FE Space cannot setup the ADR assembler </i> You are passing a nul pointer as FE Space in the setup method.
145 
146  <i> Empty beta FE Space cannot setup the ADR assembler </i> You are passing a nul pointer as FE Space for the advection field in the setup method.
147 
148  <i> Setting the FE space for the unknown to 0 is not permitted </i> You are passing a nul pointer as FE Space in the setFespace method.
149 
150  <i> No FE space for the unknown! Use setFespace before setBetaFespace! </i> You are trying to use the method setBetaFespace before having set the FE space for the unknown.
151 
152  <i> No FE space for assembling the mass! </i> You are trying to use the addMass method without having set a FE Space for the unknown. Use the setup or the setFespace methods before calling addMass.
153 
154  <i> No FE space for assembling the advection! </i> You are trying to use the addAdvection method without having set a FE Space for the unknown. Use the setup or the setFespace methods before calling addAdvection.
155 
156  <i> No FE space for assembling the diffusion! </i> You are trying to use the addDiffusion method without having set a FE Space for the unknown. Use the setup or the setFespace methods before calling addDiffusion.
157 
158  <i> No FE space (beta) for assembling the advection! </i> You are trying to add advection without having set the FE space for the advection field. Use the setup of the setBetaFespace methods before calling addAdvection.
159 
160 
161  @author Samuel Quinodoz
162  @version 1.1
163 */
164 
165 template< typename mesh_type, typename matrix_type, typename vector_type>
166 class ADRAssembler
167 {
168 public:
169 
170  //! @name Public Types
171  //@{
172 
173  typedef MapEpetra map_Type;
174 
175  typedef FESpace<mesh_type, map_Type> fespace_type;
176  typedef std::shared_ptr<fespace_type> fespace_ptrType;
177 
178  typedef std::shared_ptr<matrix_type> matrix_ptrType;
179 
180  typedef LifeChrono chrono_type;
181 
182  // Use the portable syntax of the boost function
183  typedef std::function<Real (const Real&, const Real&, const Real&, const Real&, const ID&) > function_type;
184 
185  //@}
186 
187 
188  //! @name Constructor & Destructor
189  //@{
190 
191  //! Empty Constructor
192  ADRAssembler();
193 
194  //! Destructor
195  virtual ~ADRAssembler() {}
196 
197  //@}
198 
199 
200 
201  //! @name Methods
202  //@{
203 
204  //! Setup for the class (fill the members)
205  /*!
206  This method can be called either when the class is empty or when is already (partially)
207  setup. It changes the internal containers to fit with the FESpace given in argument.
208  All the quadrature rules are overriden by the one given in fespace.
209  @param fespace The FESpace for the unknown
210  @param betaFESpace The FESpace for the advection field
211  @remark Nul pointers cannot be passed to this method. Use a more
212  specific setter if you want to do that.
213  */
214  void setup (const fespace_ptrType& fespace, const fespace_ptrType& betaFESpace);
215 
216  //! Assembling for the mass
217  /*!
218  This method adds the mass matrix times the coefficient
219  (whose default value is 1.0) to the matrix passed in argument.
220  @Remark The matrix is NOT finalized, you have to call globalAssemble
221  outside this method when the matrix is finished.
222  */
223  inline void addMass (matrix_ptrType matrix, const Real& coefficient = 1.0)
224  {
225  addMass (matrix, coefficient, 0, 0);
226  }
227 
228  //! Assembling for the mass using offsets
229  /*!
230  This method adds the mass in the given matrix. Additional arguements are provided
231  so that one can chose where to add the mass in the matrix, i.e. somewhere else
232  than in the upper left block.
233  */
234  void addMass (matrix_ptrType matrix, const Real& coefficient, const UInt& offsetLeft, const UInt& offsetUp);
235 
236  //! Assembling for the advection
237  /*!
238  This method adds the advection (with respect to the
239  given vector field) matrix to the matrix passed in argument.
240  beta represents a finite element function with the beta FE space
241  of this assembler.
242  @Remark The matrix is NOT finalized, you have to call globalAssemble
243  outside this method when the matrix is finished.
244  */
245  inline void addAdvection (matrix_ptrType matrix, const vector_type& beta)
246  {
247  addAdvection (matrix, beta, 0, 0);
248  }
249 
250  //! Assembling for the advection using offsets
251  /*!
252  This method adds the advection in the given matrix. Additional arguements are provided
253  so that one can chose where to add the mass in the matrix, i.e. somewhere else
254  than in the upper left block.
255  */
256  void addAdvection (matrix_ptrType matrix, const vector_type& beta, const UInt& offsetLeft, const UInt& offsetUp);
257 
258  //! Assembling for the diffusion
259  /*!
260  This method adds the diffusion matrix times the coefficient
261  (whose default value is 1.0) to the matrix passed in argument.
262  @Remark The matrix is NOT finalized, you have to call globalAssemble
263  outside this method when the matrix is finished.
264  */
265  inline void addDiffusion (matrix_ptrType matrix, const Real& coefficient = 1.0)
266  {
267  addDiffusion (matrix, coefficient, 0, 0);
268  }
269 
270  //! Assembling for the diffusion using offsets
271  /*!
272  This method adds the diffusion in the given matrix. Additional arguements are provided
273  so that one can chose where to add the mass in the matrix, i.e. somewhere else
274  than in the upper left block.
275  */
276  void addDiffusion (matrix_ptrType matrix, const Real& coefficient, const UInt& offsetLeft, const UInt& offsetUp);
277 
278  //! Add the stiff strain in the standard block
279  void addStiffStrain (matrix_ptrType& matrix, const Real& coefficient = 1.0)
280  {
281  addStiffStrain (matrix, coefficient, 0, 0);
282  };
283 
284  //! Add the stiff strain using the given offsets
285  void addStiffStrain (matrix_ptrType& matrix, const Real& coefficient, const UInt& offsetLeft, const UInt& offsetUp);
286 
287  //! Assembly for the right hand side (mass) with f given in vectorial form.
288  /*!
289  This method assembles the right hand side for the ADR problem
290  where the forcing term is given in the FE space of the unknown.
291  */
292  void addMassRhs (vector_type& rhs, const vector_type& f);
293 
294  //! Assembly for the right hand side (mass) with f given in functional form.
295  /*!
296  This method assembles the right hand side for the ADR problem
297  where f is given as a function of space and time (t,x,y,z,component)
298  */
299  void addMassRhs (vector_type& rhs, const function_type& f, const Real& t);
300 
301  //@}
302 
303 
304 
305  //! @name Set Methods
306  //@{
307 
308  //! Setter for the finite element space used for the unknown (reset the quadratures as well!)
309  void setFespace (const fespace_ptrType& fespace);
310 
311  //! Setter for the finite element space used for the advection field (reset the quadratures as well!)
312  /*!
313  Beware that a FE space for the unknown has to be set before calling this method.
314  */
315  void setBetaFespace (const fespace_ptrType& betaFESpace);
316 
317  //! Setter for the quadrature used for the mass matrix
318  /*!
319  Beware that calling this function might be quite heavy, so avoid using
320  it when it is not necessary.
321  */
322  inline void setQuadRuleForMassMatrix (const QuadratureRule& qr)
323  {
324  ASSERT (M_massCFE != 0, "No mass currentFE for setting the quadrature rule!");
325  M_massCFE->setQuadRule (qr);
326  }
327 
328  //! Setter for the quadrature used for the diffusion matrix
329  /*!
330  Beware that calling this function might be quite heavy, so avoid using
331  it when it is not necessary.
332  */
333  inline void setQuadRuleForDiffusionMatrix (const QuadratureRule& qr)
334  {
335  ASSERT (M_diffCFE != 0, "No diffusion currentFE for setting the quadrature rule!");
336  M_diffCFE->setQuadRule (qr);
337  }
338 
339  //! Setter for the quadrature used for the advection matrix
340  /*!
341  Beware that calling this function might be quite heavy, so avoid using
342  it when it is not necessary.
343  */
344  inline void setQuadRuleForAdvectionMatrix (const QuadratureRule& qr)
345  {
346  ASSERT (M_advCFE != 0, "No advection (u) currentFE for setting the quadrature rule!");
347  ASSERT (M_advBetaCFE != 0, "No advection (beta) currentFE for setting the quadrature rule!");
348  M_advCFE->setQuadRule (qr);
349  M_advBetaCFE->setQuadRule (qr);
350  }
351 
352  //! Setter for the quadrature used for the right hand side
353  /*!
354  Beware that calling this function might be quite heavy, so avoid using
355  it when it is not necessary.
356  */
357  inline void setQuadRuleForMassRhs (const QuadratureRule& qr)
358  {
359  ASSERT (M_massRhsCFE != 0, "No Rhs currentFE for setting the quadrature rule!");
360  M_massRhsCFE->setQuadRule (qr);
361  }
362 
363  //@}
364 
365 
366  //! @name Get Methods
367  //@{
368 
369  //! Getter for the chrono of the assembly of the mass term
370  chrono_type& massAssemblyChrono()
371  {
372  return M_massAssemblyChrono;
373  }
374 
375  //! Getter for the chrono of the assembly of the advection term
376  chrono_type& advectionAssemblyChrono()
377  {
378  return M_advectionAssemblyChrono;
379  }
380 
381  //! Getter for the chrono of the assembly of the diffusion term
382  chrono_type& diffusionAssemblyChrono()
383  {
384  return M_diffusionAssemblyChrono;
385  }
386 
387  //! Getter for the chrono of the setup of the assembler
388  chrono_type& setupChrono()
389  {
390  return M_setupChrono;
391  }
392 
393  //! Getter for the chrono of the assembly of the rhs (mass)
394  chrono_type& massRhsAssemblyChrono()
395  {
396  return M_massRhsAssemblyChrono;
397  }
398 
399  //@}
400 
401 private:
402 
403 
404  typedef CurrentFE currentFE_type;
405  typedef std::unique_ptr<currentFE_type> currentFE_ptrType;
406 
407  typedef MatrixElemental localMatrix_type;
408  typedef std::unique_ptr<localMatrix_type> localMatrix_ptrType;
409 
410  typedef VectorElemental localVector_type;
411  typedef std::unique_ptr<localVector_type> localVector_ptrType;
412 
413  //! @name Private Methods
414  //@{
415 
416  // Copy constructor is a no-sense.
417  ADRAssembler (const ADRAssembler&);
418 
419  //@}
420 
421  // Finite element space for the unknown
422  fespace_ptrType M_fespace;
423 
424  // Finite element space for the advection
425  fespace_ptrType M_betaFESpace;
426 
427  // CurrentFE for the mass
428  currentFE_ptrType M_massCFE;
429 
430  // CurrentFE for the diffusion
431  currentFE_ptrType M_diffCFE;
432 
433  // CurrentFE for the advection (unknown)
434  currentFE_ptrType M_advCFE;
435 
436  // CurrentFE for the advection (beta)
437  currentFE_ptrType M_advBetaCFE;
438 
439  // CurrentFE for the mass rhs
440  currentFE_ptrType M_massRhsCFE;
441 
442 
443  // Local matrix for the mass
444  localMatrix_ptrType M_localMass;
445 
446  // Local advection matrix
447  localMatrix_ptrType M_localAdv;
448 
449  // Local matrix for the diffusion
450  localMatrix_ptrType M_localDiff;
451 
452  // Local vector for the right hand side
453  localVector_ptrType M_localMassRhs;
454 
455  // Chronos
456  chrono_type M_diffusionAssemblyChrono;
457  chrono_type M_advectionAssemblyChrono;
458  chrono_type M_massAssemblyChrono;
459  chrono_type M_setupChrono;
460  chrono_type M_massRhsAssemblyChrono;
461 
462 };
463 
464 
465 
466 template<typename mesh_type, typename matrix_type, typename vector_type>
467 ADRAssembler< mesh_type, matrix_type, vector_type>::
468 ADRAssembler() :
469 
470  M_fespace(),
471  M_betaFESpace(),
472 
473  M_massCFE(),
474  M_diffCFE(),
475  M_advCFE(),
476  M_advBetaCFE(),
477  M_massRhsCFE(),
478 
479  M_localMass(),
480  M_localAdv(),
481  M_localDiff(),
482  M_localMassRhs(),
483 
484  M_diffusionAssemblyChrono(),
485  M_advectionAssemblyChrono(),
486  M_massAssemblyChrono(),
487  M_setupChrono(),
488  M_massRhsAssemblyChrono()
489 {}
490 
491 // ===================================================
492 // Constructors & Destructor
493 // ===================================================
494 
495 template<typename mesh_type, typename matrix_type, typename vector_type>
496 void
497 ADRAssembler< mesh_type, matrix_type, vector_type>::
498 setup ( const fespace_ptrType& fespace, const fespace_ptrType& betaFESpace )
499 {
500  ASSERT (fespace != 0, " Empty FE Space cannot setup the ADR assembler ");
501  ASSERT (betaFESpace != 0, "Empty beta FE Space cannot setup the ADR assembler ");
502 
503  M_setupChrono.start();
504 
505  setFespace (fespace);
506  setBetaFespace (betaFESpace);
507 
508  M_setupChrono.stop();
509 }
510 
511 // ===================================================
512 // Methods
513 // ===================================================
514 
515 template<typename mesh_type, typename matrix_type, typename vector_type>
516 void
517 ADRAssembler< mesh_type, matrix_type, vector_type>::
518 addMass (matrix_ptrType matrix, const Real& coefficient, const UInt& offsetLeft, const UInt& offsetUp)
519 {
520  // Check that the fespace is set
521  ASSERT (M_fespace != 0, "No FE space for assembling the mass!");
522 
523  M_massAssemblyChrono.start();
524 
525  // Some constants
526  const UInt nbElements (M_fespace->mesh()->numElements() );
527  const UInt fieldDim (M_fespace->fieldDim() );
528  const UInt nbTotalDof (M_fespace->dof().numTotalDof() );
529 
530  // Loop over the elements
531  for (UInt iterElement (0); iterElement < nbElements; ++iterElement)
532  {
533  // Update the mass current FE
534  M_massCFE->update ( M_fespace->mesh()->element (iterElement), UPDATE_WDET );
535 
536  // Clean the local matrix
537  M_localMass->zero();
538 
539  // Local Mass
540  AssemblyElemental::mass (*M_localMass, *M_massCFE, coefficient, fieldDim);
541 
542  // Assembly
543  for (UInt iFieldDim (0); iFieldDim < fieldDim; ++iFieldDim)
544  {
545  assembleMatrix ( *matrix,
546  *M_localMass,
547  *M_massCFE,
548  *M_massCFE,
549  M_fespace->dof(),
550  M_fespace->dof(),
551  iFieldDim, iFieldDim,
552  iFieldDim * nbTotalDof + offsetLeft, iFieldDim * nbTotalDof + offsetUp);
553  }
554  }
555 
556  M_massAssemblyChrono.stop();
557 }
558 
559 
560 template<typename mesh_type, typename matrix_type, typename vector_type>
561 void
562 ADRAssembler< mesh_type, matrix_type, vector_type>::
563 addAdvection (matrix_ptrType matrix, const vector_type& beta, const UInt& offsetLeft, const UInt& offsetUp)
564 {
565  // Beta has to be repeated!
566  if (beta.mapType() == Unique)
567  {
568  addAdvection (matrix, vector_type (beta, Repeated), offsetLeft, offsetUp);
569  return;
570  }
571 
572  // Check that the fespace is set
573  ASSERT (M_fespace != 0, "No FE space for assembling the advection!");
574  ASSERT (M_betaFESpace != 0, "No FE space (beta) for assembling the advection!");
575 
576  M_advectionAssemblyChrono.start();
577 
578 
579  // Some constants
580  const UInt nbElements (M_fespace->mesh()->numElements() );
581  const UInt fieldDim (M_fespace->fieldDim() );
582  const UInt betaFieldDim (M_betaFESpace->fieldDim() );
583  const UInt nbTotalDof (M_fespace->dof().numTotalDof() );
584  const UInt nbQuadPt (M_advCFE->nbQuadPt() );
585 
586  // Temporaries
587  //Real localValue(0);
588  std::vector< std::vector< Real > > localBetaValue (nbQuadPt, std::vector<Real> ( betaFieldDim, 0.0 ) );
589 
590  // Loop over the elements
591  for (UInt iterElement (0); iterElement < nbElements; ++iterElement)
592  {
593  // Update the advection current FEs
594  M_advCFE->update ( M_fespace->mesh()->element (iterElement), UPDATE_DPHI | UPDATE_WDET );
595 
596  // Clean the local matrix
597  M_localAdv->zero();
598 
599  // Interpolate beta in the quadrature points
600  AssemblyElemental::interpolate (localBetaValue, *M_advBetaCFE, betaFieldDim, M_betaFESpace->dof(), iterElement, beta);
601 
602  // Assemble the advection
603  AssemblyElemental::advection (*M_localAdv, *M_advCFE, 1.0, localBetaValue, fieldDim);
604 
605 
606  // Assembly
607  for (UInt iFieldDim (0); iFieldDim < fieldDim; ++iFieldDim)
608  {
609  assembleMatrix ( *matrix,
610  *M_localAdv,
611  *M_advCFE,
612  *M_advCFE,
613  M_fespace->dof(),
614  M_fespace->dof(),
615  iFieldDim, iFieldDim,
616  iFieldDim * nbTotalDof + offsetLeft, iFieldDim * nbTotalDof + offsetUp );
617  }
618  }
619 
620  M_advectionAssemblyChrono.stop();
621 }
622 
623 template<typename mesh_type, typename matrix_type, typename vector_type>
624 void
625 ADRAssembler< mesh_type, matrix_type, vector_type>::
626 addDiffusion (matrix_ptrType matrix, const Real& coefficient, const UInt& offsetLeft, const UInt& offsetUp)
627 {
628  // Check that the fespace is set
629  ASSERT (M_fespace != 0, "No FE space for assembling the diffusion!");
630 
631  M_diffusionAssemblyChrono.start();
632 
633  // Some constants
634  const UInt nbElements (M_fespace->mesh()->numElements() );
635  const UInt fieldDim (M_fespace->fieldDim() );
636  const UInt nbTotalDof (M_fespace->dof().numTotalDof() );
637 
638  // Loop over the elements
639  for (UInt iterElement (0); iterElement < nbElements; ++iterElement)
640  {
641  // Update the diffusion current FE
642  M_diffCFE->update ( M_fespace->mesh()->element (iterElement), UPDATE_DPHI | UPDATE_WDET );
643 
644  // Clean the local matrix
645  M_localDiff->zero();
646 
647  // local stiffness
648  AssemblyElemental::stiffness (*M_localDiff, *M_diffCFE, coefficient, fieldDim);
649 
650  // Assembly
651  for (UInt iFieldDim (0); iFieldDim < fieldDim; ++iFieldDim)
652  {
653  assembleMatrix ( *matrix,
654  *M_localDiff,
655  *M_diffCFE,
656  *M_diffCFE,
657  M_fespace->dof(),
658  M_fespace->dof(),
659  iFieldDim, iFieldDim,
660  iFieldDim * nbTotalDof + offsetLeft, iFieldDim * nbTotalDof + offsetUp );
661  }
662  }
663 
664  M_diffusionAssemblyChrono.stop();
665 }
666 
667 template< typename mesh_type, typename matrix_type, typename vector_type>
668 void
669 ADRAssembler<mesh_type, matrix_type, vector_type>::
670 addStiffStrain (matrix_ptrType& matrix, const Real& coefficient, const UInt& offsetLeft, const UInt& offsetUp)
671 {
672  ASSERT (M_fespace != 0, "No FE space for assembling the stiff strain.");
673  ASSERT (offsetLeft + M_fespace->dof().numTotalDof() * (M_fespace->fieldDim() ) <=
674  UInt (matrix->matrixPtr()->NumGlobalCols() ),
675  " The matrix is too small (columns) for the assembly of the stiff strain");
676  ASSERT (offsetUp + M_fespace->dof().numTotalDof() * (M_fespace->fieldDim() ) <=
677  UInt (matrix->matrixPtr()->NumGlobalRows() ),
678  " The matrix is too small (rows) for the assembly of the stiff strain");
679 
680  // Some constants
681  const UInt nbElements (M_fespace->mesh()->numElements() );
682  const UInt fieldDim (M_fespace->fieldDim() );
683  const UInt nbTotalDof (M_fespace->dof().numTotalDof() );
684 
685  // Loop over the elements
686  for (UInt iterElement (0); iterElement < nbElements; ++iterElement)
687  {
688  // Update the diffusion current FE
689  M_diffCFE->update ( M_fespace->mesh()->element (iterElement), UPDATE_DPHI | UPDATE_WDET );
690 
691  // Clean the local matrix
692  M_localDiff->zero();
693 
694  // local stiffness
695  AssemblyElemental::stiffStrain (*M_localDiff, *M_diffCFE, 2.0 * coefficient, fieldDim);
696 
697  // Assembly
698  for (UInt iFieldDim (0); iFieldDim < fieldDim; ++iFieldDim)
699  {
700  for (UInt jFieldDim (0); jFieldDim < fieldDim; ++jFieldDim)
701  {
702  assembleMatrix ( *matrix,
703  *M_localDiff,
704  *M_diffCFE,
705  *M_diffCFE,
706  M_fespace->dof(),
707  M_fespace->dof(),
708  iFieldDim, jFieldDim,
709  iFieldDim * nbTotalDof + offsetUp, jFieldDim * nbTotalDof + offsetLeft);
710  }
711  }
712  }
713 }
714 
715 template<typename mesh_type, typename matrix_type, typename vector_type>
716 void
717 ADRAssembler< mesh_type, matrix_type, vector_type>::
718 addMassRhs (vector_type& rhs, const vector_type& f)
719 {
720  // f has to be repeated!
721  if (f.mapType() == Unique)
722  {
723  addMassRhs (rhs, vector_type (f, Repeated) );
724  return;
725  }
726 
727  // Check that the fespace is set
728  ASSERT (M_fespace != 0, "No FE space for assembling the right hand side (mass)!");
729 
730  M_massRhsAssemblyChrono.start();
731 
732  // Some constants
733  const UInt nbElements (M_fespace->mesh()->numElements() );
734  const UInt fieldDim (M_fespace->fieldDim() );
735  const UInt nbFEDof (M_massRhsCFE->nbFEDof() );
736  const UInt nbQuadPt (M_massRhsCFE->nbQuadPt() );
737  const UInt nbTotalDof (M_fespace->dof().numTotalDof() );
738 
739  // Temporaries
740  Real localValue (0.0);
741  std::vector<Real> fValues (nbQuadPt, 0.0);
742 
743  // Loop over the elements
744  for (UInt iterElement (0); iterElement < nbElements; ++iterElement)
745  {
746  // Update the diffusion current FE
747  M_massRhsCFE->update ( M_fespace->mesh()->element (iterElement), UPDATE_WDET );
748 
749  // Clean the local matrix
750  M_localMassRhs->zero();
751 
752  // Assemble the local diffusion
753  for (UInt iterFDim (0); iterFDim < fieldDim; ++iterFDim)
754  {
755  localVector_type::vector_view localView = M_localMassRhs->block (iterFDim);
756 
757  // Compute the value of f in the quadrature nodes
758  for (UInt iQuadPt (0); iQuadPt < nbQuadPt; ++iQuadPt)
759  {
760  fValues[iQuadPt] = 0.0;
761  for (UInt iDof (0); iDof < nbFEDof ; ++iDof)
762  {
763  fValues[iQuadPt] +=
764  f[ M_fespace->dof().localToGlobalMap (iterElement, iDof) + iterFDim * nbTotalDof]
765  * M_massRhsCFE->phi (iDof, iQuadPt);
766  }
767  }
768 
769  // Loop over the basis functions
770  for (UInt iDof (0); iDof < nbFEDof ; ++iDof)
771  {
772  localValue = 0.0;
773 
774  //Loop on the quadrature nodes
775  for (UInt iQuadPt (0); iQuadPt < nbQuadPt; ++iQuadPt)
776  {
777  localValue += fValues[iQuadPt]
778  * M_massRhsCFE->phi (iDof, iQuadPt)
779  * M_massRhsCFE->wDetJacobian (iQuadPt);
780  }
781 
782  // Add on the local matrix
783  localView (iDof) = localValue;
784  }
785  }
786 
787  // Here add in the global rhs
788  for (UInt iterFDim (0); iterFDim < fieldDim; ++iterFDim)
789  {
790  assembleVector ( rhs,
791  iterElement,
792  *M_localMassRhs,
793  nbFEDof,
794  M_fespace->dof(),
795  iterFDim,
796  iterFDim * M_fespace->dof().numTotalDof() );
797  }
798  }
799 
800  M_massRhsAssemblyChrono.stop();
801 }
802 
803 template<typename mesh_type, typename matrix_type, typename vector_type>
804 void
805 ADRAssembler< mesh_type, matrix_type, vector_type>::
806 addMassRhs (vector_type& rhs, const function_type& f, const Real& t)
807 {
808  // Check that the fespace is set
809  ASSERT (M_fespace != 0, "No FE space for assembling the right hand side (mass)!");
810 
811  M_massRhsAssemblyChrono.start();
812 
813  // Some constants
814  const UInt nbElements (M_fespace->mesh()->numElements() );
815  const UInt fieldDim (M_fespace->fieldDim() );
816  const UInt nbFEDof (M_massRhsCFE->nbFEDof() );
817  const UInt nbQuadPt (M_massRhsCFE->nbQuadPt() );
818 
819  // Temporaries
820  Real localValue (0.0);
821  std::vector<Real> fValues (nbQuadPt, 0.0);
822 
823  // Loop over the elements
824  for (UInt iterElement (0); iterElement < nbElements; ++iterElement)
825  {
826  // Update the diffusion current FE
827  M_massRhsCFE->update ( M_fespace->mesh()->element (iterElement), UPDATE_QUAD_NODES | UPDATE_WDET );
828 
829  // Clean the local matrix
830  M_localMassRhs->zero();
831 
832  // Assemble the local diffusion
833  for (UInt iterFDim (0); iterFDim < fieldDim; ++iterFDim)
834  {
835  localVector_type::vector_view localView = M_localMassRhs->block (iterFDim);
836 
837  // Compute the value of f in the quadrature nodes
838  for (UInt iQuadPt (0); iQuadPt < nbQuadPt; ++iQuadPt)
839  {
840  fValues[iQuadPt] = f (t,
841  M_massRhsCFE->quadNode (iQuadPt, 0),
842  M_massRhsCFE->quadNode (iQuadPt, 1),
843  M_massRhsCFE->quadNode (iQuadPt, 2),
844  iterFDim);
845  }
846 
847  // Loop over the basis functions
848  for (UInt iDof (0); iDof < nbFEDof ; ++iDof)
849  {
850  localValue = 0.0;
851 
852  //Loop on the quadrature nodes
853  for (UInt iQuadPt (0); iQuadPt < nbQuadPt; ++iQuadPt)
854  {
855  localValue += fValues[iQuadPt]
856  * M_massRhsCFE->phi (iDof, iQuadPt)
857  * M_massRhsCFE->wDetJacobian (iQuadPt);
858  }
859 
860  // Add on the local matrix
861  localView (iDof) = localValue;
862  }
863  }
864 
865  // Here add in the global rhs
866  for (UInt iterFDim (0); iterFDim < fieldDim; ++iterFDim)
867  {
868  assembleVector ( rhs,
869  iterElement,
870  *M_localMassRhs,
871  nbFEDof,
872  M_fespace->dof(),
873  iterFDim,
874  iterFDim * M_fespace->dof().numTotalDof() );
875  }
876  }
877 
878  M_massRhsAssemblyChrono.stop();
879 }
880 
881 
882 // ===================================================
883 // Set Methods
884 // ===================================================
885 
886 template<typename mesh_type, typename matrix_type, typename vector_type>
887 void
888 ADRAssembler< mesh_type, matrix_type, vector_type>::
889 setFespace (const fespace_ptrType& fespace)
890 {
891  ASSERT (fespace != 0, " Setting the FE space for the unknown to 0 is not permitted ");
892 
893  M_fespace = fespace;
894 
895  M_massCFE.reset (new currentFE_type (M_fespace->refFE(), M_fespace->fe().geoMap(), M_fespace->qr() ) );
896  M_localMass.reset (new localMatrix_type (M_fespace->fe().nbFEDof(),
897  M_fespace->fieldDim(),
898  M_fespace->fieldDim() ) );
899 
900  M_advCFE.reset (new currentFE_type (M_fespace->refFE(), M_fespace->fe().geoMap(), M_fespace->qr() ) );
901  M_localAdv.reset (new localMatrix_type (M_fespace->fe().nbFEDof(),
902  M_fespace->fieldDim(),
903  M_fespace->fieldDim() ) );
904 
905  M_diffCFE.reset (new currentFE_type (M_fespace->refFE(), M_fespace->fe().geoMap(), M_fespace->qr() ) );
906  M_localDiff.reset (new localMatrix_type (M_fespace->fe().nbFEDof(),
907  M_fespace->fieldDim(),
908  M_fespace->fieldDim() ) );
909 
910  M_massRhsCFE.reset (new currentFE_type (M_fespace->refFE(), M_fespace->fe().geoMap(), M_fespace->qr() ) );
911  M_localMassRhs.reset (new localVector_type (M_fespace->fe().nbFEDof(), M_fespace->fieldDim() ) );
912 }
913 
914 template<typename mesh_type, typename matrix_type, typename vector_type>
915 void
916 ADRAssembler< mesh_type, matrix_type, vector_type>::
917 setBetaFespace (const fespace_ptrType& betaFESpace)
918 {
919  ASSERT (M_fespace != 0, " No FE space for the unknown! Use setFespace before setBetaFespace!");
920  ASSERT (M_advCFE != 0, " No current FE set for the advection of the unknown! Internal error.");
921  M_betaFESpace = betaFESpace;
922 
923  M_advBetaCFE.reset (new currentFE_type (M_betaFESpace->refFE(), M_fespace->fe().geoMap(), M_advCFE->quadRule() ) );
924 }
925 
926 
927 } // Namespace LifeV
928 
929 #endif /* ADRASSEMBLER_H */
void start()
Start the timer.
Definition: LifeChrono.hpp:93
void updateInverseJacobian(const UInt &iQuadPt)
Epetra_Import const & importer()
Getter for the Epetra_Import.
Definition: MapEpetra.cpp:394
#define ASSERT(X, A)
Definition: LifeAssert.hpp:90
double Real
Generic real data.
Definition: LifeV.hpp:175
CurrentFE - A primordial class for the assembly of the local matrices/vectors retaining the values on...
Definition: CurrentFE.hpp:243
void stop()
Stop the timer.
Definition: LifeChrono.hpp:100
QuadratureRule - The basis class for storing and accessing quadrature rules.
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191