LifeV
BCManageNormal.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 contains BCManageNormal class for handling normal essential boundary conditions
30 
31  @author Gwenol Grandperrin <gwenol.grandperrin@epfl.ch>
32  @contributor Mauro Perego <perego.mauro@gmail.com>
33  @maintainer Mauro Perego <perego.mauro@gmail.com>
34 
35  @date 12-02-2009
36  *///@HEADER
37 
38 #ifndef BCMANAGENORMAL_H
39 #define BCMANAGENORMAL_H
40 
41 #include <lifev/core/fem/BCHandler.hpp>
42 
43 namespace LifeV
44 {
45 
46 //! BCManageNormal - class for handling normal essential boundary conditions
47 /*!
48  @author Gwenol Grandperrin
49 
50  The purpose of this class is to store the data and provide the methods needed to
51  create the rotation matrix that help to impose normal essential boundary conditions.
52  */
53 
54 
55 template<typename MatrixType>
57 {
58 public:
59 
60  //! @name Public Types
61  //@{
62  typedef std::map<ID, ID> flagsMap_Type;
64  typedef MatrixType matrix_Type;
68 
69  //@}
70 
71 
72  //! @name Constructors & Destructor
73  //@{
74 
75  //! Empty Constructor
77 
78  //! Copy constructor
79  /*!
80  * All the stored data are copied so that the pointers of bcManageNormal and this do not share the same objects
81  @param bcManageNormal BCManageNormal
82  */
83  BCManageNormal ( BCManageNormal const& bcManageNormal );
84 
85 
86  //! Destructor
87  ~BCManageNormal();
88 
89  //@}
90 
91 
92  //! @name Operators
93  //@{
94 
95  //! Assignment operator
96  /*!
97  Stored data are copied so that the pointers of bcManageNormal and of the returned class do not share the same objects
98  @param bcManageNormal BCManageNormal
99  @return Reference to a new BCManageNormal with the same content of bcManageNormal
100  */
101  BCManageNormal& operator= ( const BCManageNormal& bcManageNormal );
102 
103  //@}
104 
105 
106  //! @name Methods
107  //@{
108 
109  //! Store boundary DOFs id and coordinates related to the boundary conditions
110  /*!
111  This method store the coordinates and the flags of the DOFs on the boundary.
112  In the directional case, it will also store the normals.
113  @param boundaryCondition A BCBase object
114  @param time The actual time
115  */
116  void init (const BCBase& boundaryCondition, const Real& time);
117 
118  //! Build the rotation matrix
119  /*!
120  * This method calculates the normal and tangential vectors and builds the rotation matrix
121  @param mesh The mesh
122  @param dof The DOF object
123  @param currentBdFE the current boundary finite element
124  @param systemMatrix The system matrix
125  @param offset The boundary condition offset
126  @param commPtr pointer to Epetra_Comm object
127  */
128  template<typename MeshType>
129  void build (const MeshType& mesh, const DOF& dof, CurrentFEManifold& currentBdFE, const MapEpetra& map, UInt offset);
130 
131  //! This function modify the system matrix to apply a change of basis from the Cartesian coordinate system to the local coordinate system given by tangents and normals to the boundary
132  /*!
133  This method is used to change the basis of the DOF. Then it will be possible to prescribe
134  an Essential boundary condition in the (t1, t2, n) direction by simply prescribing it along the x,y and z axis respectively.
135  In fact it will perform the operations A := R*A*Rt and R*b, where A and be are the system matrix and right hand side,
136  while R is the rotation matrix which transform the Cartesian system into the system of normals and tangents to the boundary.
137  @param systemMatrix the matrix of the problem
138  @param rightHandSide the right hand side
139  */
140  template <typename VectorType>
141  void bcShiftToNormalTangentialCoordSystem (matrix_Type& systemMatrix, VectorType& rightHandSide) const;
142 
143  //! This function modify the system matrix to apply a change of basis from the local coordinate system given by tangents and normals to the boundary to the Cartesian coordinate system
144  /*!
145  This method is used to do the opposite operation of the method bcShiftToNormalTangentialCoordSystem.
146  In fact it will perform the operations A := Rt*A*R and Rt*b, where A and be are the system matrix and right hand side,
147  and R is the rotation matrix which transform the Cartesian system into the system of normals and tangents to the boundary.
148  @param systemMatrix the matrix of the problem
149  @param rightHandSide the right hand side
150  */
151  template <typename VectorType>
152  void bcShiftToCartesianCoordSystem (matrix_Type& systemMatrix, VectorType& rightHandSide) const;
153 
154  //! This method computes the normals to the domain boundary
155  /*!
156  @warning the computed normals can be not compatible with the incompressibility condition
157  @param dof The DOF object containing the local-to-global map
158  @param currentBdFE The current finite element on the boundary
159  @param normals The output vector
160  @param mesh The mesh
161  */
162  template <typename VectorType, typename MeshType>
163  void computeIntegratedNormals (const DOF& dof, CurrentFEManifold& currentBdFE, VectorType& normals, const MeshType& mesh);
164 
165  //! Export in the vtk format the tangential and normal vectors (t1, t2, n) for each DOF on the domain boundary
166  /*!
167  @param fileName The name of the file where the data are exported
168  */
169  void exportToParaview (std::string fileName) const;
170 
171 
172  //@}
173 
174 private:
175 
176  //! @name Private Methods
177  //@{
178  //! stores the coordinates of the mesh vertices involved in the normal boundary conditions
179  /*!
180  @param mesh The mesh
181  */
182  template<typename MeshType>
183  void M_calculateCoordinates (const MeshType& mesh);
184 
185  //! Add point to the map of flags
186  /*!
187  @param ID boundaryCondition A BCBase object
188  @param time The actual time
189  */
190  void M_addBoundaryPoint (const ID& dofId, const ID& flag);
191 
192  //! Add point to the map of flags
193  /*!
194  @param ID dofId The point global id
195  @param nx The x component of the unit vector
196  @param ny The y component of the unit vector
197  @param nz The z component of the unit vector
198  */
199  void M_addVersor (const ID& dofId, const Real& vx, const Real& vy, const Real& vz);
200 
201  //! Calculate the normal vectors
202  /*!
203  @param dof the dof class
204  @param currentBdFE the current boundary finite element
205  */
206  template<typename MeshType>
207  void M_calculateNormals (const MeshType& mesh, const DOF& dof, CurrentFEManifold& currentBdFE);
208 
209  //! Store in *M_normalPtr the versors given by the user
210  /*!
211  This function normalizes the versors in case they are not already normalized
212  */
213  void M_storeGivenVersors();
214 
215  //! Compute the tangential vectors
217 
218  //! This function builds the rotation matrix for the change the basis.
219  /*!
220  @param systemMatrix the matrix of the problem
221  @param offset that will be used if there is more than one unknown to recover the global ID
222  */
223  void M_buildRotationMatrix (const MapEpetra& systemMatrixMap, UInt offset = 0);
224  //@}
225 
226  //! true when there are stored normals
228 
229  //! Shared pointer to the rotation matrix and its transpose
232 
233  //! Shared pointer to the local Map
235 
236  //! Shared pointer to the vector of the first tangents to the domain boundary
238 
239  //! Shared pointer to the vector of the second tangents to the domain boundary
241 
242  //! Shared pointer to the vector of the normals to the domain boundary
244 
245  //! Shared coordinates of the point
247 
248  //! Number of degree of freedom (of one component)
250 
251  //! Number of degree of freedom (of one component) involved in boundary conditions
253 
254  //! flag of the boundary elements
256 
257  //! Versors that are given by the user
259 };
260 
261 //==============================================
262 // IMPLEMENTATION
263 //==============================================
264 
265 //==============================================
266 // Constructors and Destructor
267 //==============================================
268 
269 //Empty Constructor
270 template<typename MatrixType>
272  M_dataBuilt (false),
273  M_numDof (0),
274  M_numInvoledDof (0)
275 {
276  // Nothing to be done here
277 }
278 
279 //Copy Constructor
280 template<typename MatrixType>
281 BCManageNormal<MatrixType>::BCManageNormal ( const BCManageNormal& bcManageNormal ) :
282  M_dataBuilt (bcManageNormal.M_dataBuilt),
283  M_rotationMatrixPtr (new matrix_Type (*bcManageNormal.M_rotationMatrixPtr) ),
289  M_numDof (bcManageNormal.M_numDof),
290  M_numInvoledDof (bcManageNormal.M_numInvoledDof),
291  M_flags (bcManageNormal.M_flags),
292  M_givenVersors (bcManageNormal.M_givenVersors)
293 {
294  // Nothing to be done here
295 }
296 
297 // Destructor.
298 template<typename MatrixType>
300 {
301  // Nothing to be done here
302 }
303 
304 //==============================================
305 // Operators
306 //==============================================
307 
308 // Assignment operator
309 template<typename MatrixType>
310 BCManageNormal<MatrixType>&
311 BCManageNormal<MatrixType>::operator= ( const BCManageNormal& bcManageNormal )
312 {
313  if (this != &bcManageNormal)
314  {
315  M_dataBuilt = bcManageNormal.M_dataBuilt;
316  M_rotationMatrixPtr.reset (new matrix_Type (*bcManageNormal.M_rotationMatrixPtr) );
317  M_localMapEpetraPtr.reset (new MapEpetra (*bcManageNormal.M_localMapEpetraPtr) );
318  M_firstTangentPtr.reset (new VectorEpetra (*bcManageNormal.M_firstTangentPtr) );
319  M_secondTangentPtr.reset (new VectorEpetra (*bcManageNormal.M_secondTangentPtr) );
320  M_normalPtr.reset (new VectorEpetra (*bcManageNormal.M_normalPtr) );
321  M_coordPtr.reset (new VectorEpetra (*bcManageNormal.M_coordPtr) );
322  M_numDof = bcManageNormal.M_numDof;
323  M_numInvoledDof = bcManageNormal.M_numInvoledDof;
324  M_flags = bcManageNormal.M_flags;
325  M_givenVersors = bcManageNormal.M_givenVersors;
326  }
327  return *this;
328 }
329 
330 //==============================================
331 // Methods
332 //==============================================
333 
334 template<typename MatrixType>
335 void BCManageNormal<MatrixType>::init (const BCBase& boundaryCondition, const Real& time)
336 {
337  // Loop on BC identifiers
338  for ( ID i = 0; i < boundaryCondition.list_size(); ++i )
339  {
340  const BCIdentifierEssential* pId = static_cast< const BCIdentifierEssential* > ( boundaryCondition[ i ] );
341 
342  if (boundaryCondition.mode() == Directional)
343  {
344  const BCFunctionDirectional* pBcF = static_cast<const BCFunctionDirectional*> ( boundaryCondition.pointerToFunctor() );
345  Real nx (pBcF->vectFct (time, pId->x(), pId->y(), pId->z(), 0) );
346  Real ny (pBcF->vectFct (time, pId->x(), pId->y(), pId->z(), 1) );
347  Real nz (pBcF->vectFct (time, pId->x(), pId->y(), pId->z(), 2) );
348 
349  M_addVersor (boundaryCondition[i]->id(), nx, ny, nz);
350  }
351  else
352  {
353  M_addBoundaryPoint (boundaryCondition[i]->id(), boundaryCondition.flag() );
354  }
355  }
356  M_dataBuilt = true; //Since vectors has been given we must apply the basis change.
357 }
358 
359 template<typename MatrixType>
360 template<typename MeshType>
361 void BCManageNormal<MatrixType>::build (const MeshType& mesh, const DOF& dof, CurrentFEManifold& currentBdFE, const MapEpetra& map, UInt offset)
362 {
363  if (M_dataBuilt)
364  {
365  //-----------------------------------------------------
366  // STEP 1: Building the map
367  //-----------------------------------------------------
368 
369  //First we build the map
370  UInt nbPoints (M_flags.size() + M_givenVersors.size() );
371  UInt i (0);
372  std::vector<Int> idList (3 * nbPoints); //3 times because we want 3 coordinates
373 
374  //We store the number of Degrees of Freedom
376 
377  //Creating the iterators to explore the maps
378  flagsMap_Type::iterator mapIt;
379  versorsMap_Type::iterator mapIt2;
380 
381  //Building the list
382  for ( mapIt = M_flags.begin() ; mapIt != M_flags.end(); mapIt++ )
383  {
384  idList[i] = (*mapIt).first;
385  idList[i + nbPoints] = (*mapIt).first + M_numDof;
386  idList[i + 2 * nbPoints] = (*mapIt).first + 2 * M_numDof;
387  ++i;
388  }
389  for ( mapIt2 = M_givenVersors.begin() ; mapIt2 != M_givenVersors.end(); mapIt2++ )
390  {
391  idList[i] = (*mapIt2).first;
392  idList[i + nbPoints] = (*mapIt2).first + M_numDof;
393  idList[i + 2 * nbPoints] = (*mapIt2).first + 2 * M_numDof;
394  ++i;
395  }
396 
397  M_localMapEpetraPtr.reset ( new MapEpetra (-1, 3 * nbPoints, &idList[0], map.commPtr() ) );
398 
399  //-----------------------------------------------------
400  // STEP 2: Compute normals and tangents
401  //-----------------------------------------------------
402  M_calculateNormals (mesh, dof, currentBdFE);
404 
405  //this is used only for exporting the normals in vtk format.. should be put elsewhere?
406  M_calculateCoordinates (mesh);
408  M_buildRotationMatrix (map, offset);
409  }
410 }
411 
412 template<typename MatrixType>
413 template <typename VectorType>
414 void BCManageNormal<MatrixType>::bcShiftToNormalTangentialCoordSystem (matrix_Type& systemMatrix, VectorType& rightHandSide) const
415 {
416  if (M_dataBuilt)
417  {
418  //Shift to tangential system
419 
420  //C = R*A
421  matrix_Type C (systemMatrix.map(), systemMatrix.meanNumEntries() );
422  M_rotationMatrixPtr->multiply (false, systemMatrix, false, C);
423 
424  //A = C*Rt"
425  matrix_Type D (systemMatrix.map(), systemMatrix.meanNumEntries() );
426  C.multiply (false, *M_rotationMatrixTransposePtr, false, D);
427  systemMatrix.swapCrsMatrix (D);
428 
429  //b = R*b
430  VectorType c (rightHandSide);
431  M_rotationMatrixPtr->multiply (false, c, rightHandSide);
432  }
433 }
434 
435 template<typename MatrixType>
436 template <typename VectorType>
437 void BCManageNormal<MatrixType>::bcShiftToCartesianCoordSystem (matrix_Type& systemMatrix, VectorType& rightHandSide) const
438 {
439  if (M_dataBuilt)
440  {
441  // C = Rt*A;
442  matrix_Type C (systemMatrix.map(), systemMatrix.meanNumEntries() );
443  M_rotationMatrixTransposePtr->multiply (false, systemMatrix, false, C);
444 
445  // A = C*R";
446  matrix_Type D (systemMatrix.map(), systemMatrix.meanNumEntries() );
447  C.multiply (false, *M_rotationMatrixPtr, false, D);
448  systemMatrix.swapCrsMatrix (D);
449 
450  // b = Rt*b;
451  VectorType c (rightHandSide);
452  M_rotationMatrixTransposePtr->multiply (false, c, rightHandSide);
453  }
454 }
455 
456 template<typename MatrixType>
457 template<typename VectorType, typename MeshType>
458 void BCManageNormal<MatrixType>::computeIntegratedNormals (const DOF& dof, CurrentFEManifold& currentBdFE, VectorType& normals, const MeshType& mesh)
459 {
460 
461  //-----------------------------------------------------
462  // STEP 1: Calculating the normals
463  //-----------------------------------------------------
464 
465  VectorType repNormals (normals.map(), Repeated);
466  //Loop on the Faces
467  for ( UInt iFace = 0; iFace < mesh.numBoundaryFacets(); ++iFace )
468  {
469  //Update the currentBdFE with the face data
470  currentBdFE.update ( mesh.boundaryFacet ( iFace ), UPDATE_NORMALS | UPDATE_W_ROOT_DET_METRIC );
471  UInt nDofF = currentBdFE.nbFEDof();
472 
473  //For each node on the face
474  for (UInt icheck = 0; icheck < nDofF; ++icheck)
475  {
476  ID idf = dof.localToGlobalMapByBdFacet (iFace, icheck);
477 
478  //If the face exists and the point is on this processor
479  if (M_flags.find (idf) != M_flags.end() )
480  {
481  ID flag = M_flags[idf];
482 
483  //if the normal is not already calculated
484  //and the marker correspond to the flag of the point
485  if ( (flag == mesh.boundaryFacet (iFace).markerID() ) || (flag == 0) )
486  {
487  //Warning: the normal is taken in the first Gauss point
488  //since the normal is the same over the triangle
489  //(not true in the case of quadratic and bilinear maps)
490  Real nx (currentBdFE.normal (0, 0) );
491  Real ny (currentBdFE.normal (1, 0) );
492  Real nz (currentBdFE.normal (2, 0) );
493 
494  //We get the area
495  Real area (currentBdFE.measure() );
496 
497  //We update the normal component of the boundary point
498  (repNormals) [idf] += nx * area;
499  (repNormals) [idf + dof.numTotalDof()] += ny * area;
500  (repNormals) [idf + 2 * dof.numTotalDof()] += nz * area;
501  }
502  }
503  }
504  }
505 
506  //-----------------------------------------------------
507  // STEP 2: Gathering the data from others processors
508  //-----------------------------------------------------
509 
510  normals = VectorType (repNormals, Unique);
511 
512  //-----------------------------------------------------
513  // STEP 3: Normalizing the vectors
514  //-----------------------------------------------------
515 
516  //We obtain the ID of the element
517  Int NumMyElements = normals.map().map (Unique)->NumMyElements();
518  std::vector<Int> MyGlobalElements (NumMyElements);
519  normals.map().map (Unique)->MyGlobalElements (& (MyGlobalElements[0]) );
520 
521  //We normalize the normal
522  Real norm;
523  UInt id;
524 
525  //Need to run only over the first third of MyGlobalElements
526  //(the larger values are the y and z components)
527  for ( Int i (0); i < NumMyElements / static_cast<Int> ( nDimensions ); ++i )
528  {
529  id = MyGlobalElements[i];
530  Real nx ( (normals) [id] );
531  Real ny ( (normals) [id + dof.numTotalDof()] );
532  Real nz ( (normals) [id + 2 * dof.numTotalDof()] );
533  norm = std::sqrt ( nx * nx + ny * ny + nz * nz );
534  (normals) [id] /= norm;
535  (normals) [id + dof.numTotalDof()] /= norm;
536  (normals) [id + 2 * dof.numTotalDof()] /= norm;
537  }
538 }
539 
540 //TODO this function can be improved using the vtk writers
541 template<typename MatrixType>
542 void BCManageNormal<MatrixType>::exportToParaview (std::string fileName) const
543 {
544  if (M_dataBuilt)
545  {
546  fileName.append ("_proc");
547  std::ostringstream ossMyPid;
548  ossMyPid << M_localMapEpetraPtr->comm().MyPID();
549  fileName.append ( ossMyPid.str() );
550  fileName.append (".vtk");
551  std::ofstream file (fileName.c_str() );
552 
553  //Is the file open?
554  if (file.fail() )
555  {
556  std::cerr << "Error: The file " << fileName << " is not opened " << std::endl;
557  }
558  else
559  {
560  //We obtain the ID of the element
561  Int NumMyElements = M_localMapEpetraPtr->map (Unique)->NumMyElements();
562  std::vector<Int> MyGlobalElements (NumMyElements);
563  M_localMapEpetraPtr->map (Unique)->MyGlobalElements (&MyGlobalElements[0]);
564  ID idof (0);
565 
566  //Writing the header
567  file << "# vtk DataFile Version 2.0" << std::endl;
568  file << "Normal directions" << std::endl;
569  file << "ASCII" << std::endl;
570 
571  //Writing the points
572  file << "DATASET POLYDATA" << std::endl;
573  file << "POINTS " << M_numInvoledDof << " float" << std::endl;
574 
575  //Need to run only over the first third of MyGlobalElements
576  //(the larger values are the y and z components)
577  for ( Int i (0); i < NumMyElements / static_cast<Int> ( nDimensions ); ++i )
578  {
579  idof = MyGlobalElements[i];
580 
581  file << (*M_coordPtr) [idof] << "\t";
582  file << (*M_coordPtr) [idof + M_numDof] << "\t";
583  file << (*M_coordPtr) [idof + 2 * M_numDof] << std::endl;
584  }
585 
586  //Starting the data part of the file
587  file << "POINT_DATA " << M_numInvoledDof << std::endl;
588 
589  //Writing t1
590  file << "VECTORS cell_tangent_1 float" << std::endl;
591 
592  //Need to run only over the first third of MyGlobalElements
593  //(the larger values are the y and z components)
594  for ( Int i (0); i < NumMyElements / static_cast<Int> ( nDimensions ); ++i )
595  {
596  idof = MyGlobalElements[i];
597 
598  file << (*M_firstTangentPtr) [idof] << "\t";
599  file << (*M_firstTangentPtr) [idof + M_numDof] << "\t";
600  file << (*M_firstTangentPtr) [idof + 2 * M_numDof] << std::endl;
601  }
602 
603  //Writing t2
604  file << "VECTORS cell_tangent_2 float" << std::endl;
605 
606  //Need to run only over the first third of MyGlobalElements
607  //(the larger values are the y and z components)
608  for ( Int i (0); i < NumMyElements / static_cast<Int> ( nDimensions ); ++i )
609  {
610  idof = MyGlobalElements[i];
611 
612  file << (*M_secondTangentPtr) [idof] << "\t";
613  file << (*M_secondTangentPtr) [idof + M_numDof] << "\t";
614  file << (*M_secondTangentPtr) [idof + 2 * M_numDof] << std::endl;
615  }
616 
617  //Writing n
618  file << "VECTORS cell_normals float" << std::endl;
619 
620  //Need to run only over the first third of MyGlobalElements
621  //(the larger values are the y and z components)
622  for ( Int i (0); i < NumMyElements / static_cast<Int> ( nDimensions ); ++i )
623  {
624  idof = MyGlobalElements[i];
625 
626  file << (*M_normalPtr) [idof] << "\t";
627  file << (*M_normalPtr) [idof + M_numDof] << "\t";
628  file << (*M_normalPtr) [idof + 2 * M_numDof] << std::endl;
629  }
630 
631  //Closing the file
632  file.close();
633  }
634  }
635 }
636 
637 //==============================================
638 // Private Methods
639 //==============================================
640 
641 template< typename MatrixType>
642 template< typename MeshType >
643 void BCManageNormal<MatrixType>::M_calculateCoordinates (MeshType const& mesh)
644 {
645  M_coordPtr.reset ( new VectorEpetra (*M_localMapEpetraPtr, Unique) );
646 
647  //We obtain the ID of the element
648  Int NumMyElements = M_localMapEpetraPtr->map (Unique)->NumMyElements();
649  std::vector<Int> MyGlobalElements (NumMyElements);
650  M_localMapEpetraPtr->map (Unique)->MyGlobalElements (&MyGlobalElements[0]);
651 
652  UInt id;
653 
654  //Need to run only over the first third of MyGlobalElements
655  //(the larger values are the y and z components)
656  for ( Int i (0); i < NumMyElements / static_cast<Int> ( nDimensions ); ++i )
657  {
658  id = MyGlobalElements[i];
659 
660  for (UInt j (0); j < mesh.pointList.size(); ++j)
661  {
662  if (id == mesh.pointList[j].id() )
663  {
664  (*M_coordPtr) [id] = mesh.pointList[j].x();
665  (*M_coordPtr) [id + M_numDof] = mesh.pointList[j].y();
666  (*M_coordPtr) [id + 2 * M_numDof] = mesh.pointList[j].z();
667  j = mesh.pointList.size();
668  }
669  }
670  }
671 }
672 
673 template<typename MatrixType>
674 void BCManageNormal<MatrixType>::M_addBoundaryPoint (const ID& idof, const ID& flag)
675 {
676  M_flags.insert (std::pair<ID, ID> (idof, flag) );
677 }
678 
679 
680 template<typename MatrixType>
681 void BCManageNormal<MatrixType>::M_addVersor (const ID& idof, const Real& vx, const Real& vy, const Real& vz)
682 {
683  Vector n (3);
684  n[0] = vx;
685  n[1] = vy;
686  n[2] = vz;
687  M_givenVersors.insert (std::pair<ID, Vector> (idof, n) );
688 }
689 
690 template< typename MatrixType>
691 template< typename MeshType>
692 void BCManageNormal< MatrixType>::M_calculateNormals (const MeshType& mesh, const DOF& dof, CurrentFEManifold& currentBdFE)
693 {
694  //-----------------------------------------------------
695  // STEP 1: Calculating the normals
696  //-----------------------------------------------------
697 
698  M_normalPtr.reset ( new VectorEpetra (*M_localMapEpetraPtr, Repeated) );
699  //(*M_normalPtr)*=0;
700  computeIntegratedNormals (dof, currentBdFE, *M_normalPtr, mesh);
701 
702  //-----------------------------------------------------
703  // STEP 4: Cleaning the memory
704  //-----------------------------------------------------
705 
706  M_flags.clear();
707 }
708 
709 //! Save the imposed normal vectors.
710 template<typename MatrixType>
712 {
713  //-----------------------------------------------------
714  // STEP 1: Retrieve the normals
715  //-----------------------------------------------------
716 
717  //We obtain the ID of the element
718  Int NumMyElements = M_localMapEpetraPtr->map (Unique)->NumMyElements();
719  std::vector<Int> MyGlobalElements (NumMyElements);
720  M_localMapEpetraPtr->map (Unique)->MyGlobalElements (&MyGlobalElements[0]);
721 
722  //We normalize the normal
723  Real norm;
724  UInt id;
725 
726  //Need to run only over the first third of MyGlobalElements
727  //(the larger values are the y and z components)
728  for ( Int i (0); i < NumMyElements / static_cast<Int> ( nDimensions ); ++i )
729  {
730  id = MyGlobalElements[i];
731 
732  if ( M_givenVersors.find (id) != M_givenVersors.end() )
733  {
734  Real nx ( (M_givenVersors) [id][0] );
735  Real ny ( (M_givenVersors) [id][1] );
736  Real nz ( (M_givenVersors) [id][2] );
737  norm = std::sqrt ( nx * nx + ny * ny + nz * nz );
738  (*M_normalPtr) [id] = nx / norm;
739  (*M_normalPtr) [id + M_numDof] = ny / norm;
740  (*M_normalPtr) [id + 2 * M_numDof] = nz / norm;
741  }
742  }
743 
744  //-----------------------------------------------------
745  // STEP 2: Cleaning the memory
746  //-----------------------------------------------------
747 
748  M_givenVersors.clear();
749 }
750 
751 //! Calculate the tangential vectors for each triad in the vector triad.
752 template<typename MatrixType>
754 {
755  //-----------------------------------------------------
756  // STEP 1: Initialization
757  //-----------------------------------------------------
758 
759  //We obtain the ID of the element
760  Int NumMyElements = M_localMapEpetraPtr->map (Unique)->NumMyElements();
761  std::vector<Int> MyGlobalElements (NumMyElements);
762  M_localMapEpetraPtr->map (Unique)->MyGlobalElements (&MyGlobalElements[0]);
763 
764  //Building the tangential vectors
765  M_firstTangentPtr.reset ( new VectorEpetra (*M_localMapEpetraPtr, Unique) );
766  (*M_firstTangentPtr) *= 0;
767  M_secondTangentPtr.reset ( new VectorEpetra (*M_localMapEpetraPtr, Unique) );
768  (*M_secondTangentPtr) *= 0;
769 
770  //We are going to use the loop to count the number
771  //of imposed DOF because since the VectorEpetra is
772  //unique now it is possible that we have less DOF
773  M_numInvoledDof = 0;
774 
775  //-----------------------------------------------------
776  // STEP 2: Calculation of the tangential vectors
777  //-----------------------------------------------------
778 
779  // Real norm;
780  UInt id;
781 
782  //Need to run only over the first third of MyGlobalElements
783  //(the larger values are the y and z components)
784  for ( Int i (0); i < NumMyElements / static_cast<Int> ( nDimensions ); ++i )
785  {
786  id = MyGlobalElements[i];
787 
788  //Counting the number of DOF
789  M_numInvoledDof++;
790 
791  //We take max{|n x i|,|n x j|,|n x k|}
792  // =max{sqrt(ny^2+nz^2),sqrt(nx^2+nz^2),sqrt(nx^2+ny^2)}
793  // =max{r1,r2,r3}
794  Real nx ( (*M_normalPtr) [id] );
795  Real ny ( (*M_normalPtr) [id + M_numDof] );
796  Real nz ( (*M_normalPtr) [id + 2 * M_numDof] );
797  Real nxi = std::sqrt (ny * ny + nz * nz);
798  Real nxj = std::sqrt (nx * nx + nz * nz);
799  Real nxk = std::sqrt (nx * nx + ny * ny);
800 
801  if ( (nxi >= nxj) && (nxi >= nxk) ) //max = |n x i|
802  {
803  //We create t1
804  (*M_firstTangentPtr) [id] = 0;
805  (*M_firstTangentPtr) [id + M_numDof] = nz / nxi;
806  (*M_firstTangentPtr) [id + 2 * M_numDof] = -ny / nxi;
807 
808  //We create t2
809  (*M_secondTangentPtr) [id] = -nxi;
810  (*M_secondTangentPtr) [id + M_numDof] = nx * ny / nxi;
811  (*M_secondTangentPtr) [id + 2 * M_numDof] = nx * nz / nxi;
812  }
813  else if ( (nxj >= nxi) && (nxj >= nxk) ) //max = |n x j|
814  {
815  //We create t1
816  (*M_firstTangentPtr) [id] = -nz / nxj;
817  (*M_firstTangentPtr) [id + M_numDof] = 0;
818  (*M_firstTangentPtr) [id + 2 * M_numDof] = nx / nxj;
819 
820  //We create t2
821  (*M_secondTangentPtr) [id] = nx * ny / nxj;
822  (*M_secondTangentPtr) [id + M_numDof] = -nxj;
823  (*M_secondTangentPtr) [id + 2 * M_numDof] = ny * nz / nxj;
824  }
825  else //max = |n x k|
826  {
827  //We create t1
828  (*M_firstTangentPtr) [id] = ny / nxk;
829  (*M_firstTangentPtr) [id + M_numDof] = -nx / nxk;
830  (*M_firstTangentPtr) [id + 2 * M_numDof] = 0;
831 
832  //We create t2
833  (*M_secondTangentPtr) [id] = nx * nz / nxk;
834  (*M_secondTangentPtr) [id + M_numDof] = ny * nz / nxk;
835  (*M_secondTangentPtr) [id + 2 * M_numDof] = -nxk;
836  }
837  }
838 }
839 
840 template<typename MatrixType>
841 void BCManageNormal<MatrixType>::M_buildRotationMatrix (const MapEpetra& map, UInt offset)
842 {
843  //Initialization of the map to store the normal vectors
844  std::map< ID, std::vector< Real > >::iterator mapIt;
845 
846  //Creating the matrix
847  M_rotationMatrixPtr.reset ( new matrix_Type (map, 3) );
848 
849  //Adding one to the diagonal
850  M_rotationMatrixPtr->insertOneDiagonal();
851 
852  static const Int nbRows (3);
853  static const Int nbCols (3);
854  std::vector<Real*> values (nbCols);
855  Int Indices[3];
856  for ( Int n = 0; n < nbCols; ++n )
857  {
858  values[n] = new Real[nbRows];
859  for ( Int m = 0; m < nbRows; ++m )
860  {
861  values[n][m] = 0.0;
862  }
863  }
864 
865  std::vector<Int> rows;
866  std::vector<Int> cols;
867 
868  //We obtain the ID of the element
869  Int NumMyElements = M_localMapEpetraPtr->map (Unique)->NumMyElements();
870  std::vector<Int> MyGlobalElements (NumMyElements);
871  M_localMapEpetraPtr->map (Unique)->MyGlobalElements (&MyGlobalElements[0]);
872 
873  UInt id;
874 
875  //Need to run only over the first third of MyGlobalElements
876  //(the larger values are the y and z components)
877  for ( Int i (0); i < NumMyElements / static_cast<Int> ( nDimensions ); ++i )
878  {
879  id = MyGlobalElements[i];
880 
881  //...Except for the nodes where we make the rotation
882  //Global Dof
883  //idDof = boundaryCondition( i ) ->id() + boundaryCondition.component( j ) * totalDof;
884  //i,j and k take values in [0,totalDof)
885  Indices[0] = id + offset;
886  Indices[1] = id + M_numDof + offset;
887  Indices[2] = id + 2 * M_numDof + offset;
888 
889  cols.clear();
890  cols.push_back (Indices[0]);
891  cols.push_back (Indices[1]);
892  cols.push_back (Indices[2]);
893 
894  rows.clear();
895  rows.push_back (Indices[0]);
896  rows.push_back (Indices[1]);
897  rows.push_back (Indices[2]);
898 
899  //Line i (first tangential vector)
900  values[0][0] = (*M_firstTangentPtr) [id];
901  values[1][0] = (*M_firstTangentPtr) [id + M_numDof];
902  values[2][0] = (*M_firstTangentPtr) [id + 2 * M_numDof];
903 
904  //-1 because we added one to the diagonal
905  M_rotationMatrixPtr->addToCoefficient (Indices[0], Indices[0], -1.0);
906 
907  //Line j (second tangential vector)
908  values[0][1] = (*M_secondTangentPtr) [id];
909  values[1][1] = (*M_secondTangentPtr) [id + M_numDof];
910  values[2][1] = (*M_secondTangentPtr) [id + 2 * M_numDof];
911 
912  //-1 because we added one to the diagonal
913  M_rotationMatrixPtr->addToCoefficient (Indices[1], Indices[1], -1.0);
914 
915  //Line k (normal vector)
916  values[0][2] = (*M_normalPtr) [id];
917  values[1][2] = (*M_normalPtr) [id + M_numDof];
918  values[2][2] = (*M_normalPtr) [id + 2 * M_numDof];
919 
920  //-1 because we added one to the diagonal
921  M_rotationMatrixPtr->addToCoefficient (Indices[2], Indices[2], -1.0);
922 
923  M_rotationMatrixPtr->addToCoefficients (nbCols, nbRows, cols, rows, &values[0]);
924  }
925 
926  for ( Int n = 0; n < nbRows; ++n )
927  {
928  delete[] values[n];
929  }
930 
931  M_rotationMatrixPtr->globalAssemble();
932  M_rotationMatrixTransposePtr = M_rotationMatrixPtr->transpose();
933 }
934 
935 } //end of namespace LifeV
936 
937 #endif // BCMANAGENORMAL_H
epetraVectorPtr_type M_secondTangentPtr
Shared pointer to the vector of the second tangents to the domain boundary.
const flag_Type UPDATE_NORMALS(UPDATE_ONLY_NORMALS|UPDATE_ONLY_TANGENTS|UPDATE_ONLY_CELL_NODES)
epetraVectorPtr_type M_firstTangentPtr
Shared pointer to the vector of the first tangents to the domain boundary.
~BCManageNormal()
Destructor.
std::shared_ptr< matrix_Type > matrixPtr_Type
void computeIntegratedNormals(const DOF &dof, CurrentFEManifold &currentBdFE, VectorType &normals, const MeshType &mesh)
This method computes the normals to the domain boundary.
const Real & y() const
Recovering the node&#39;s y-coordinate.
void M_buildRotationMatrix(const MapEpetra &systemMatrixMap, UInt offset=0)
This function builds the rotation matrix for the change the basis.
void M_storeGivenVersors()
Store in *M_normalPtr the versors given by the user.
Real measure() const
Compute the measure of the current element.
const Real & z() const
Recovering the node&#39;s z-coordinate.
A class for a finite element on a manifold.
void bcShiftToCartesianCoordSystem(matrix_Type &systemMatrix, VectorType &rightHandSide) const
This function modify the system matrix to apply a change of basis from the local coordinate system gi...
std::map< ID, Vector > versorsMap_Type
bcFlag_Type flag() const
Returns the flag associated to the boundary condition name.
Definition: BCBase.cpp:712
Real vectFct(const Real &t, const Real &x, const Real &y, const Real &z, const ID &component) const
Evaluate the versors&#39; function.
Definition: BCFunction.hpp:751
int32_type Int
Generic integer data.
Definition: LifeV.hpp:188
BCManageNormal & operator=(const BCManageNormal &bcManageNormal)
Assignment operator.
UInt M_numInvoledDof
Number of degree of freedom (of one component) involved in boundary conditions.
epetraVectorPtr_type M_coordPtr
Shared coordinates of the point.
void updateInverseJacobian(const UInt &iQuadPt)
void bcShiftToNormalTangentialCoordSystem(matrix_Type &systemMatrix, VectorType &rightHandSide) const
This function modify the system matrix to apply a change of basis from the Cartesian coordinate syste...
BCManageNormal - class for handling normal essential boundary conditions.
std::shared_ptr< VectorEpetra > epetraVectorPtr_type
std::map< ID, ID > flagsMap_Type
matrixPtr_Type M_rotationMatrixTransposePtr
Epetra_Import const & importer()
Getter for the Epetra_Import.
Definition: MapEpetra.cpp:394
void M_addBoundaryPoint(const ID &dofId, const ID &flag)
Add point to the map of flags.
uint32_type ID
IDs.
Definition: LifeV.hpp:194
Real normal(UInt coordinate, UInt quadNode) const
Values of the normal on the quadrature points.
bcMode_Type mode() const
Returns the boundary condition mode.
Definition: BCBase.cpp:722
epetraMapPtr_Type M_localMapEpetraPtr
Shared pointer to the local Map.
const UInt & numTotalDof() const
The total number of Dof.
Definition: DOF.hpp:177
versorsMap_Type M_givenVersors
Versors that are given by the user.
void build(const MeshType &mesh, const DOF &dof, CurrentFEManifold &currentBdFE, const MapEpetra &map, UInt offset)
Build the rotation matrix.
void M_calculateNormals(const MeshType &mesh, const DOF &dof, CurrentFEManifold &currentBdFE)
Calculate the normal vectors.
double Real
Generic real data.
Definition: LifeV.hpp:175
std::shared_ptr< MapEpetra > epetraMapPtr_Type
void M_addVersor(const ID &dofId, const Real &vx, const Real &vy, const Real &vz)
Add point to the map of flags.
flagsMap_Type M_flags
flag of the boundary elements
const flag_Type UPDATE_W_ROOT_DET_METRIC(UPDATE_ONLY_W_ROOT_DET_METRIC|UPDATE_METRIC|UPDATE_ONLY_DET_METRIC)
BCManageNormal()
Empty Constructor.
ID localToGlobalMapByBdFacet(const ID &facetId, const ID &localDof) const
Definition: DOF.cpp:81
const BCIdentifierBase * operator[](const ID &i) const
Returns a pointer to the (i)-th element of the list of identifiers.
Definition: BCBase.cpp:638
const ID & id() const
Returns the ID of the BCIdentifier.
BCFunctionUDepBase - class that holds the function used for prescribing boundary conditions.
Definition: BCFunction.hpp:683
BCManageNormal(BCManageNormal const &bcManageNormal)
Copy constructor.
const UInt nDimensions(NDIM)
BCIdentifierEssential - BCIdentifier for implementing Essential Boundary Conditions.
void M_calculateTangentVectors()
Compute the tangential vectors.
matrixPtr_Type M_rotationMatrixPtr
Shared pointer to the rotation matrix and its transpose.
const Real & x() const
Recovering the node&#39;s x-coordinate.
UInt M_numDof
Number of degree of freedom (of one component)
const BCFunctionBase * pointerToFunctor() const
Returns a pointer to the BCFunctionBase object.
Definition: BCBase.cpp:528
epetraVectorPtr_type M_normalPtr
Shared pointer to the vector of the normals to the domain boundary.
void M_calculateCoordinates(const MeshType &mesh)
stores the coordinates of the mesh vertices involved in the normal boundary conditions ...
UInt list_size() const
Returns the size of the identifiers list.
Definition: BCBase.cpp:551
std::vector< std::shared_ptr< BCIdentifierBase > > M_idVector
container for id&#39;s when the list is finalized
Definition: BCBase.hpp:647
void exportToParaview(std::string fileName) const
Export in the vtk format the tangential and normal vectors (t1, t2, n) for each DOF on the domain bou...
uint32_type UInt
generic unsigned integer (used mainly for addressing)
Definition: LifeV.hpp:191
void init(const BCBase &boundaryCondition, const Real &time)
Store boundary DOFs id and coordinates related to the boundary conditions.
bool M_dataBuilt
true when there are stored normals