LifeV
ETCurrentFE_FD3.hpp
Go to the documentation of this file.
1 ///*!
2 // ETCurrenteFE is a template class.
3 // This is the non-specialized class used with fieldDim = 3 or 2 (using faster VectorSmall return objects)
4 //
5 // */
6 
7 template< UInt spaceDim, UInt fieldDim >
8 class ETCurrentFE
9 {
10 
11  //! @name Friends
12  //@{
13 
14  //!Friend to allow direct access to the raw data
15  template< UInt dim >
16  friend class ExpressionAssembly::EvaluationPhiI;
17 
18  //!Friend to allow direct access to the raw data
19  template< UInt dim >
20  friend class ExpressionAssembly::EvaluationPhiJ;
21 
22  //!Friend to allow direct access to the raw data
23  template< UInt dim, UInt FSpaceDim >
24  friend class ExpressionAssembly::EvaluationDphiI;
25 
26  //!Friend to allow direct access to the raw data
27  template< UInt dim, UInt FSpaceDim >
28  friend class ExpressionAssembly::EvaluationDphiJ;
29 
30  //!Friend to allow direct access to the raw data
31  template< UInt dim, UInt FSpaceDim >
32  friend class ExpressionAssembly::EvaluationDivI;
33 
34  //!Friend to allow direct access to the raw data
35  template< UInt dim, UInt FSpaceDim >
36  friend class ExpressionAssembly::EvaluationDivJ;
37 
38  //!Friend to allow direct access to the raw data
39  template< UInt dim, UInt FSpaceDim >
40  friend class ExpressionAssembly::EvaluationLaplacianI;
41 
42  //!Friend to allow direct access to the raw data
43  template< UInt dim, UInt FSpaceDim >
44  friend class ExpressionAssembly::EvaluationLaplacianJ;
45 
46  //@}
47 
48 private:
49 
50  // Vector return type for phi
51  typedef VectorSmall< fieldDim > array1D_Return_Type;
52 
53  // Matrix return type for dphi
54  typedef MatrixSmall< fieldDim, spaceDim > matrix_Return_Type;
55 
56  //Private typedefs for the 2D array of vector
57  typedef std::vector< std::vector< array1D_Return_Type > > array2D_vector_Type;
58 
59  //Private typedefs for the 3D array of vector
60  typedef std::vector< std::vector< matrix_Return_Type > > array2D_matrix_Type;
61 
62  //Private typedefs for the laplacian
63  typedef std::vector< std::vector< std::vector <matrix_Return_Type > > > array_3D_matrix_Type;
64 
65  // Typedefs for the second derivative
66  typedef MatrixSmall< spaceDim, spaceDim > matrix_d2Phi;
67  typedef std::vector< std::vector< std::vector< matrix_d2Phi > > > array_d2Phi;
68 
69 public:
70 
71  //! @name Static constants
72  //@{
73 
74  //! Static value for the space dimension
75  static const UInt S_spaceDimension; // = spaceDim;
76 
77  //! Static value for the dimension of the field (fieldDim here as it is a vectorial FE)
78  static const UInt S_fieldDimension; // = fieldDim;
79 
80  //@}
81 
82  //! @name Constructors, destructor
83  //@{
84 
85  //! Full constructor
86  /*!
87  @param refFE The reference element for the FE
88  @param geoMap The geometric map from the reference element to the current element
89  @param qr The quadrature rule
90  */
91  ETCurrentFE (const ReferenceFE& refFE, const GeometricMap& geoMap, const QuadratureRule& qr);
92 
93  //! Constructor without quadrature rule
94  /*!
95  @param refFE The reference element for the FE
96  @param geoMap The geometric map from the reference element to the current element
97  */
98  ETCurrentFE (const ReferenceFE& refFE, const GeometricMap& geoMap);
99 
100  //! Copy constructor
101  /*!
102  @param otherFE The currentFE to be copied
103  */
104  ETCurrentFE (const ETCurrentFE<spaceDim, fieldDim>& otherFE);
105 
106  //! Destructor
107  virtual ~ETCurrentFE();
108 
109  //@}
110 
111  //! @name Methods
112  //@{
113 
114  //! Update method
115  /*!
116  The update method computes the required quantities (indicated by the flag,
117  see in \ref Update_flag) on the element.
118 
119  @param element The current element were to compute the values
120  @param flag The flag indicating the quantities to update
121 
122  <b>Template parameters</b>
123 
124  <i>elementType</i>: The type of the element
125 
126  <b>Template requirements</b>
127 
128  <i>elementType</i>: has a id() method returning the identifier (global); has a localId() method returning
129  the identifier (local); has a method point(UInt i) that returns the ith point.
130  */
131  template<typename elementType>
132  void update (const elementType& element, const flag_Type& flag);
133 
134  //! ShowMe method
135  /*!
136  @param out Output stream were to print the informations
137  */
138  void showMe (std::ostream& out = std::cout) const;
139 
140  //@}
141 
142  //! @name Set Methods
143  //@{
144 
145  //! Setter for the quadrature rule
146  /*!
147  Beware that when this setter is called, all the internal
148  structures have to be reshaped (according to the number
149  of quadrature nodes).
150 
151  @param qr The new quadrature to use.
152  */
153  void setQuadratureRule (const QuadratureRule& qr);
154 
155  //@}
156 
157  //! @name Get Methods
158  //@{
159 
160  //! Getter for the number of degrees of freedom of this element
161  /*!
162  @return The number of number of degrees of freedom of this element
163  */
164  UInt nbFEDof() const
165  {
166  return M_nbFEDof;
167  }
168 
169  //! Getter for the values of the basis functions in the quadrature nodes in the current element
170  /*!
171  @param i The index of the basis function
172  @param q The index of the quadrature node
173  @return The vector<3> of the ith basis function in the qth quadrature node
174  */
175  const array1D_Return_Type& phi (const UInt& i, const UInt& q) const
176  {
177  ASSERT ( i < fieldDim * M_nbFEDof, "No basis function with this index" );
178  ASSERT ( q < M_nbQuadPt, "No quadrature point with this index" );
179 
180  return ( M_phi[q][i] );
181  }
182 
183  //! Getter for the coordinates of the quadrature nodes in the current element
184  /*!
185  @param q The index of the quadrature node
186  @param coord The coordinate required
187  @return The coordth component of the coordinate of the qth quadrature point
188  */
189  Real quadNode (const UInt& q, const UInt& coord) const
190  {
191  ASSERT ( M_isQuadNodeUpdated, "Quadrature nodes have not been updated");
192  ASSERT ( q < M_nbQuadPt, "No quadrature point with this index");
193  ASSERT ( coord < spaceDim, "No such coordinate index");
194  return M_quadNode[q][coord];
195  }
196 
197  //! Getter for the weighted jacobian determinant (current element)
198  /*!
199  @param q The index of the quadrature point
200  @return The weighted determinant of the jacobian transform in the qth quadrature node
201  */
202  Real wDet (const UInt& q) const
203  {
204  ASSERT ( M_isWDetUpdated, "Weighted determinant has not been updated");
205  ASSERT ( q < M_nbQuadPt, "No quadrature point with this index");
206  return M_wDet[q];
207  }
208 
209  //! Getter for the derivatives of the basis function in the quadrature nodes (current element)
210  /*!
211  @param i The index of the basis function
212  @param iCoor The component of the basis function to be derived
213  @param dxi The direction of the derivative required (0 for d/dx, 1 for d/dy...)
214  @param q The index of the quadrature node
215  @return The iCoor component of the ith basis function derived w.r. to dxi, in the qth quadrature node.
216  */
217  const Real& dphi (const UInt& i, const UInt& iCoor, const UInt& dxi, const UInt& q) const
218  {
219  ASSERT ( M_isDphiUpdated, "Derivative of the basis functions have not been updated");
220  ASSERT ( i < fieldDim * M_nbFEDof, "No basis function with this index");
221  ASSERT ( iCoor < fieldDim, "No such coordinate index");
222  ASSERT ( dxi < spaceDim, "No such coordinate index");
223  ASSERT ( q < M_nbQuadPt, "No quadrature point with this index");
224 
225  return M_dphi[q][i][iCoor][dxi];
226  }
227 
228  //! Getter for the derivatives of the basis function in the quadrature nodes (current element)
229  /*!
230  @param i The index of the basis function
231  @param q The index of the quadrature node
232  @return The local vector of the basis functions derived w.r. to dxi, in the qth quadrature node.
233  */
234  MatrixSmall<spaceDim, 3> const& dphi (const UInt& i, const UInt& q) const
235  {
236  ASSERT ( M_isDphiUpdated, "Derivative of the basis functions have not been updated");
237  ASSERT ( i < 3 * M_nbFEDof, "No basis function with this index");
238  ASSERT ( q < M_nbQuadPt, "No quadrature point with this index");
239  return M_dphi[q][i];
240  }
241 
242  //! Getter for the divergence of the basis functions in the quadrature nodes in the current element
243  /*!
244  @param i The index of the basis function
245  @param q The index of the quadrature node
246  @return The divergence of the ith basis function in the qth quadrature node
247  */
248  const array1D_Return_Type& divergence (const UInt& i, const UInt& q) const
249  {
250  ASSERT ( M_isDivergenceUpdated, "Divergence of the basis functions have not been updated");
251  ASSERT ( i < fieldDim * M_nbFEDof, "No basis function with this index" );
252  ASSERT ( q < M_nbQuadPt, "No quadrature point with this index" );
253 
254  return ( M_divergence[q][i] );
255  }
256 
257 
258  //! Getter for the laplacian of the basis functions in the quadrature nodes in the current element
259  /*!
260  @param i The index of the basis function
261  @param q The index of the quadrature node
262  @return The divergence of the ith basis function in the qth quadrature node
263  */
264  const VectorSmall<fieldDim>& laplacian (const UInt& i, const UInt& q) const
265  {
266  ASSERT ( M_isLaplacianUpdated, "Divergence of the basis functions have not been updated");
267  ASSERT ( i < fieldDim * M_nbFEDof, "No basis function with this index" );
268  ASSERT ( q < M_nbQuadPt, "No quadrature point with this index" );
269 
270  return ( M_laplacian[q][i] );
271  }
272 
273  //! Getter for the identifier of the current element
274  /*!
275  @return The (global) identifier of the current element.
276  */
277  UInt currentId() const
278  {
279  ASSERT (M_isCellNodeUpdated, "Cell has not been updated");
280  return M_currentId;
281  }
282 
283  //@}
284 
285 private:
286 
287  //Private typedefs for the 1D array
288  typedef std::vector< Real > array1D_Type;
289 
290  //Private typedefs for the 2D array (array of 1D array)
291  typedef std::vector< array1D_Type > array2D_Type;
292 
293  //Private typedefs for the 3D array (array of 2D array)
294  typedef std::vector< array2D_Type > array3D_Type;
295 
296  typedef std::vector< std::vector< array1D_Return_Type > > arrayLaplacian_Type;
297 
298  //Private typedefs for the 4D array (array of 3D array)
299  typedef std::vector< array3D_Type > array4D_Type;
300 
301  //! @name Private Methods
302  //@{
303 
304  //! No default constructor
305  ETCurrentFE();
306 
307  //! No assignement
308  void operator= ( const ETCurrentFE< spaceDim, fieldDim >& );
309 
310  //! Resize all the internal containers w.r. to the stored data and compute the constant values
311  void setupInternalConstants();
312 
313  //! Update the cell nodes
314  template< typename ElementType >
315  void updateCellNode (const ElementType& element);
316 
317  //! Update the quadrature nodes
318  void updateQuadNode (const UInt& iQuadPt);
319 
320  //! Update Jacobian
321  void updateJacobian (const UInt& iQuadPt);
322 
323  //! Update DetJacobian
324  void updateDetJacobian ( const UInt& iQuadPt );
325 
326  //! Update InverseJacobian
327  void updateInverseJacobian ( const UInt& iQuadPt );
328 
329  //! Update WeightedJacobian
330  void updateWDet ( const UInt& iQuadPt );
331 
332  //! Update Dphi
333  void updateDphi ( const UInt& iQuadPt );
334 
335  //! Update D2phi
336  void updateD2phi ( const UInt& iQuadPt );
337 
338  //! Update Divergence
339  void updateDivergence (const UInt& iQuadPt);
340 
341  //! Update Laplacian
342  void updateLaplacian ( const UInt& iQuadPt);
343 
344 
345  //@}
346 
347  // Pointer on the reference FE
348  const ReferenceFE* M_referenceFE;
349  // Pointer on the geometric map
350  const GeometricMap* M_geometricMap;
351  // Pointer on the quadrature rule
352  const QuadratureRule* M_quadratureRule;
353 
354  // Number of FE dof (current element)
355  UInt M_nbFEDof;
356  // Number of dof for the geometric map
357  UInt M_nbMapDof;
358  // Number of quadrature point
359  UInt M_nbQuadPt;
360 
361  // Global identifier
362  UInt M_currentId;
363  // Local identifier
364  UInt M_currentLocalId;
365 
366  // Storage for the values of the basis functions
367  array2D_vector_Type M_phi;
368 
369  // Storage for the values of the geometric map
370  array2D_Type M_phiMap;
371  // Storage for the derivatives of the basis functions
372  array3D_Type M_dphiReferenceFE;
373  // Storage for the derivatives of the geometric map
374  array3D_Type M_dphiGeometricMap;
375  // Storage for the second derivatives of the basis functions
376  array4D_Type M_d2phiReferenceFE;
377 
378  // Storage for the coordinates of the nodes of the current element
379  array2D_Type M_cellNode;
380  // Storage for the position the quadrature nodes (current element)
381  array2D_Type M_quadNode;
382  // Storage for the jacobian of the transformation
383  array3D_Type M_jacobian;
384  // Storage for the determinant of the jacobian of the transformation
385  array1D_Type M_detJacobian;
386  // Storage for the weighted determinant
387  array1D_Type M_wDet;
388  // Storage for the inverse of the jacobian
389  array3D_Type M_tInverseJacobian;
390 
391  // Storage for the derivative of the basis functions
392  array2D_matrix_Type M_dphi;
393  // Storage for the divergence of the basis functions
394  array2D_Type M_divergence;
395 
396  // Storage for the second derivative of the basis functions
397  array_d2Phi M_d2phi;
398 
399  // Storage for the laplacian of the basis functions
400  arrayLaplacian_Type M_laplacian;
401 
402 
403 #ifdef HAVE_LIFEV_DEBUG
404  // Debug informations, defined only if the code
405  // is compiled in debug mode. These booleans store the
406  // information about what the last call to "update"
407  // has actually computed (names are self explanatory)
408  bool M_isCellNodeUpdated;
409  bool M_isQuadNodeUpdated;
410  bool M_isJacobianUpdated;
411  bool M_isDetJacobianUpdated;
412  bool M_isInverseJacobianUpdated;
413  bool M_isWDetUpdated;
414  bool M_isPhiUpdated;
415  bool M_isDphiUpdated;
416  bool M_isDivergenceUpdated;
417  bool M_isD2phiUpdated;
418  bool M_isLaplacianUpdated;
419 #endif
420 
421 };
422 
423 // ===================================================
424 // IMPLEMENTATION
425 // ===================================================
426 
427 template< UInt spaceDim, UInt fieldDim >
428 const UInt ETCurrentFE< spaceDim, fieldDim >::S_spaceDimension = spaceDim;
429 
430 template< UInt spaceDim, UInt fieldDim >
431 const UInt ETCurrentFE< spaceDim, fieldDim >::S_fieldDimension = fieldDim;
432 
433 // ===================================================
434 // Constructors & Destructor
435 // ===================================================
436 
437 template< UInt spaceDim, UInt fieldDim >
438 ETCurrentFE<spaceDim, fieldDim>::
439 ETCurrentFE (const ReferenceFE& refFE, const GeometricMap& geoMap, const QuadratureRule& qr)
440  :
441  M_referenceFE (&refFE),
442  M_geometricMap (&geoMap),
443  M_quadratureRule (&qr),
444 
445  M_nbFEDof (M_referenceFE->nbDof() ),
446  M_nbMapDof (M_geometricMap->nbDof() ),
447  M_nbQuadPt (M_quadratureRule->nbQuadPt() ),
448 
449  M_currentId(),
450  M_currentLocalId(),
451 
452  M_phi(),
453  M_phiMap(),
454  M_dphiReferenceFE(),
455  M_d2phiReferenceFE(),
456  M_dphiGeometricMap(),
457 
458  M_cellNode(),
459  M_quadNode(),
460  M_jacobian(),
461  M_detJacobian(),
462  M_wDet(),
463  M_tInverseJacobian(),
464  M_dphi(),
465  M_divergence(),
466  M_d2phi(),
467  M_laplacian()
468 
469 #ifdef HAVE_LIFEV_DEBUG
470  , M_isCellNodeUpdated (false),
471  M_isQuadNodeUpdated (false),
472  M_isJacobianUpdated (false),
473  M_isDetJacobianUpdated (false),
474  M_isInverseJacobianUpdated (false),
475  M_isWDetUpdated (false),
476  M_isPhiUpdated (false),
477  M_isDphiUpdated (false),
478  M_isDivergenceUpdated (false),
479  M_isD2phiUpdated (false),
480  M_isLaplacianUpdated (false)
481 #endif
482 
483 {
484  // Everything's there, so reshape the arrays
485  setupInternalConstants();
486 }
487 
488 template< UInt spaceDim, UInt fieldDim >
489 ETCurrentFE<spaceDim, fieldDim>::
490 ETCurrentFE (const ReferenceFE& refFE, const GeometricMap& geoMap)
491  :
492  M_referenceFE (&refFE),
493  M_geometricMap (&geoMap),
494  M_quadratureRule (0),
495 
496  M_nbFEDof (M_referenceFE->nbDof() ),
497  M_nbMapDof (M_geometricMap->nbDof() ),
498  M_nbQuadPt (0),
499 
500  M_currentId(),
501  M_currentLocalId(),
502 
503  M_phi(),
504  M_phiMap(),
505  M_dphiReferenceFE(),
506  M_d2phiReferenceFE(),
507  M_dphiGeometricMap(),
508 
509  M_cellNode(),
510  M_quadNode(),
511  M_jacobian(),
512  M_detJacobian(),
513  M_wDet(),
514  M_tInverseJacobian(),
515  M_dphi(),
516  M_divergence(),
517 
518  M_d2phi(),
519  M_laplacian()
520 
521 #ifdef HAVE_LIFEV_DEBUG
522  , M_isCellNodeUpdated (false),
523  M_isQuadNodeUpdated (false),
524  M_isJacobianUpdated (false),
525  M_isDetJacobianUpdated (false),
526  M_isInverseJacobianUpdated (false),
527  M_isWDetUpdated (false),
528  M_isPhiUpdated (false),
529  M_isDphiUpdated (false),
530  M_isDivergenceUpdated (false),
531  M_isD2phiUpdated (false),
532  M_isLaplacianUpdated (false)
533 #endif
534 
535 {
536  // Miss the QR, so no reshape
537 }
538 
539 template< UInt spaceDim, UInt fieldDim >
540 ETCurrentFE<spaceDim, fieldDim>::
541 ETCurrentFE (const ETCurrentFE<spaceDim, fieldDim>& otherFE)
542  :
543  M_referenceFE (otherFE.M_referenceFE),
544  M_geometricMap (otherFE.M_geometricMap),
545  M_quadratureRule (otherFE.M_quadratureRule),
546 
547  M_nbFEDof (otherFE.M_nbFEDof),
548  M_nbMapDof (otherFE.M_nbMapDof),
549  M_nbQuadPt (otherFE.M_nbQuadPt),
550 
551  M_currentId (otherFE.M_currentId),
552  M_currentLocalId (otherFE.M_currentLocalId),
553 
554  M_phi (otherFE.M_phi),
555  M_phiMap (otherFE.M_phiMap),
556  M_dphiReferenceFE (otherFE.M_dphiReferenceFE),
557  M_d2phiReferenceFE (otherFE.M_d2phiReferenceFE),
558  M_dphiGeometricMap (otherFE.M_dphiGeometricMap),
559 
560  M_cellNode (otherFE.M_cellNode),
561  M_quadNode (otherFE.M_quadNode),
562  M_jacobian (otherFE.M_jacobian),
563  M_detJacobian (otherFE.M_detJacobian),
564  M_wDet (otherFE.M_wDet),
565  M_tInverseJacobian (otherFE.M_tInverseJacobian),
566  M_dphi (otherFE.M_dphi),
567  M_divergence (otherFE.M_divergence),
568 
569  M_d2phi (otherFE.M_d2phi),
570  M_laplacian (otherFE.M_laplacian)
571 
572 #ifdef HAVE_LIFEV_DEBUG
573  //Beware for the comma at the begining of this line!
574  , M_isCellNodeUpdated ( otherFE.M_isCellNodeUpdated ),
575  M_isQuadNodeUpdated ( otherFE.M_isQuadNodeUpdated ),
576  M_isJacobianUpdated ( otherFE.M_isJacobianUpdated ),
577  M_isDetJacobianUpdated ( otherFE.M_isDetJacobianUpdated ),
578  M_isInverseJacobianUpdated ( otherFE.M_isInverseJacobianUpdated ),
579  M_isWDetUpdated ( otherFE.M_isWDetUpdated ),
580  M_isPhiUpdated ( otherFE.M_isPhiUpdated ),
581  M_isDphiUpdated ( otherFE.M_isDphiUpdated ),
582  M_isDivergenceUpdated ( otherFE.M_isDivergenceUpdated ),
583  M_isD2phiUpdated ( otherFE.M_isD2phiUpdated ),
584  M_isLaplacianUpdated ( otherFE.M_isLaplacianUpdated )
585 #endif
586 
587 {}
588 
589 template< UInt spaceDim, UInt fieldDim >
590 ETCurrentFE<spaceDim, fieldDim>::
591 ~ETCurrentFE()
592 {}
593 
594 // ===================================================
595 // Methods
596 // ===================================================
597 
598 template< UInt spaceDim, UInt fieldDim >
599 template<typename elementType>
600 void
601 ETCurrentFE<spaceDim, fieldDim>::
602 update (const elementType& element, const flag_Type& flag)
603 {
604  ASSERT (M_referenceFE != 0, "No reference FE for the update");
605  ASSERT (M_geometricMap != 0, "No geometric mapping for the update");
606  ASSERT (M_quadratureRule != 0, "No quadrature rule for the update");
607 
608 #ifdef HAVE_LIFEV_DEBUG
609  // Reset all the flags to false
610  M_isCellNodeUpdated = false;
611  M_isQuadNodeUpdated = false;
612  M_isJacobianUpdated = false;
613  M_isDetJacobianUpdated = false;
614  M_isInverseJacobianUpdated = false;
615  M_isWDetUpdated = false;
616  M_isDphiUpdated = false;
617  M_isDivergenceUpdated = false;
618  M_isD2phiUpdated = false;
619  M_isLaplacianUpdated = false;
620 #endif
621 
622  // update the cell informations if required
623  if (flag & ET_UPDATE_ONLY_CELL_NODE)
624  {
625  updateCellNode (element);
626  }
627 
628  // Loop over the quadrature nodes
629  for (UInt i (0); i < M_nbQuadPt; ++i)
630  {
631  // and update the required quantities
632  if ( flag & ET_UPDATE_ONLY_QUAD_NODE )
633  {
634  updateQuadNode (i);
635  }
636  if ( flag & ET_UPDATE_ONLY_JACOBIAN )
637  {
638  updateJacobian (i);
639  }
640  if ( flag & ET_UPDATE_ONLY_DET_JACOBIAN )
641  {
642  updateDetJacobian (i);
643  }
644  if ( flag & ET_UPDATE_ONLY_T_INVERSE_JACOBIAN )
645  {
646  updateInverseJacobian (i);
647  }
648  if ( flag & ET_UPDATE_ONLY_W_DET_JACOBIAN )
649  {
650  updateWDet (i);
651  }
652  if ( flag & ET_UPDATE_ONLY_DPHI )
653  {
654  updateDphi (i);
655  }
656  if ( flag & ET_UPDATE_ONLY_DIVERGENCE )
657  {
658  updateDivergence (i);
659  }
660  if ( flag & ET_UPDATE_ONLY_D2PHI )
661  {
662  updateD2phi (i);
663  }
664  if ( flag & ET_UPDATE_ONLY_LAPLACIAN )
665  {
666  updateLaplacian (i);
667  }
668  }
669 }
670 
671 template< UInt spaceDim, UInt fieldDim >
672 void
673 ETCurrentFE<spaceDim, fieldDim>::
674 showMe (std::ostream& out) const
675 {
676  out << " Number of FE Dof : " << M_nbFEDof << std::endl;
677  out << " Number of Map Dof : " << M_nbMapDof << std::endl;
678  out << " Number of QR point : " << M_nbQuadPt << std::endl;
679  out << std::endl;
680 
681  out << " Cell Nodes : " << std::endl;
682  for ( UInt i (0); i < M_nbMapDof; ++i )
683  {
684  for ( UInt icoor (0); icoor < S_spaceDimension; ++icoor)
685  {
686  out << M_cellNode[i][icoor] << " ";
687  }
688  out << std::endl;
689  }
690  out << std::endl;
691 
692  out << " Jacobian : " << std::endl;
693  for (UInt iQuad (0); iQuad < M_nbQuadPt; ++iQuad)
694  {
695  for (UInt iDim (0); iDim < S_spaceDimension; ++iDim)
696  {
697  for (UInt jDim (0); jDim < S_spaceDimension; ++jDim)
698  {
699  out << M_jacobian[iQuad][iDim][jDim] << " ";
700  }
701  out << std::endl;
702  }
703  out << std::endl;
704  }
705 
706  out << " Det jacobian : " << std::endl;
707  for (UInt iQuad (0); iQuad < M_nbQuadPt; ++iQuad)
708  {
709  out << M_detJacobian[iQuad] << " ";
710  }
711  out << std::endl;
712 
713  out << " T inverse Jacobian : " << std::endl;
714  for (UInt iQuad (0); iQuad < M_nbQuadPt; ++iQuad)
715  {
716  for (UInt iDim (0); iDim < S_spaceDimension; ++iDim)
717  {
718  for (UInt jDim (0); jDim < S_spaceDimension; ++jDim)
719  {
720  out << M_tInverseJacobian[iQuad][iDim][jDim] << " ";
721  }
722  out << std::endl;
723  }
724  out << std::endl;
725  }
726 
727  out << " DPhi : " << std::endl;
728  for (UInt iQuad (0); iQuad < M_nbQuadPt; ++iQuad)
729  {
730  for (UInt iDof (0); iDof < M_nbFEDof; ++iDof)
731  {
732  for (UInt iCoor (0); iCoor < S_spaceDimension; ++iCoor)
733  {
734  for (UInt jCoor (0); jCoor < S_spaceDimension; ++jCoor)
735  {
736  out << M_dphi[iQuad][iDof][iCoor][jCoor] << " ";
737  }
738  }
739  out << std::endl;
740  }
741  out << std::endl;
742  }
743 
744  out << " Divergence : " << std::endl;
745  for (UInt iQuad (0); iQuad < M_nbQuadPt; ++iQuad)
746  {
747  for (UInt iDof (0); iDof < fieldDim * M_nbFEDof; ++iDof)
748  {
749  out << M_divergence[iQuad][iDof] << " ";
750  }
751  out << std::endl;
752  }
753 
754 }
755 
756 // ===================================================
757 // Set Methods
758 // ===================================================
759 
760 template< UInt spaceDim, UInt fieldDim >
761 void
762 ETCurrentFE<spaceDim, fieldDim>::
763 setQuadratureRule (const QuadratureRule& qr)
764 {
765  M_quadratureRule = &qr;
766  M_nbQuadPt = qr.nbQuadPt();
767  setupInternalConstants();
768 }
769 
770 // ===================================================
771 // Private Methods
772 // ===================================================
773 
774 template< UInt spaceDim, UInt fieldDim >
775 void
776 ETCurrentFE<spaceDim, fieldDim>::
777 setupInternalConstants()
778 {
779  // The first group of values can be computed as it
780  // it does not depend on the current element
781 
782  // PHI
783  M_phi.resize ( M_nbQuadPt );
784  for ( UInt q ( 0 ); q < M_nbQuadPt; ++q )
785  {
786  // we have M_nbFEDof * 3 basis functions
787  M_phi[q].resize ( M_nbFEDof * 3 );
788 
789  // set only appropriate values, other are initialized to 0 by default constructor (of VectorSmall)
790  for ( UInt j ( 0 ); j < M_nbFEDof; ++j )
791  {
792  M_phi[q][j][0] = M_referenceFE->phi ( j, M_quadratureRule->quadPointCoor ( q ) );
793 
794  // copy other values according to the vectorial basis functions
795  for ( UInt k ( 1 ); k < S_fieldDimension; ++k )
796  {
797  M_phi[q][k * M_nbFEDof + j][k] = M_phi[q][j][0];
798  }
799  }
800  }
801 #ifdef HAVE_LIFEV_DEBUG
802  M_isPhiUpdated = true;
803 #endif
804 
805  // PHI MAP
806  M_phiMap.resize (M_nbQuadPt);
807  for (UInt q (0); q < M_nbQuadPt; ++q)
808  {
809  M_phiMap[q].resize (M_nbMapDof);
810  for (UInt i (0); i < M_nbMapDof; ++i)
811  {
812  M_phiMap[q][i] = M_geometricMap->phi (i, M_quadratureRule->quadPointCoor (q) );
813  }
814  }
815 
816  // DPHIREFERENCEFE
817  M_dphiReferenceFE.resize (M_nbQuadPt);
818  for (UInt q (0); q < M_nbQuadPt; ++q)
819  {
820  M_dphiReferenceFE[q].resize (M_nbFEDof);
821  for (UInt i (0); i < M_nbFEDof; ++i)
822  {
823  M_dphiReferenceFE[q][i].resize (spaceDim);
824  for (UInt j (0); j < spaceDim; ++j)
825  {
826  M_dphiReferenceFE[q][i][j] = M_referenceFE->dPhi (i, j, M_quadratureRule->quadPointCoor (q) );
827  }
828  }
829  }
830 
831  // DPHIGEOMETRICMAP
832  M_dphiGeometricMap.resize (M_nbQuadPt);
833  for (UInt q (0); q < M_nbQuadPt; ++q)
834  {
835  M_dphiGeometricMap[q].resize (M_nbMapDof);
836  for (UInt i (0); i < M_nbMapDof; ++i)
837  {
838  M_dphiGeometricMap[q][i].resize (spaceDim);
839  for (UInt j (0); j < spaceDim; ++j)
840  {
841  M_dphiGeometricMap[q][i][j] = M_geometricMap->dPhi (i, j, M_quadratureRule->quadPointCoor (q) );
842  }
843  }
844  }
845 
846 
847  // D2PHIREFERENCEFE
848  M_d2phiReferenceFE.resize (M_nbQuadPt);
849  for (UInt q (0); q < M_nbQuadPt; ++q)
850  {
851  M_d2phiReferenceFE[q].resize (M_nbFEDof);
852  for (UInt i (0); i < M_nbFEDof; ++i)
853  {
854  M_d2phiReferenceFE[q][i].resize (spaceDim);
855  for (UInt j (0); j < spaceDim; ++j)
856  {
857  M_d2phiReferenceFE[q][i][j].resize (spaceDim);
858  for (UInt k (0); k < spaceDim; ++k)
859  {
860  M_d2phiReferenceFE[q][i][j][k] = M_referenceFE->d2Phi (i, j, k, M_quadratureRule->quadPointCoor (q) );
861  }
862  }
863  }
864  }
865 
866  // The second group of values cannot be computed
867  // now because it depends on the current element.
868  // So, we just make space for it.
869  // Cell nodes
870  M_cellNode.resize (M_nbMapDof);
871  for (UInt i (0); i < M_nbMapDof; ++i)
872  {
873  M_cellNode[i].resize (spaceDim);
874  }
875 
876  // Quad nodes
877  M_quadNode.resize (M_nbQuadPt);
878  for (UInt i (0); i < M_nbQuadPt; ++i)
879  {
880  M_quadNode[i].resize (spaceDim);
881  }
882 
883  // Jacobian
884  M_jacobian.resize (M_nbQuadPt);
885  for (UInt i (0); i < M_nbQuadPt; ++i)
886  {
887  M_jacobian[i].resize (spaceDim);
888  for (UInt j (0); j < spaceDim; ++j)
889  {
890  M_jacobian[i][j].resize (spaceDim);
891  }
892  }
893 
894  // Det jacobian
895  M_detJacobian.resize (M_nbQuadPt);
896 
897  // wDet
898  M_wDet.resize (M_nbQuadPt);
899 
900  // tInverseJacobian
901  M_tInverseJacobian.resize (M_nbQuadPt);
902  for (UInt i (0); i < M_nbQuadPt; ++i)
903  {
904  M_tInverseJacobian[i].resize (spaceDim);
905  for (UInt j (0); j < spaceDim; ++j)
906  {
907  M_tInverseJacobian[i][j].resize (spaceDim);
908  }
909  }
910 
911  // dphi
912  M_dphi.resize (M_nbQuadPt);
913  for (UInt i (0); i < M_nbQuadPt; ++i)
914  {
915  // we have fieldDim * DoF basis functions
916  M_dphi[i].resize ( fieldDim * M_nbFEDof );
917  }
918 
919  // divergence
920  M_divergence.resize (M_nbQuadPt);
921  for (UInt i (0); i < M_nbQuadPt; ++i)
922  {
923  // we have fieldDim * DoF basis functions
924  M_divergence[i].resize ( fieldDim * M_nbFEDof );
925  }
926 
927  // d2phi
928  M_d2phi.resize (M_nbQuadPt);
929  for (UInt i (0); i < M_nbQuadPt; ++i)
930  {
931  // we have fieldDim * DoF basis functions
932  M_d2phi[i].resize ( fieldDim * M_nbFEDof );
933 
934  // for each basis function we have fieldDim
935  for (UInt j (0); j < ( fieldDim * M_nbFEDof ); ++j)
936  {
937  M_d2phi[i][j].resize(fieldDim);
938  }
939  }
940 
941  // laplacian
942  M_laplacian.resize (M_nbQuadPt);
943  for (UInt i (0); i < M_nbQuadPt; ++i)
944  {
945  // we have fieldDim * DoF basis functions
946  M_laplacian[i].resize ( fieldDim * M_nbFEDof );
947  }
948 }
949 
950 template <UInt spaceDim, UInt fieldDim >
951 void
952 ETCurrentFE<spaceDim, fieldDim>::
953 updateQuadNode (const UInt& iQuadPt)
954 {
955  // Check the requirements
956  ASSERT (M_isCellNodeUpdated, "Cell must be updated to compute the quadrature node position");
957 
958  // Set the check boolean
959 #ifdef HAVE_LIFEV_DEBUG
960  M_isQuadNodeUpdated = true;
961 #endif
962 
963  for (UInt iDim (0); iDim < S_spaceDimension; ++iDim)
964  {
965  M_quadNode[iQuadPt][iDim] = 0.0;
966 
967  for (UInt iDof (0); iDof < M_nbMapDof; ++iDof)
968  {
969  M_quadNode[iQuadPt][iDim] += M_cellNode[iDof][iDim] * M_phiMap[iQuadPt][iDof];
970  }
971  }
972 }
973 
974 template< UInt spaceDim, UInt fieldDim >
975 void
976 ETCurrentFE<spaceDim, fieldDim>::
977 updateJacobian (const UInt& iQuadPt)
978 {
979  // Check the requirements
980  ASSERT (M_isCellNodeUpdated, "Cell must be updated to compute the jacobian");
981 
982  // Set the check boolean
983 #ifdef HAVE_LIFEV_DEBUG
984  M_isJacobianUpdated = true;
985 #endif
986 
987  Real partialSum (0.0);
988  for (UInt iDim (0); iDim < S_spaceDimension; ++iDim)
989  {
990  for (UInt jDim (0); jDim < S_spaceDimension; ++jDim)
991  {
992  partialSum = 0.0;
993  for (UInt iterNode (0); iterNode < M_nbMapDof; ++iterNode)
994  {
995  partialSum += M_cellNode[iterNode][iDim] * M_dphiGeometricMap[iQuadPt][iterNode][jDim];
996  }
997 
998  M_jacobian[iQuadPt][iDim][jDim] = partialSum;
999  }
1000  }
1001 }
1002 
1003 template< UInt spaceDim, UInt fieldDim >
1004 void ETCurrentFE< spaceDim, fieldDim >::updateWDet ( const UInt& iQuadPt )
1005 {
1006  ASSERT ( M_isDetJacobianUpdated,
1007  "Determinant of the jacobian must be updated to compute WDet" );
1008 
1009 #ifdef HAVE_LIFEV_DEBUG
1010  M_isWDetUpdated = true;
1011 #endif
1012 
1013  M_wDet[iQuadPt] = M_detJacobian[iQuadPt] * M_quadratureRule->weight ( iQuadPt );
1014 }
1015 
1016 template< UInt spaceDim, UInt fieldDim >
1017 void ETCurrentFE< spaceDim, fieldDim >::updateDphi ( const UInt& iQuadPt )
1018 {
1019  ASSERT ( M_isInverseJacobianUpdated,
1020  "Inverse jacobian must be updated to compute the derivative of the basis functions" );
1021 
1022 #ifdef HAVE_LIFEV_DEBUG
1023  M_isDphiUpdated = true;
1024 #endif
1025 
1026  Real partialSum ( 0.0 );
1027 
1028 // std::cout << "\n-------- DPHI BEGIN -------\n";
1029 
1030  for ( UInt iDof ( 0 ); iDof < M_nbFEDof; ++iDof )
1031  {
1032  for ( UInt iCoor ( 0 ); iCoor < S_spaceDimension; ++iCoor )
1033  {
1034  partialSum = 0.0;
1035  for ( UInt jCoor ( 0 ); jCoor < S_spaceDimension; ++jCoor )
1036  {
1037  partialSum += M_tInverseJacobian[iQuadPt][iCoor][jCoor] * M_dphiReferenceFE[iQuadPt][iDof][jCoor];
1038  }
1039 
1040  // set only appropriate values, other are initialized to 0 by default constructor (of VectorSmall)
1041  M_dphi[iQuadPt][iDof][0][iCoor] = partialSum;
1042 
1043 // std::cout << "Matrix of dof " << iDof << " equal to " << M_dphi[iQuadPt][iDof];
1044 // std::cout << "\n";
1045 
1046  // copy other values according to the vectorial basis functions
1047  for ( UInt k ( 1 ); k < fieldDim; ++k)
1048  {
1049 // std::cout << "Matrix of dof " << iDof + k * M_nbFEDof << " equal to ";
1050  M_dphi[iQuadPt][k * M_nbFEDof + iDof][k][iCoor] = partialSum;
1051 // std::cout << M_dphi[iQuadPt][k * M_nbFEDof + iDof];
1052  }
1053  }
1054 // std::cout << "\n---------------\n";
1055  }
1056 // std::cout << "\n-------- DPHI END -------\n";
1057 }
1058 
1059 template< UInt spaceDim, UInt fieldDim >
1060 void ETCurrentFE< spaceDim, fieldDim >::updateDivergence ( const UInt& iQuadPt )
1061 {
1062  ASSERT ( M_isDphiUpdated,
1063  "Basis function derivatives must be updated to compute the divergence" );
1064 
1065 #ifdef HAVE_LIFEV_DEBUG
1066  M_isDivergenceUpdated = true;
1067 #endif
1068 
1069  Real partialSum ( 0.0 );
1070 
1071 // std::cout << "\n-------- DIVERGENCE BEGIN -------\n";
1072 
1073  for ( UInt iDof ( 0 ); iDof < fieldDim * M_nbFEDof; ++iDof )
1074  {
1075  partialSum = 0.0;
1076  for ( UInt iCoor ( 0 ); iCoor < S_spaceDimension; ++iCoor ) // for me here it is possible to improve performances, this for is not needed
1077  {
1078  partialSum += M_dphi[iQuadPt][iDof][iCoor][iCoor];
1079  }
1080  M_divergence[iQuadPt][iDof] = partialSum;
1081 // std::cout << "Divergence of dof " << iDof << " equal to ";
1082 // std::cout << M_divergence[iQuadPt][iDof];
1083 // std::cout << "\n---------------\n";
1084 
1085  }
1086 
1087 // std::cout << "\n-------- DIVERGENCE END -------\n";
1088 }
1089 
1090 template< UInt spaceDim, UInt fieldDim >
1091 void ETCurrentFE< spaceDim, fieldDim >::updateD2phi ( const UInt& iQuadPt )
1092 {
1093  ASSERT ( M_isInverseJacobianUpdated,
1094  "Inverse jacobian must be updated to compute the derivative of the basis functions" );
1095 
1096 #ifdef HAVE_LIFEV_DEBUG
1097  M_isD2phiUpdated = true;
1098 #endif
1099 
1100  Real partialSum ( 0.0 );
1101 
1102  for ( UInt iDof ( 0 ); iDof < M_nbFEDof; ++iDof )
1103  {
1104  for ( UInt iCoor ( 0 ); iCoor < S_spaceDimension; ++iCoor )
1105  {
1106  for ( UInt jCoor ( 0 ); jCoor < S_spaceDimension; ++jCoor )
1107  {
1108  partialSum = 0.0;
1109  for ( UInt k1 (0); k1 < S_spaceDimension; ++k1 )
1110  {
1111  for ( UInt k2 (0) ; k2 < S_spaceDimension; ++k2 )
1112  {
1113  partialSum += M_tInverseJacobian[iQuadPt][iCoor][k1]
1114  * M_d2phiReferenceFE[iQuadPt][iDof][k1][k2]
1115  * M_tInverseJacobian[iQuadPt][jCoor][k2];
1116  }
1117  }
1118 
1119  // set only appropriate values, other are initialized to 0 by default constructor (of VectorSmall)
1120  M_d2phi[iQuadPt][iDof][0][iCoor][jCoor] = partialSum;
1121 
1122  // copy other values according to the vectorial basis functions
1123  for ( UInt k ( 1 ); k < fieldDim; ++k)
1124  {
1125  M_d2phi[iQuadPt][k * M_nbFEDof + iDof][k][iCoor][jCoor] = partialSum;
1126  }
1127  }
1128  }
1129  }
1130 }
1131 
1132 template< UInt spaceDim, UInt fieldDim >
1133 void ETCurrentFE< spaceDim, fieldDim >::updateLaplacian ( const UInt& iQuadPt )
1134 {
1135  ASSERT ( M_isD2phiUpdated,
1136  "Basis function second derivatives must be updated to compute the laplacian" );
1137 
1138 #ifdef HAVE_LIFEV_DEBUG
1139  M_isLaplacianUpdated = true;
1140 #endif
1141 
1142  Real partialSum ( 0.0 );
1143 
1144  for ( UInt iDof ( 0 ); iDof < M_nbFEDof; ++iDof )
1145  {
1146  for ( UInt k ( 0 ); k < fieldDim; ++k )
1147  {
1148  partialSum = 0.0;
1149  for ( UInt iCoor ( 0 ); iCoor < S_spaceDimension; ++iCoor )
1150  {
1151  partialSum += M_d2phi[iQuadPt][iDof][k][iCoor][iCoor];
1152  }
1153 
1154  M_laplacian[iQuadPt][iDof][k] = partialSum;
1155 
1156  // copy other values according to the vectorial basis functions
1157  for ( UInt k ( 1 ); k < fieldDim; ++k)
1158  {
1159  M_laplacian[iQuadPt][k * M_nbFEDof + iDof][k] = M_laplacian[iQuadPt][iDof][0];
1160  }
1161  }
1162  }
1163 }
1164 
1165 template< UInt spaceDim, UInt fieldDim >
1166 template< typename ElementType >
1167 void
1168 ETCurrentFE<spaceDim, fieldDim>::
1169 updateCellNode (const ElementType& element)
1170 {
1171 
1172 #ifdef HAVE_LIFEV_DEBUG
1173  M_isCellNodeUpdated = true;
1174 #endif
1175 
1176  M_currentId = element.id();
1177  M_currentLocalId = element.localId();
1178 
1179  for ( UInt i (0); i < M_nbMapDof; ++i )
1180  {
1181  for ( UInt icoor (0); icoor < S_spaceDimension; ++icoor)
1182  {
1183  M_cellNode[i][icoor] = element.point (i).coordinate (icoor);
1184  }
1185  }
1186 }
GeometricMap - Structure for the geometrical mapping.
const Real & weight(const UInt &ig) const
weight(ig) is the ig-th quadrature weight
friend class ExpressionAssembly::EvaluationLaplacianJ
Friend to allow direct access to the raw data.
uint32_type flag_Type
bit-flag with up to 32 different flags
Definition: LifeV.hpp:197
friend class ExpressionAssembly::EvaluationPhiI
Friend to allow direct access to the raw data.
Real dPhi(UInt i, UInt icoor, const GeoVector &v) const
return the value of the icoor-th derivative of the i-th basis function on point v ...
friend class ExpressionAssembly::EvaluationDphiI
Friend to allow direct access to the raw data.
const GeoVector & quadPointCoor(const UInt &ig) const
quadPointCoor(ig) is the full coordinates of the quadrature point ig
#define ASSERT(X, A)
Definition: LifeAssert.hpp:90
const UInt & nbDof() const
Return the number of degrees of freedom for this reference element.
double Real
Generic real data.
Definition: LifeV.hpp:175
friend class ExpressionAssembly::EvaluationLaplacianI
Friend to allow direct access to the raw data.
The class for a reference Lagrangian finite element.
friend class ExpressionAssembly::EvaluationDphiJ
Friend to allow direct access to the raw data.
QuadratureRule - The basis class for storing and accessing quadrature rules.
Real phi(UInt i, const GeoVector &v) const
Return the value of the i-th basis function in the point v.
friend class ExpressionAssembly::EvaluationPhiJ
Friend to allow direct access to the raw data.
const UInt & nbQuadPt() const
Getter for the number of quadrature points.
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191